
背景
规定要求采用服务端播放音乐,所以要在服务端实现并提供播放器的能力。
一个房间只能有一个音乐播放器,且由房间拥有者控制,房间拥有者退出房间,则播放器销毁。
需求收集
播放器有哪些功能??
- 音乐文件上传预检
- 添加到播放队列
- 从播放队列移除 ( 不影响当前播放的音乐正常播放 )
- 清除播放队列( 不影响当前播放的音乐正常播放 )
- 上一首/下一首
- 暂停/播放
- 循环模式: 顺序播放/单曲循环/队列循环
- 设置音量大小 ( 服务端实现此功能较为复杂,后续将重点说明 )
- 获取播放状态(播放进度/播放模式)
- 查询播放队列
- 插播
- 播放器销毁
功能说明
音乐文件上传预检
提供上传预检接口,采用基于内容指纹的秒传机制,判断音乐文件是否存在,若命中缓存则复用已有资源,跳过实际数据传输环节,从而降低上行带宽消耗,减少存储冗余,音乐更快的响应到用户的耳朵。
另外也是校验文件的完整性,文件损坏则响应提示给调用者。
添加到播放队列

播放队列的生命周期随房间拥有者操作而创建,房间拥有者离开则销毁,仅提供队列能力。
根据上传预检的结果,判断是否需要上传音乐文件,如果携带音乐文件,会持久化到临时存储,作为转码任务的输入源,系统立即触发音频转码任务,最后将音乐的元数据添加到指定房间的播放器队列中。
在播放过程中,可以提前将音乐添加到队列的队尾。
正在播放的音乐不受影响,当队列为空时,添加到播放队列则立即播放此音乐。
播放采用异步缓冲架构,防止音频受指令时间影响造成的卡顿。
除了首次操作添加会自动播放,其余播放是暂停状态时,添加队列依然维持暂停播放状态,所以移动端可以尽管缓冲队列,不会让用户产生明明暂停了,却莫名其妙的又开始播放。
从播放队列移除
可以将音乐从播放队列移除,此后将不会再播放该音乐。
将正在播放的音乐从队列移除,会导致指针与所播放的音乐不同步问题,那此时操作"上一首"是未移除之前的上一首还是上上一首呢? 为保障播放过程中的原子性和状态一致性,禁止移除正在播放的音乐。
注意,移除当前播放音乐之前的索引,其指针位置需要变动,避免播放的是 a 音乐,指针跑到 b 音乐上的状态不一致问题。
清除播放队列
可以将全部音乐从播放队列移除。
注意,正在播放的音乐不受影响,当前播放完后自动停止。
上一首
如果在队列中确实存在上一首,则立即播放上一首。
如果当前已经是队首,则重新播放该音乐。
暂停状态下,可以切换,但不会播放,需要播放可以与播放组合使用。
下一首
如果在队列中确实存在下一首,则立即播放下一首。
顺序播放模式 和 单曲循环模式下,如果当前已经是队尾,则不会做任何操作。
队列循环播放模式下,如果当前已经是队尾,则会跳到队首播放。
暂停状态下,可以切换,但不会播放,需要播放可以与播放组合使用。
暂停/播放
如果播放队列为空,一切保持暂停状态。
如果是暂停状态,则播放。
如果是播放状态,则暂停。
循环模式: 顺序播放/单曲循环/队列循环
顺序播放,按照播放队列依次的播放,播放完自动停止,该模式是默认模式。
单曲循环,按照当前播放的歌曲,无限循环。
队列循环,按照顺序播放,播放完后回到队首,开始新的一轮顺序播放,循环往复。
设置音量大小
音量 1~10,根据音量调整音乐的大小,客户端应避免在 1 秒内连续调整调用接口。
这个功能对于服务端有一定复杂度,音量的播放在是客户端,客户端可以设定声音,服务端如何控制客户端的声音呢??
再次明确背景,此设计是基于服务端!! 站在服务端的角度实现功能!!! 在不打破规则的前提下,只能重新编解码音频文件,控制音频增益。
采用异步实时编码,对 PCM 做音量增益,封装成 opus 音频流,优点是操作跟手,调整音量后能尽快感知到音量变化。
缺点是占用运行内存和硬盘存储较高,比方案一多 10 倍存储量,每个编码任务占用 20MB 左右内存。
获取播放状态
查询播放进度,播放状态,播放模式
查询播放队列
查询播放队列和当前播放位置
插播
如果想播放的音乐在队尾,要播放到指定音乐要等 20 分钟,是播放器先着急还是用户先着急?
插播就是为了解决这个问题,可以将指定音乐插入到 “下一首” 位置。
插播不会中断当前播放。
播放器销毁
音乐由房间拥有者播放,房间拥有者退出房间播放器自动销毁。就好比房间拥有者带着音响离开了,房间内不应该余音绕梁三日不绝。
尽快销毁播放器,有助于资源回收,提升资源利用率。
验证测试
-
✅️在播放或暂停状态中,清空播放队列,是指除了当前正在播放的都清空
-
✅️在顺序播放完时,清空播放队列,是指清除全部
-
✅️移除上一首音乐,上一首,即 1,2,3 移除 2 播放 1
-
✅️移除下一首音乐,下一首,即 2,3,4 移除 3 播放 4
-
✅️设置单曲循环时,上一首/下一首,测试表现应为上一首直到队首,下一首直到队尾
-
✅️设置队列循环时,上一首/下一首,测试表现应为上一首直到队首,下一首可以循环队列。
-
✅️设置顺序播放时,上一首/下一首,测试表现与单曲循环效果相同
-
✅️顺序播放结束,自动暂停,触发播放,应从队首重新开始
-
✅️暂停 5 分钟后,触发播放,还在之前停止的位置继续播放
-
✅️不在播放中,且队列没有音乐时,触发播放将响应提示
-
✅️添加音乐到队列中,首次添加时自动触发播放,非首次添加,保持旧的播放状态
-
✅️重复添加相同音乐到队列中,响应提示
-
✅️处理在未知的房间播放音乐,响应提示
-
✅️房间拥有者离开/房间内没人/主动调用接口,三者任意结可销毁音乐播放器
-
✅️插播正在播放的歌曲,当前播放 A 插播 A,此操作不可行,响应提示。
-
✅️队列为空时,下一首,此操作不可行,响应提示
-
✅️同一文件多次上传,预检应命中,复用资源
-
✅️播放器销毁后继续调用播放接口,应返回 “播放器不存在” 错误
-
✅️播放进度查询精度,是否准确表达出音频播放位置
以上是单元测试,还有集成测试项依赖测试环境,不一一列举。