avatar

Derek Zeng

Loneliness is the gift of life

自制电台播放器

我平时喜欢听电台广播。以前在新加坡上中学住宿舍的时候我就买了一个大家伙,它可以放广播,也可以放CD。 学习之余都是这个家伙陪伴着我。我最喜欢的电台是Yes 93.3,新加坡最受年轻人欢迎的音乐电台。经常可以听到 我喜欢的港台新歌手比如梁静茹,林俊杰的歌。这么多年过去了,它的风格没有太大变化。对于我来说这是好事情, 毕竟现在的新歌(手)都不如老歌(手)。

离开新加坡好几年了,时不时还会在网络上听Yes 93.3。由于时差,早上的节目跟晚上的颠倒,我时常想,如果 可以调整这个时差,早上听早上的节目多好。

其实现在电台广播可以在网络上streaming,给许多开发者带来了很多可利用的机会。比如这个小伙子就用raspberry pi 做了一个radio player, https://github.com/yeokm1/pi-radio

这样简单的项目网上很多,基本上都是利用mplayer解码radio stream来播放,然后用gpio来控制pi显示和输入。

其实作为web developer我知道,媒体解码这个,HTML5 media API都已经做的很不错了,而且是跨平台的。 完全可以在浏览器里实现。如果希望做成app,也可以用electron或cordora来包装一下,就很好用了。

回到之前我听Yes 93.3有时差的问题,我想如果我可以buffer 12个小时的radio stream,这样就有24小时 的差距。虽然是一整天但也实现了早上听早上的节目,晚上听晚上的节目的目标。想要buffer stream,得要有 一个程序可以读stream。

研究了一下,一般radio stream 都用SHOUTcast格式。这种格式除了可以stream音乐,还可以发送当前节目的 标题和一些meta信息。用SHOUTcast server还可以动态穿插广告在节目中来让播放者赚钱。之前我用过的一款 安卓应用tuneIn就是经常放广告,我挺受不了的。还好新加坡的一些电台都不需要这样。

SHOUTcast是跑在TCP上面的,所以用socket就可以链接上了。Stream媒体一旦链接上就不会主动断开,所以 它会一直占用资源。Stream是以二维码的形式传输,其中文字和媒体文件的编码会混合在一起,我依照这个 文章里的方法将他们剥离

但这是有一个很重要的问题,buffer 12个小时的数据可能需要很多储存空间。如果一首歌算2MB,3分钟。那么12 小时需要的容量=20首歌/小时 × 12 × 2 MB = 480MB。这是一个电台的。我还得做一个streaming server 来重头发送这个stream,同时之前的socket不停的向尾部添加新的数据。

这听起来可以作为我后续的项目。但现在,我可以先做一个自己的电台播放器。自己的UI,没有广告。这个 其实要简单些。电台音频数据可以直接在浏览器里用audio API 来播放,比较复杂的就是我需要有一个websocket server来push 当前播放节目的信息。

我照着 mozilla 网站 用java实现了一个简单的符合我自己需求的Websocket server。配合我的radio streaming client,我 现在可以推送歌曲名字到浏览器了。

在浏览器里,我用angular实现了一个简单的UI。顺便用Audio API 实现了一个音频视觉的动画效果。如下图。

这个播放器不只是Yes 93.3,任何提供streaming 的电台都可以放到这个list。灰常爽!

Demo http://radio.derekzeng.me

(End of article)