Featured image of post WebRTC 音乐播放器

WebRTC 音乐播放器

image-20251113110517168

背景

规定要求采用服务端播放音乐,所以要在服务端实现并提供播放器的能力。

一个房间只能有一个音乐播放器,且由房间拥有者控制,房间拥有者退出房间,则播放器销毁。

需求收集

播放器有哪些功能??

  • 音乐文件上传预检
  • 添加到播放队列
  • 从播放队列移除 ( 不影响当前播放的音乐正常播放 )
  • 清除播放队列( 不影响当前播放的音乐正常播放 )
  • 上一首/下一首
  • 暂停/播放
  • 循环模式: 顺序播放/单曲循环/队列循环
  • 设置音量大小 ( 服务端实现此功能较为复杂,后续将重点说明 )
  • 获取播放状态(播放进度/播放模式)
  • 查询播放队列
  • 插播
  • 播放器销毁

功能说明

音乐文件上传预检

提供上传预检接口,采用基于内容指纹的秒传机制,判断音乐文件是否存在,若命中缓存则复用已有资源,跳过实际数据传输环节,从而降低上行带宽消耗,减少存储冗余,音乐更快的响应到用户的耳朵。

另外也是校验文件的完整性,文件损坏则响应提示给调用者。

添加到播放队列

image-20251113151507852

播放队列的生命周期随房间拥有者操作而创建,房间拥有者离开则销毁,仅提供队列能力。

根据上传预检的结果,判断是否需要上传音乐文件,如果携带音乐文件,会持久化到临时存储,作为转码任务的输入源,系统立即触发音频转码任务,最后将音乐的元数据添加到指定房间的播放器队列中。

在播放过程中,可以提前将音乐添加到队列的队尾。

正在播放的音乐不受影响,当队列为空时,添加到播放队列则立即播放此音乐

播放采用异步缓冲架构,防止音频受指令时间影响造成的卡顿。

除了首次操作添加会自动播放,其余播放是暂停状态时,添加队列依然维持暂停播放状态,所以移动端可以尽管缓冲队列,不会让用户产生明明暂停了,却莫名其妙的又开始播放。

从播放队列移除

可以将音乐从播放队列移除,此后将不会再播放该音乐。

将正在播放的音乐从队列移除,会导致指针与所播放的音乐不同步问题,那此时操作"上一首"是未移除之前的上一首还是上上一首呢? 为保障播放过程中的原子性和状态一致性,禁止移除正在播放的音乐。

注意,移除当前播放音乐之前的索引,其指针位置需要变动,避免播放的是 a 音乐,指针跑到 b 音乐上的状态不一致问题。

清除播放队列

可以将全部音乐从播放队列移除。

注意,正在播放的音乐不受影响,当前播放完后自动停止。

上一首

如果在队列中确实存在上一首,则立即播放上一首。

如果当前已经是队首,则重新播放该音乐。

暂停状态下,可以切换,但不会播放,需要播放可以与播放组合使用。

下一首

如果在队列中确实存在下一首,则立即播放下一首。

顺序播放模式 和 单曲循环模式下,如果当前已经是队尾,则不会做任何操作。

队列循环播放模式下,如果当前已经是队尾,则会跳到队首播放。

暂停状态下,可以切换,但不会播放,需要播放可以与播放组合使用。

暂停/播放

如果播放队列为空,一切保持暂停状态。

如果是暂停状态,则播放。

如果是播放状态,则暂停。

循环模式: 顺序播放/单曲循环/队列循环

顺序播放,按照播放队列依次的播放,播放完自动停止,该模式是默认模式。

单曲循环,按照当前播放的歌曲,无限循环。

队列循环,按照顺序播放,播放完后回到队首,开始新的一轮顺序播放,循环往复。

设置音量大小

音量 1~10,根据音量调整音乐的大小,客户端应避免在 1 秒内连续调整调用接口。

这个功能对于服务端有一定复杂度,音量的播放在是客户端,客户端可以设定声音,服务端如何控制客户端的声音呢??

再次明确背景,此设计是基于服务端!! 站在服务端的角度实现功能!!! 在不打破规则的前提下,只能重新编解码音频文件,控制音频增益。

采用异步实时编码,对 PCM 做音量增益,封装成 opus 音频流,优点是操作跟手,调整音量后能尽快感知到音量变化。

缺点是占用运行内存和硬盘存储较高,比方案一多 10 倍存储量,每个编码任务占用 20MB 左右内存。

获取播放状态

查询播放进度,播放状态,播放模式

查询播放队列

查询播放队列和当前播放位置

插播

如果想播放的音乐在队尾,要播放到指定音乐要等 20 分钟,是播放器先着急还是用户先着急?

插播就是为了解决这个问题,可以将指定音乐插入到 “下一首” 位置。

插播不会中断当前播放。

播放器销毁

音乐由房间拥有者播放,房间拥有者退出房间播放器自动销毁。就好比房间拥有者带着音响离开了,房间内不应该余音绕梁三日不绝。

尽快销毁播放器,有助于资源回收,提升资源利用率。

验证测试

  1. ✅️在播放或暂停状态中,清空播放队列,是指除了当前正在播放的都清空

  2. ✅️在顺序播放完时,清空播放队列,是指清除全部

  3. ✅️移除上一首音乐,上一首,即 1,2,3 移除 2 播放 1

  4. ✅️移除下一首音乐,下一首,即 2,3,4 移除 3 播放 4

  5. ✅️设置单曲循环时,上一首/下一首,测试表现应为上一首直到队首,下一首直到队尾

  6. ✅️设置队列循环时,上一首/下一首,测试表现应为上一首直到队首,下一首可以循环队列。

  7. ✅️设置顺序播放时,上一首/下一首,测试表现与单曲循环效果相同

  8. ✅️顺序播放结束,自动暂停,触发播放,应从队首重新开始

  9. ✅️暂停 5 分钟后,触发播放,还在之前停止的位置继续播放

  10. ✅️不在播放中,且队列没有音乐时,触发播放将响应提示

  11. ✅️添加音乐到队列中,首次添加时自动触发播放,非首次添加,保持旧的播放状态

  12. ✅️重复添加相同音乐到队列中,响应提示

  13. ✅️处理在未知的房间播放音乐,响应提示

  14. ✅️房间拥有者离开/房间内没人/主动调用接口,三者任意结可销毁音乐播放器

  15. ✅️插播正在播放的歌曲,当前播放 A 插播 A,此操作不可行,响应提示。

  16. ✅️队列为空时,下一首,此操作不可行,响应提示

  17. ✅️同一文件多次上传,预检应命中,复用资源

  18. ✅️播放器销毁后继续调用播放接口,应返回 “播放器不存在” 错误

  19. ✅️播放进度查询精度,是否准确表达出音频播放位置

以上是单元测试,还有集成测试项依赖测试环境,不一一列举。

本文阅读量 次, 总访问量 ,总访客数
Built with Hugo .   Theme Stack designed by Jimmy