我需要能够尽可能地将一些JavaScript事件同步到YouTube视频中的特定时间。虽然我知道有一些limitations to how accurate timers can be in browsers,但我认为应该可以做得比我从视频播放器获得的更好。我在开始播放YouTube视频时使用了以下代码。
startTime = new Date();
setInterval(function () {
samples.push({player: player.getCurrentTime(), jstime: new Date() - startTime});
}, 20);
此代码获取视频播放器认为与player.getCurrentTime()
处于同一时间的当前时间,并将其与常规时钟时间一起记录到播放开始时间。以下结果可让您了解准确性:
{"player":0.188,"jstime":109},
{"player":0.676,"jstime":125},
{"player":0.676,"jstime":140},
{"player":0.676,"jstime":171},
{"player":0.676,"jstime":203},
{"player":0.676,"jstime":218},
{"player":0.676,"jstime":234},
{"player":0.676,"jstime":265},
{"player":0.676,"jstime":296},
{"player":0.676,"jstime":312},
{"player":0.676,"jstime":327},
{"player":0.676,"jstime":577},
{"player":1.012,"jstime":624},
{"player":1.187,"jstime":655},
{"player":1.187,"jstime":671},
{"player":1.187,"jstime":686},
{"player":1.187,"jstime":717},
{"player":1.187,"jstime":733},
{"player":1.187,"jstime":749},
{"player":1.187,"jstime":780},
{"player":1.187,"jstime":811},
{"player":1.447,"jstime":842},
{"player":1.447,"jstime":858},
{"player":1.447,"jstime":873},
{"player":1.447,"jstime":905},
{"player":1.447,"jstime":936},
{"player":1.447,"jstime":951},
{"player":1.447,"jstime":998},
{"player":1.605,"jstime":1029},
{"player":1.605,"jstime":1061},
在网上进行的一些挖掘表明,YouTube视频计时器的准确性直接来自底层播放器(在我的情况下通常是HTML5),并且不应该依赖于更精确的几百毫秒。
一些观察/假设(以及一些明显的说明):
player.getCurrentTime()
检索的时间将接近不变的时间。 0
)。一旦知道了错误率并且随着时间的推移采样,就应该可以得到一个接近两者中最准确的定时器(提供给JavaScript的时钟)的准确度的定时器。这个假设是否正确?
考虑到播放器时间和JavaScript时钟播放时间的输入,我如何得到一个可以调用每个动画帧的计时器,以便为我提供最高精度?
这样的派生时间有多精确?
答案 0 :(得分:1)
我之前已经做过这样的事情(诚然使用ActionScript并以AVM为目标),但原则仍然存在。
不要依赖浏览器(或应用)来获取时间信息。
想一想,在视频方面稍微缓冲一下,或偶尔使用沙滩球/旋转小时玻璃,突然间你的同步是错误的。
您要做的是挂钩媒体播放器事件,然后对视频时间作出反应。
W3 HTML5视频演示页面[http://www.w3.org/2010/05/video/mediaevents.html]显示了一大堆属性和值 - 我认为您想要查看的是timeUpdate事件和currentTime属性。
答案 1 :(得分:0)
我想我已经想出如何实现这一目标。现在有点乱,但你明白了。
function youTubeTimer (player) {
var startTime;
var totalTime = 0;
var lastPlayerTime;
//Array of offsets between the JS timer and reported video player time
var deltas = [];
// Amount of time to correct
var correction;
player.addEventListener('onStateChange', function (e) {
if (e.data === YT.PlayerState.PLAYING) {
startTime = new Date();
} else if (e.data === YT.PlayerState.PAUSED || e.data === YT.PlayerState.BUFFERING || e.data === YT.PlayerState.ENDED) {
totalTime = ((new Date() - startTime)/1000) + totalTime;
}
if (e.data === YT.PlayerState.ENDED) {
console.log(totalTime);
}
});
function getJsTime() {
if (player.getPlayerState() === YT.PlayerState.PLAYING) {
return ((new Date() - startTime)/1000) + totalTime;
} else {
return totalTime;
}
}
// Call this function frequently!
this.getHighResPlayerTime = function getHighResPlayerTime() {
if (!player.getCurrentTime) {
return 0;
}
var playerTime = player.getCurrentTime(); // Seconds of playback, reported by the video player
var jsTime = getJsTime(); // Seconds from the clock time when the video started
// Has the player time been updated? Adjust the correction offset.
if (playerTime !== lastPlayerTime) {
lastPlayerTime = playerTime;
// Store up to 20 samples of offsets
if (deltas.length >= 500) {
deltas.shift();
}
deltas.push(jsTime - playerTime);
// Calculate a new correction value
correction = 0;
for (var x = 0; x < deltas.length; x ++)
{
correction += deltas[x];
}
correction = correction / x;
}
return jsTime - correction;
}
}