如何用JavaScript获取HTML Video的帧率?现有方案存精度问题
解决视频元素帧率获取的精度问题
方案1:直接读取视频轨道的元数据帧率
这是精度最高的方式,直接获取视频文件本身的帧率属性,无需依赖帧时间计算。需要等待视频元数据加载完成后读取:
const video = document.querySelector('video'); // 监听元数据加载完成事件 video.addEventListener('loadedmetadata', () => { const videoTrack = video.videoTracks[0]; if (videoTrack) { const trackSettings = videoTrack.getSettings(); // frameRate 为精确浮点数,支持 29.97、59.94 这类非整数帧率 const preciseFps = trackSettings.frameRate; console.log('视频原始帧率:', preciseFps); // 按需取整 const roundedFps = Math.round(preciseFps); } });
注意事项:
- 需确保视频已设置有效src并开始加载,才会触发
loadedmetadata事件 - 对于内嵌第三方视频(如YouTube),需确认视频元素已完成元数据加载
方案2:改进requestVideoFrameCallback的多帧平均计算
若需获取视频实际渲染帧率(而非原始帧率),可通过累积多帧时间差的方式,抵消单帧mediaTime的精度误差:
const video = document.querySelector('video'); let frameCount = 0; let lastMediaTime = null; // 取10帧计算平均,可根据需求调整样本量 const sampleFrameCount = 10; function calculateFps(timestamp, metadata) { const currentMediaTime = metadata.mediaTime; if (lastMediaTime === null) { lastMediaTime = currentMediaTime; } else { frameCount++; // 累积到指定帧数后计算平均帧率 if (frameCount >= sampleFrameCount) { const totalMediaElapsed = currentMediaTime - lastMediaTime; const avgFrameDuration = totalMediaElapsed / frameCount; const preciseFps = 1 / avgFrameDuration; console.log('实际渲染帧率(多帧平均):', preciseFps); // 重置计数,持续监测 frameCount = 0; lastMediaTime = currentMediaTime; } } video.requestVideoFrameCallback(calculateFps); } video.requestVideoFrameCallback(calculateFps);
优势:
- 通过多帧平均消除单帧
mediaTime的精度偏差 - 能反映浏览器实际渲染视频的帧率(如性能限制导致的降帧、倍速播放场景)
方案3:结合performance.now()计算真实渲染帧率
如果mediaTime的精度始终无法满足需求,可使用浏览器高精度时间戳performance.now()计算帧间隔:
const video = document.querySelector('video'); let lastPerformanceTime = null; let frameCount = 0; const sampleFrameCount = 15; function calculateRealFps(timestamp, metadata) { const currentTime = performance.now(); if (lastPerformanceTime !== null) { frameCount++; if (frameCount >= sampleFrameCount) { const totalElapsed = currentTime - lastPerformanceTime; const avgFrameDuration = totalElapsed / frameCount; const realFps = 1000 / avgFrameDuration; // 转换为每秒帧数 console.log('真实渲染帧率:', realFps); frameCount = 0; lastPerformanceTime = currentTime; } } else { lastPerformanceTime = currentTime; } video.requestVideoFrameCallback(calculateRealFps); } video.requestVideoFrameCallback(calculateRealFps);
注意:
- 该方法计算的是浏览器渲染视频帧的实际帧率,可能与视频原始帧率存在差异(如倍速播放、浏览器降帧)
总结
- 若需视频原始文件帧率,优先选择方案1(读取视频轨道元数据),精度最高
- 若需实际播放的渲染帧率,选择方案2或3,通过多帧平均减少精度误差
内容的提问来源于stack exchange,提问作者derder56
相关产品推荐
相关产品推荐

