1

我需要捕捉 HTML5 音频开始产生声音的确切时刻。

事实证明并不像看起来那么简单。

onplay您可能期望在触发事件或触发事件时开始播放音频onplaying?没门。至少在 WebKit 家族中,似乎没有浏览器事件在这个时间点完全触发。在 Chrome、Safari 和 Firefox 中onplayonplaying事件只是通过简单地与oncanplay!

我准备了一个简单的测试来证明这个事实。它表明音频实际上是在所有事件都已被触发的合理时间(超过 100 毫秒 - 400 毫秒)后开始播放的。

如果您查看控制台日志,您可以通过耳朵和耳朵注意到这一点。在日志中,我currentTime每 15 毫秒输出一次。它似乎正确地反映了实际的音频状态,并且在任何事件被触发后它开始改变 10-40 轮询。所以音频在play被触发后仍然被冻结。

测试代码如下所示:

    var audioEl = new Audio('http://www.w3schools.com/tags/horse.ogg');

    audioEl.oncanplay = function () {
        console.log('oncanplay');

        audioEl.currentTime = 1;    

        console.log('ready state is: ' + audioEl.readyState);
        audioEl.play();
    }


    audioEl.oncanplay = function () {
        console.log('oncanplay again');
    }

    audioEl.onplay = function() {
        console.log('onplay -----------------');
    }

    audioEl.onplaying = function() {
        console.log('onplaying ----------------');
    }

    setInterval(function () {
        console.log(audioEl.currentTime);
    }, 15);

提琴手

我非常需要知道音频开始播放的确切时刻,以便与视觉动画精确同步。

当然,我可以使用快速轮询大致找到这个时刻。这对实时应用程序的性能非常不利,尤其是在移动设备上。

我在问是否有人知道对此有更好的解决方案。2014 年的 HTML 音频实现看起来仍然很差:(

4

2 回答 2

3

正如@justin 所说,您可以监听playing事件以获得(或多或少)媒体开始实际播放的精确时刻。但是,是的,我一直看到对媒体事件readyState的一些支持,一般来说,即使在最新的 Chrome中也是如此。

无论这些事件是否有效,我都建议不要使用setInterval动画(或其他任何东西,就此而言)。相反,使用requestAnimationFrame,它会更频繁地触发,并且应该与浏览器和视频卡的重绘同步。您可以轮询currentTime每一帧的值,以计算您应该在动画中的位置。性能应该不是问题;您的情况正是requestAnimationFrame设计的目的。

function update() {
    var currentTime = audioEl.currentTime;
    // update your animation here
    requestAnimationFrame(update);
}

update();

当您使用它时,不要设置为currentTime5 直到事件触发之后。如果您尝试在浏览器加载足够的视频文件以知道持续时间之前进行设置,则会引发错误。但是你可以随时打电话;它不必等待。readyState > 0loadedmetadatacurrentTimeplay()canplay

于 2014-05-30T02:08:00.433 回答
-1

请尝试使用 canplaythrough。可能会有所帮助,并且最好确保您的音频可以一直播放到最后..

audioEl.oncanplay = function () {
      console.log('ready state is: ' + audioEl.readyState);
      audioEl.play();
}
于 2014-05-30T00:11:09.577 回答