前一篇文章中介绍了使用AuidoQueue实现一个音频播放器的功能,最近我又把这个项目完善了一下,做了一个边播边缓存的功能。
因为播放部分的逻辑我们已经完成,这里主要是怎么缓存数据的问题,实现之前我想到了2种方案。
方案一 在didReceiveDataBlock中缓存文件
直接在拿到音频数据进行播放的同时就将数据写入文件,这种方案的优点是实时性,播放过的音频数据都会被缓存起来,缺点就是缓存的文件可能并不是一个完整的音频,比如播了1分钟后seek到2分钟的地方继续播,中间1分钟的数据可能就没有收到,这就导致缓存的文件是有问题的,如果下次直接播这个本地文件可能就凉凉了。。。
方案二 在success的回调中缓存数据
在success中回调回来的数据就是完整的音频数据,缓存这个数据不会出现数据不完整的情况,但是这个回调并不是实时返回的,会在整个音频的数据都获取到以后才会返回,有一个延迟,如果网络不太好,可能直到音频播放完了才会返回。
考虑到方案的可行性和数据的可用性,这里我选择了方案二,毕竟完整的数据比缓存的实时性更重要一些。当然,这个方案一我觉得还是有优化的空间,如果能够优化到保证了数据的完整性,会比方案二更优。
增加的模块
这里我增加了2个模块,一个是文件的操作模块,还有一个是网络模块。
LLYFileManager
文件操作模块是对音频数据的存储相关操作。
|
|
LLYHttpSessionManager
网络模块是基于AFNetworking做的一个二次封装(参考这篇文章),主要就是请求音频数据。
播放优化
在播放前,我们需判断一下当前url对应的文件是否已经下载到本地了,如果已经下载就直接播本地的文件,否则还是走网络播放的逻辑。
这个判断逻辑我是这样处理的,先发送一个http head请求,拿到对应url文件的countOfBytesExpectedToReceive,然后将countOfBytesExpectedToReceive和本地文件大小(fileSize)进行比较,如果fileSize >= contentExceptLength,则说明本地文件是完整的音频文件,可以直接播放,否则的话还是走网络播放的逻辑,并在success回调中覆盖之前的不完整文件。