HLS/DASH 切片:直播点播的网页播放方案 HLS/DASH 切片直播点播的网页播放方案视频做好了怎么放到网页上让别人看直接放 MP4 文件加载慢、拖动卡。HLS 和 DASH 是目前最主流的流媒体方案把视频切成小分片边下边播。这篇讲怎么用 FFmpeg 生成 HLS m3u8 和 DASH mpd以及两者的区别和选型。大家好我是黒漂技术佬。做视频网站、直播、在线课程都需要流媒体切片。直接传一个大 MP4用户打开要等半天拖动进度条也要缓冲。切成 HLS 或 DASH 之后几秒钟就能开始播放还能自动切换清晰度。这篇讲 HLS 和 DASH 的基本原理FFmpeg 怎么生成各自的优缺点以及实际项目里怎么选。一、HLS 是什么HLSHTTP Live Streaming是苹果推出的流媒体协议现在全平台都支持了。原理把一个视频切成很多个小的 TS 分片文件一般 10 秒一个再生成一个 m3u8 播放列表文件。播放器先下载 m3u8然后按顺序下载分片播放。视频 → 切成 N 个 .ts 分片 一个 .m3u8 索引文件优点兼容性最好iOS 原生支持安卓、PC 浏览器也都支持基于 HTTPCDN 好加速防火墙友好支持多码率自适应清晰度自动切换缺点延迟较高默认 30 秒不适合互动直播TS 封装有 overhead同样画质体积略大二、最简单的 HLS 切片ffmpeg-iinput.mp4-c:vlibx264-c:aaac-fhls output.m3u8就这一条命令生成一个 m3u8 文件和一堆 ts 分片。默认每 2 秒一个分片数量 视频时长 / 2。三、HLS 常用参数1. 分片时长ffmpeg-iinput.mp4-ccopy-fhls-hls_time10output.m3u8-hls_time 10每个分片约 10 秒。分片短启动快、seek 准但文件多、开销大分片长文件少、开销小但启动慢、seek 不准一般点播用 6-10 秒直播用 2-4 秒。2. 分片数量控制直播模式直播的时候分片会越来越多占满硬盘。设置保留数量ffmpeg-iinput.mp4-ccopy-fhls-hls_time4-hls_list_size6output.m3u8-hls_list_size 6m3u8 里只保留最新的 6 个分片旧的删掉。配合直播推流使用始终只存最近几十秒的内容。3. 单个文件模式不推荐ffmpeg-iinput.mp4-ccopy-fhls-hls_flagssingle_file output.m3u8所有分片存在一个文件里m3u8 用字节偏移量索引。文件少了但不利于 CDN 缓存一般不用。4. 加密 HLSffmpeg-iinput.mp4-ccopy-fhls-hls_key_info_filekey_info.txt output.m3u8视频分片加密防止别人直接下载。需要准备 key_info 文件指定密钥地址和密钥文件。视频网站、付费课程常用。四、多码率自适应 HLS同一个视频压成多个清晰度播放器根据网速自动切换。先生成多个码率# 1080pffmpeg-iinput.mp4-c:vlibx264-b:v4M-c:aaac-b:a128k-fhls-hls_time10hls_1080p/output.m3u8# 720pffmpeg-iinput.mp4-c:vlibx264-b:v2M-c:aaac-b:a128k-fhls-hls_time10hls_720p/output.m3u8# 480pffmpeg-iinput.mp4-c:vlibx264-b:v1M-c:aaac-b:a96k-fhls-hls_time10hls_480p/output.m3u8再写一个主播放列表master m3u8#EXTM3U #EXT-X-STREAM-INF:BANDWIDTH4000000,RESOLUTION1920x1080 hls_1080p/output.m3u8 #EXT-X-STREAM-INF:BANDWIDTH2000000,RESOLUTION1280x720 hls_720p/output.m3u8 #EXT-X-STREAM-INF:BANDWIDTH1000000,RESOLUTION854x480 hls_480p/output.m3u8播放器读这个主列表根据网速自动选清晰度。一条命令生成多码率用 filter_complex 分流只解码一次ffmpeg-iinput.mp4\-filter_complex[0:v]split3[v1][v2][v3];[v1]scale1920:1080[out1];[v2]scale1280:720[out2];[v3]scale854:480[out3]\-map[out1]-c:vlibx264-b:v4M-map0:a-c:aaac-b:a128k-fhls-hls_time10hls_1080p/output.m3u8\-map[out2]-c:vlibx264-b:v2M-map0:a-c:aaac-b:a128k-fhls-hls_time10hls_720p/output.m3u8\-map[out3]-c:vlibx264-b:v1M-map0:a-c:aaac-b:a96k-fhls-hls_time10hls_480p/output.m3u8只解码一次效率比转三次高。五、直播推 HLS把 RTMP 或 RTSP 流转成 HLS 直播ffmpeg-irtsp://摄像头地址-ccopy-fhls\-hls_time2\-hls_list_size6\-hls_flagsdelete_segments\/var/www/hls/live.m3u82 秒一个分片保留 6 个分片约 12 秒内容旧分片自动删除配合 Nginx 或 CDN 对外提供 HTTP 访问网页就能看直播了。⚠️ HLS 延迟较高6 个分片就是 12 秒起步加上缓冲一般 20-30 秒延迟。适合安防监控、赛事直播这种不需要互动的场景。六、DASH 是什么DASHDynamic Adaptive Streaming over HTTP是国际标准的自适应码率流媒体协议和 HLS 类似但更灵活。和 HLS 的区别对比项HLSDASH推出方苹果国际标准组织分片格式TS / fMP4fMP4 / WebM索引文件m3u8文本mpdXML兼容性最好全平台大部分现代浏览器支持iOS 较晚才支持灵活性一般更高支持更多编码格式延迟较高可配置更低延迟适用场景追求兼容性 → HLS多编码格式、精细控制 → DASH现在一般两个都生成播放器自动选七、FFmpeg 生成 DASHffmpeg-iinput.mp4-c:vlibx264-c:aaac-fdash output.mpd生成一个 mpd 文件和一堆 m4s 分片。常用参数ffmpeg-iinput.mp4\-c:vlibx264-b:v2M-c:aaac-b:a128k\-fdash\-seg_duration10\-adaptation_setsid0,streamsv id1,streamsa\output.mpd-seg_duration 10分片 10 秒-adaptation_sets视频和音频分属不同自适应集多码率 DASH和 HLS 类似多个视频流一起输出ffmpeg-iinput.mp4\-filter_complex[0:v]split2[v1][v2];[v1]scale1280:720[v720];[v2]scale854:480[v480]\-map[v720]-c:vlibx264-b:v2M\-map[v480]-c:vlibx264-b:v1M\-map0:a-c:aaac-b:a128k\-fdash\-seg_duration10\-adaptation_setsid0,streams0,1 id1,streams2\output.mpd八、HLS vs DASH 怎么选只选一个的话HLS兼容性碾压iOS 必须用 HLS安卓和 PC 也都支持。保守方案选 HLS 不会错。两个都生成现在主流视频平台都是 HLS DASH 都有播放器根据环境自动选择。低延迟场景都不选HLS 和 DASH 都是分片机制延迟天然高。需要秒级以下延迟用 WebRTC1-3 秒延迟用 HTTP-FLV。九、网页播放HLS 播放PC 浏览器原生不支持 HLSSafari 除外需要用 hls.jsscriptsrchttps://cdn.jsdelivr.net/npm/hls.js/scriptvideoidvideocontrols/videoscriptconstvideodocument.getElementById(video);consthlsnewHls();hls.loadSource(output.m3u8);hls.attachMedia(video);/scriptDASH 播放用 dash.jsscriptsrchttps://cdn.dashjs.org/latest/dash.all.min.js/scriptvideodata-dashjs-playersrcoutput.mpdcontrols/video统一方案Video.js / DPlayer封装好的播放器自动判断用 hls.js 还是 dash.js。十、踩过的坑坑 1分片对不上关键帧分片不是从关键帧开始的话每个分片开头会卡一下。解决编码时设置关键帧间隔和分片时长对齐。# 10 秒分片就设 10 秒一个关键帧帧率 30 的话就是 300 帧ffmpeg-iinput.mp4-c:vlibx264-g300-keyint_min300-fhls-hls_time10output.m3u8坑 2m3u8 路径问题m3u8 文件里引用的 ts 路径是相对路径放 CDN 的时候要注意目录结构。解决用-hls_base_url指定基础 URL。ffmpeg-iinput.mp4-fhls-hls_base_urlhttps://cdn.example.com/hls/output.m3u8坑 3HLS 直播延迟太高默认配置 30 秒延迟很正常。优化方向分片改小-hls_time 11 秒一片列表减少-hls_list_size 3播放器端减小缓冲极限能压到 3-5 秒但稳定性会下降。再低就得上 WebRTC 了。坑 4音视频不同步分片切割点如果音视频不对齐播放就会漂移。解决用-hls_flags split_by_time按时间切割或者编码时统一时间基。十一、本篇小结HLS 兼容性最好DASH 更灵活主流平台两个都做FFmpeg 生成 HLS-f hls生成 DASH-f dash点播分片 6-10 秒直播 2-4 秒多码率自适应用 split 分流一次编码输出多路HLS 延迟较高不适合互动直播网页播放用 hls.js 或 dash.js下一篇进入 SDK 开发部分FFmpeg SDK 开发入门——不再用命令行用 C 代码调用 FFmpeg 库打开视频、读帧、解码集成到自己的程序里。我是黒漂技术佬。