web端怎么播放m3u8流地址?
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
m3u8 是 HLS(HTTP Live Streaming)协议的播放列表文件,不是视频本体。它是纯文本索引:按时间顺序列出若干 TS 分片(也支持 fMP4)的地址、时长、码率,并带有 EXT-X-VERSION、EXT-X-TARGETDURATION、EXT-X-ENDLIST 等控制标签;主播放列表(master playlist)还会列出多条不同码率的子流,供播放器做自适应码率切换。
因此浏览器不能像 mp4 那样把地址直接交给 <video src>——video 标签不认识这套分片索引。必须由播放器读取 m3u8,逐个拉取分片、按序解码拼接、维护播放缓冲区,才能出画面。这就是"能播"和"不能播"的分界线。
video.canPlayType('application/vnd.apple.mpegurl')。主流、成熟、体积适中,基于 MSE(Media Source Extensions),覆盖绝大多数需要 HLS 的桌面与安卓场景。
引入方式:npm 安装,或用 script 标签加载构建产物(CDN 地址由发布方补充)。
import Hls from 'hls.js'
const video = document.querySelector('#player')
const src = '/live/stream.m3u8'
if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = src // Safari:走原生
} else if (Hls.isSupported()) {
const hls = new Hls({
lowLatencyMode: true, // 低延迟直播
liveSyncDurationCount: 3 // 直播追帧:缓冲几个分片
})
hls.loadSource(src) // 加载播放列表
hls.attachMedia(video) // 绑定 video 元素
hls.on(Hls.Events.MANIFEST_PARSED, () => video.play())
hls.on(Hls.Events.ERROR, (evt, data) => {
if (!data.fatal) return // 非致命错误交给内部重试
if (data.type === Hls.ErrorTypes.NETWORK_ERROR) {
hls.startLoad() // 网络错误:重新拉流
} else if (data.type === Hls.ErrorTypes.MEDIA_ERROR) {
hls.recoverMediaError() // 解码错误:恢复媒体
} else {
hls.destroy()
}
})
}
关键参数说明:
lowLatencyMode:低延迟直播必须开启,且要求服务端输出 LL-HLS 才有实际收益。liveSyncDurationCount:直播追帧的核心。数值越小越贴近直播边缘,但越容易卡顿;延迟偏高就调小,抖动严重就调大,默认 3。Hls.Events.ERROR:只处理 fatal 错误,NETWORK_ERROR 用 startLoad()、MEDIA_ERROR 用 recoverMediaError();连续失败建议加退避,不要无限重试。video.js + videojs-contrib-hls:UI 与插件体系完整,适合已有 video.js 的项目,但包体与配置成本更高;dplayer 偏 UI 层,HLS 能力仍需挂 hls.js;Safari 原生路径不需要任何库,但要自己写兼容分支。
Access-Control-Allow-Origin;携带 Cookie 时还需 Allow-Credentials 与请求端 withCredentials 配合。liveSyncDurationCount 与缓冲区配置,避免一次性改一堆参数。最后补一句:如果你手里的 m3u8 是自己服务器上 FFmpeg 现切出来的,转码、切片、多码率、鉴权这些活儿其实可以整条交给托管的视频点播服务去做,播放器这边照样用上面的 hls.js 接入,运维成本能省一大截——阿里云视频点播 VOD 是这类场景里比较省心的选择,控制台走一遍转码模板配置就能出播放地址。当然,继续自建 FFmpeg 也完全没问题,看你的运维预算。
cnpm install hls.js -S
const src = ref("")
const video = document.getElementById('player')
if (!video) return
if (src.value.indexOf('.m3u8') > 0) {
if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = src.value
} else if (Hls.isSupported()) {
const hls = new Hls()
hls.loadSource(src.value)
hls.attachMedia(video)
video && video.play()
} else {
console.error('This is an old browser that does not support MSE https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API')
}
} else {
video.play()
}