一、业务获取视频总时长返回 0 的现实痛点做点播网课、视频网站业务经常需要 JS 拿到视频总时长用于展示进度条、计算播放完成度、学习时长统计。很多新手直接调用 video.duration结果拿到返回值为 0拿不到真实视频时长。现象很迷惑视频已经可以正常播放画面声音全部正常但是 JS 读取总时长始终是 0。网上碎片化说法很多有人说是浏览器 bug有人说是 M3U8 损坏实际背后分很多种不同原因。点播和直播表现不一样直播流本身就没有固定总时长拿到 0 属于正常现象但点播 M3U8 明明是完整回放也拿到 0就属于异常故障。很多新手不区分点播、直播拿到 0 就一头雾水反复修改 JS 代码折腾很久问题根源却出在 M3U8、预加载策略、播放器初始化时机。遇到获取 duration 总时长异常的问题我会使用 m3u8live.cn加载同一份点播 M3U8观察元信息加载行为区分是流本身问题还是业务页面代码时机错误。二、点播场景 duration 返回 0 常见原因原因 1video 标签 preload 设置为 nonepreloadnone 代表页面初始化不去拉取任何视频元信息。视频分片、索引不会发起请求在用户点击播放之前元数据完全没有加载此时读取 duration 直接返回 0。很多列表页大量视频卡片会设置 none就会出现拿不到时长。原因 2hls.js 清单 MANIFEST_PARSED 事件还没有触发M3U8 索引还没有解析完成就去读取 duration。M3U8 是远程网络清单不是本地 MP4不能页面加载完立刻读时长要等清单解析完毕之后元数据才会就绪。很多新手页面渲染完成直接取值时机过早。原因 3M3U8 索引本身元信息缺失分片元数据异常虽然可以播放但分片内部元信息有缺陷播放器解析之后无法提取完整时长。VLC 可以正常播放浏览器 MSE 环境拿不到 duration。原因 4Safari 原生 HLS 和 hls.js 环境行为不一致同样一份 M3U8Chrome 下可以正常拿到时长iOS Safari 时机不对就返回 0。Safari 原生 HLS 元信息加载逻辑和 hls.js 存在差异。重要提醒直播 M3U8 拿到 duration 等于 0 属于正常现象直播没有固定完整总时长不要把直播流拿来做总时长获取的测试。三、简单排查实操步骤第一步确认当前是点播流M3U8 末尾存在 #EXT‑X‑ENDLIST 结束标记直播不用排查 duration 为 0。 第二步待测点播 M3U8 粘贴网页调试工具观察元信息加载。如果工具可以正常读出视频总时长代表 M3U8 分片本身没问题重点排查业务页面 preload、读取时机如果工具也拿不到时长代表 M3U8 分片元信息存在缺陷需要重新转码切片。第三步业务代码不要页面初始化直接读取 duration。点播业务监听 MANIFEST_PARSEDhls.js 环境或者 loadedmetadata原生 video事件事件触发之后再去读取总时长。第四步业务需要页面打开就获取时长preload 不要设置为 none可以改为 metadata仅拉取元信息不会下载大量音视频分片。四、新手开发避坑建议分清点播与直播直播不要尝试获取固定总时长。不要 DOM 渲染完成立刻读取 duration等待对应元信息就绪事件回调再取值。页面列表需要提前拿到视频时长preload 设置 metadata不需要预取时长的视频卡片preload 使用 none 节省带宽。iOS Safari 真机做回归测试不要只依赖 Chrome 桌面浏览器。五、总结点播业务 video.duration 返回 0不一定是 M3U8 损坏。最常见两个因素一是 preloadnone 不加载元数据二是读取总时长时机太早M3U8 清单还没有解析完成。直播流拿到 0 是正常现象。借助网页调试工具验证流本身是否可以解析出时长再调整 preload 配置与 JS 读取时机就可以解决大部分获取总时长为 0 的疑难问题。