如何实现类似Hotstar的视频离线下载(TS分片存储)
视频离线观看(TS分片)实现指南
嘿,我之前做过视频流媒体应用的离线功能,刚好对TS分片这块比较熟,给你唠唠怎么实现,还有你提到的那个Perl项目的事儿👇
核心逻辑:为什么Hotstar用chunk.ts分片?
首先得搞懂为什么选TS(MPEG-2 Transport Stream)格式做分片:
- TS分片天生支持独立播放,哪怕某几个分片损坏,剩下的依然能正常播放,容错性拉满;
- 分片大小灵活,适合断点续传,用户中途暂停下载也不用从头再来;
- 几乎所有主流播放器(包括Android的ExoPlayer)都原生支持TS分片的HLS播放,适配成本低。
具体实现步骤拆解
1. 视频转码与分片生成(后端/本地处理)
你不用纠结那个Perl项目,业界通用方案是用FFmpeg来搞定转码和分片,功能全、跨平台,还能直接集成到Android项目里(比如用FFmpegKit)。
举个最常用的FFmpeg命令,直接把源视频转成TS分片+索引文件:
ffmpeg -i 你的源视频.mp4 -c:v libx264 -c:a aac -hls_time 15 -hls_list_size 0 -hls_segment_filename "chunk_%03d.ts" output.m3u8
参数解释:
-hls_time 15:每个分片15秒(可以根据需求调整,建议10-30秒);-hls_segment_filename:指定分片文件名格式(比如chunk_001.ts、chunk_002.ts);output.m3u8:这是分片的索引文件,记录了所有分片的顺序、时长等信息,离线播放时必须和分片存在一起。
2. Android端的下载与存储管理
存储路径选择
把m3u8和所有chunk.ts下载到Android的私有目录最稳妥,比如:
/Android/data/你的应用包名/files/offline/视频唯一ID/
Android 10+建议用Scoped Storage,避免权限问题;如果是兼容旧版本,需要申请WRITE_EXTERNAL_STORAGE权限。
下载优化
- 做断点续传:记录已下载的分片文件名,下次启动下载时跳过已完成的;
- 多线程下载:同时下载多个分片,提升下载速度;
- 进度监听:实时更新下载进度,给用户反馈。
3. 离线播放实现
用Android主流的ExoPlayer就能轻松实现本地TS分片播放,核心是让播放器读取本地的m3u8索引文件:
// 获取本地m3u8文件的Uri File offlineDir = new File(getFilesDir(), "offline/视频唯一ID/output.m3u8"); Uri localM3u8Uri = Uri.fromFile(offlineDir); // 初始化ExoPlayer并加载本地媒体 MediaItem mediaItem = MediaItem.fromUri(localM3u8Uri); ExoPlayer exoPlayer = new ExoPlayer.Builder(context).build(); exoPlayer.setMediaItem(mediaItem); exoPlayer.prepare(); exoPlayer.play();
ExoPlayer会自动解析m3u8里的分片列表,依次加载本地的chunk.ts文件播放,完全不用你手动拼接分片。
关于那个Perl项目的说明
你找到的ts-split是用Perl写的TS分片工具,原理和FFmpeg的HLS分片逻辑类似,但它更适合PC端的小批量处理,在Android项目里集成Perl环境成本太高,完全没必要——用FFmpeg或者FFmpegKit才是更高效的选择。
额外注意事项
- 版权保护:如果你的视频需要加密,Hotstar应该用了Widevine DRM,你需要把加密信息写入m3u8,同时在本地安全存储解密密钥;
- 分片大小:不要把分片做的太小(比如1秒),会生成大量小文件,拖慢存储和读取速度;也不要太大,不利于断点续传;
- 缓存清理:给用户提供离线视频删除功能,定期清理过期的离线文件,避免占用过多存储空间。
内容的提问来源于stack exchange,提问作者Samwinishere Here




