
目标:在网页(桌面/移动浏览器)与原生客户端(Android / iOS)上做到稳定播放、跨网络兼容和可控缓存。
小分段:兼容策略包括同时提供:1) 原始MP4渐进式下载(兼容最老环境);2) HLS(iOS原生支持、广泛兼容);3) DASH(结合MSE支持更细粒度自适应)。再配合CDN的Range支持、CORS与正确MIME确保高兼容性。
步骤1:准备原始素材(尽量使用高码率无损或高质量源)。步骤2:使用FFmpeg生成多码率TS或fMP4分片与主清单(示例命令)。
示例(HLS多码率):ffmpeg -i input.mp4 -map 0 -codec: copy -start_number 0 -hls_time 6 -hls_playlist_type vod -hls_segment_filename "v%v_seg_%03d.ts" -var_stream_map "v:0,name:1080 v:1,name:720 v:2,name:480" -master_pl_name master.m3u8 v%v.m3u8
注意:选用fMP4分片可同时支持HLS与DASH(减少转封装),并确保关键帧对齐、分片时长(4~6s)以及对每个码率生成独立播放列表。
必备头部:Content-Type(video/mp4 或 application/vnd.apple.mpegurl)、Accept-Ranges: bytes、Content-Length、Cache-Control(根据策略)、Access-Control-Allow-Origin。
小分段:避免对视频资源启用压缩(不要 gzip 视频),确保 Range 请求被正确响应(支持206 Partial Content),并对分片文件与索引文件设置合理的缓存时间(.m3u8短缓存,分片长缓存)。
步骤:1) 创建CDN域名并指向源站;2) 配置缓存规则:对.m3u8设置较短TTL,对.ts/.m4s等分片设置较长TTL;3) 启用“Origin Shield”或回源加速;4) 确保Forwarding:转发Origin的Range与必要头(Authorization/Origin/Referer)和Query String(如签名参数)。
小分段:启用HTTPS、HTTP/2,必要时启用Signed URLs或Token(见第6点鉴权)。测试回源是否走正常304/206逻辑。
配置:CDN/源站需返回Access-Control-Allow-Origin: *或你的域名,Access-Control-Expose-Headers: Content-Length, Accept-Ranges, Content-Range。如使用带鉴权的请求则允许 Authorization,并正确响应OPTIONS预检。
小分段:在HTML层面检测HLS支持:iOS Safari原生支持HLS;其它浏览器使用hls.js(基于MSE)或dash.js播放DASH。示例JS:if (Hls.isSupported()) { const hls = new Hls(); hls.loadSource('master.m3u8'); hls.attachMedia(video); }
方案:服务器端生成带过期时间的签名URL或短期Token,CDN配置验证签名(CloudFront Signed URLs、Akamai Token、Cloudflare Workers等)。
小分段:签名应包含路径、过期时间与防重放参数;在播放端获取播放凭证后直接将签名附到m3u8或分片请求的Query String,CDN需将Query String转发给源站以验证合法性。
Android:使用ExoPlayer,优先播放HLS或DASH(与MSE类似的自适应),示例:MediaItem.fromUri("https://cdn/.../master.m3u8"),启用DefaultDataSourceFactory以注入Headers(如鉴权Token)。
iOS:使用AVPlayer/AVURLAsset;如果使用自签名或自定义Header,可实现AVAssetResourceLoader或在服务器端签名URL。注意iOS原生对HLS支持最好,DASH需第三方支持。
桌面浏览器:优先使用MSE(hls.js/dash.js)对非原生HLS浏览器做兼容;同时提供MP4作为回退。移动WebView:某些WebView对MSE支持差,建议在检测到不支持时通过Native Bridge调用原生播放器或使用Intent跳转至系统播放器。
小分段:实现特性检测:if (Hls.isSupported()) else if (video.canPlayType('application/vnd.apple.mpegurl')) fallback to native, else use MP4.
基础测试:curl -I 看头部,curl -r 0-1023 检查Range响应;浏览器打开master.m3u8观察是否能下载分片;真机测试网络切换与卡顿切换。
小分段:使用Chrome Network面板观察Content-Type、CORS头、206响应;使用ffprobe检测分片时长和关键帧对齐;对Android/iOS真机做断网重连与前后台切换测试。
优化:合理分片时长,启用CDN边缘缓存预热,使用多区域回源或近源复制。监控:收集播放事件(start/first-buffer/bitrate-switch/errors)、CDN回源流量、HTTP错误分布。
小分段:在客户端埋点统计首帧时间、缓冲率和平均码率,结合CDN日志定位回源热点或缓存失效率。
问:为什么浏览器不播放m3u8但iOS能播放?
答:iOS Safari对HLS原生支持,但其他浏览器需MSE支持并用hls.js或dash.js实现,如果缺少CORS头或CDN未允许Range请求,hls.js会失败。检查Access-Control-Allow-Origin与Accept-Ranges头,或提供MP4回退。
问:如何处理移动网络切换导致的卡顿与码率突降?
答:确保分片时长适中(4~6s),启用ABR(自动码率切换)策略并在播放器中设置缓冲前最小缓冲区与自适应开关;在CDN侧减少回源延迟并启用边缘缓存以降低网络切换影响。
问:如何在WebView中保证稳定播放?
答:先检测WebView是否支持MSE/HLS,如不支持则通过JS桥调用原生播放组件(ExoPlayer / AVPlayer)或触发系统外部播放器;同时在服务器端提供MP4渐进式下载作为最后回退。