Dan*_*rry 6 video iframe html5 youtube-api youtube-iframe-api
我一直在寻找一个解决方案,但我还没有找到它.我们的应用需要使用player.getCurrentTime()
驱动某些屏幕动画来轮询YouTube视频对象.使用Flash API这很棒,因为我们可以40ms
间隔(25 FPS)轮询播放器并获得非常准确的当前播放器时间值.我们现在已经开始使用iFrame API,遗憾的是它不允许任何接近该准确度的任何内容.我做了一些研究,似乎因为它是一个iFrame,a postMessage
用于将玩家状态暴露给player.getCurrentTime()
呼叫.不幸的是,这个帖子消息事件很少被触发 - 有时低至每秒4次.更糟糕的是,消息触发的实际速率似乎取决于浏览器的渲染引擎.
有人知道是否有可能强制渲染引擎更频繁地触发这些消息,以便可以实现更长的时间分辨率来轮询播放器?我试过requestAnimationFrame
,它没有解决问题.有没有人成功地让iFrame播放器更频繁地报告更准确的时间?
我已经为我原来的问题想出了一个解决方法.我写了一个简单的补间函数,它将以我想要的频率轮询iFrame播放器并插入两者之间的时间瞬间.播放器本身仅每250毫秒左右更新一次当前时间,具体取决于渲染引擎和平台.如果您更频繁地轮询它,它将在几个连续的轮询中返回相同的当前时间值.但是,如果应用某些逻辑,则可以检测播放器何时返回新的当前时间并相应地更新您自己的计时器.我在一个间隔为25毫秒的定时器上运行以下功能.在每次迭代中,我向当前时间添加25毫秒,除非我检测到播放器报告的当前时间的变化.在那种情况下,我用新的"实际"当前时间更新我自己的计时器.当你这样做的时候可能有一个小的跳跃或非线性,但是如果你以足够高的速率轮询玩家,这应该是难以察觉的.
window.setInterval(tween_time, 25);
function tween_time() {
time_update = (ytplayer.getCurrentTime()*1000)
playing=ytplayer.getPlayerState();
if (playing==1){
if (last_time_update == time_update)
{
current_time_msec += 25;
}
if (last_time_update != time_update)
{
current_time_msec = time_update;
}
}
do_my_animations();
last_time_update = time_update;
}
Run Code Online (Sandbox Code Playgroud)
在 HTML5 中,Youtube API 中的 getCurrentTime() 函数和 postMessage 事件可能链接到 HTML5 媒体元素规范的 currentTime 属性和 timeupdate 事件。
timeupdate 事件触发的速率因浏览器而异,并且截至目前无法调整到您所寻求的精度级别(Flash 在这方面仍然领先一些)。根据规范:
如果在正常播放期间通过当前播放位置的通常单调增加来达到时间,并且用户代理在过去 15 到 250 毫秒内没有在元素上触发 timeupdate 事件,并且仍然没有为此类事件运行事件处理程序,那么用户代理必须将任务排队以在元素上触发名为 timeupdate 的简单事件。(在其他情况下,例如显式搜索,相关事件将作为更改当前播放位置的整个过程的一部分被触发。)
因此,该事件的触发速度不会快于 66Hz 或慢于 4Hz(假设事件处理程序的运行时间不超过 250ms)。鼓励用户代理根据系统负载和每次处理事件的平均成本来改变事件的频率,以便 UI 更新的频率不会超过用户代理在解码视频时可以轻松处理的频率。
对于 currentTime 属性,精度以秒表示。任何低于秒的精度都是浏览器特定的实现,不应被视为理所当然(实际上,您将在 Chrome 等现代浏览器中获得亚秒精度,但效率会波动)。
最重要的是,Youtube API 可以限制所有这些事情,以达到 250 毫秒精度的更大共同点,并使所有浏览器满意(因此每秒 4 个事件以及您在测试中注意到的情况)。对于您的案例场景,您最好尝试将动画缩放到 250 毫秒的精度概念,并允许一定的误差幅度以获得更好的用户体验。未来浏览器和 HTML5 媒体将会变得更好,希望我们能够获得真正的毫秒精度。