音频文件在线时如何在HTML5音频对象中设置currentTime?

Igi*_*gid 7 javascript event-handling audio-player dom-events html5-audio

我有一个带有前进/后退10第二个按钮的JavaScript音频播放器.我通过设置currentTime我的音频元素来做到这一点:

function Player(skipTime)
{
    this.skipTime = skipTime;
    this.waitLoad = false;

    // initialise main narration audio
    this.narration = new Audio(getFileName(dynamicNarration));
    this.narration.preload = "auto";
    this.narration.addEventListener('canplaythrough', () => { this.loaded();       });
    this.narration.addEventListener('timeupdate',     () => { this.seek();         });
    this.narration.addEventListener('ended',          () => { this.ended();        });
    this.narration.addEventListener('waiting',        () => { this.audioWaiting(); });
    this.narration.addEventListener('playing',        () => { this.loaded();       });
}

Player.prototype = {
    rew: function rew()
    {
        if (!this.waitLoad) {
            this.skip(-this.skipTime);
        }
    },

    ffw: function ffw()
    {
        if (!this.waitLoad) {
            this.skip(this.skipTime);
        }
    },

    skip: function skip(amount)
    {
        const curTime = this.narration.currentTime;
        const newTime = curTime + amount;
        console.log(`Changing currentTime (${curTime}) to ${newTime}`);
        this.narration.currentTime = newTime;
        console.log(`Result: currentTime = ${this.narration.currentTime}`);
    },

    loaded: function loaded()
    {
        if (this.waitLoad) {
            this.waitLoad = false;
            playButton.removeClass('loading');
        }
    },

    audioWaiting: function audioWaiting()
    {
        if (!this.waitLoad) {
            this.waitLoad = true;
            playButton.addClass('loading');
        }
    },
}
Run Code Online (Sandbox Code Playgroud)

(我在这里包括了一些我正在附加的事件监听器,因为之前我调试了一个类似的问题,因为在事件监听器中存在冲突.虽然这次彻底调试了事件监听器,但我不认为这是根问题.)

虽然这一切在我的本地副本上运行正常,但当我测试在线版本时,我得到以下结果:

  • Chrome:将播放位置重置为0.最终控制台行读取结果:currentTime = 0.
  • Safari:根本不改变游戏位置.最后console.log一行给出的值currentTime等于newTime(即使游戏位置实际上没有变化).
  • Firefox:跳过工作; 向后跳过会中断音频几秒钟,然后在播放头出现之前的几秒钟内再次开始播放.在这两种情况下,最终的console.log行都给出了currentTime等于的值newTime

该问题必须与音频加载方式有关.我尝试添加另一个控制台日志行来显示开始和结束值buffered.

在Chrome中,它2在当前播放位置后上升到几秒钟.在Safari中它可以达到~170几秒钟,而在Firefox中似乎可以缓冲整个音频长度.

但是,在每种情况下,buffered对象的开始是0.

有谁知道可能出现什么问题?

小智 8

正确加载音频文件并使用属性有一些要求。您在提供文件时的响应需要具有以下标头。

接受范围:字节

内容长度:BYTE_LENGTH_OF_YOUR_FILE

内容范围:字节 0-BYTE_LENGTH_OF_YOUR_FILE/BYTE_LENGTH_OF_YOUR_FILE

内容类型:音频/mp3

我和我的同事们为此苦苦挣扎了几天,终于成功了

音频文件的响应标头的图像


Igi*_*gid 0

我找到了解决问题的方法,即使不是确切的解释。

我的托管提供商使用 CDN,必须将资源的 URL 替换为不同域的 URL。我的音频资源的URL是由JS动态构建的,因为它们有一个随机元素;因此,替换 URL 的部署过程无法捕获我的音频文件的 URL。为了解决这个问题,我手动从 CDN 中排除了音频文件,这意味着我可以使用相对文件路径引用它们。

这就是我遇到这个问题时的情况。

然后,由于另一个问题,我采取了不同的方法:我将音频文件放回到 CDN 上,并编写了一个函数来提取检索文件所需的域名。当我这么做的时候,我突然发现所有与设置有关的问题都currentTime消失了。不知何故,CDN 上没有文件会严重干扰浏览器有序加载它们的能力。

如果有人能自愿解释为什么会这样,我会很想听听......

编辑

我一直在从事另一个涉及流音频的项目,这次也支持 PWA,所以我必须在我的 Service Worker 中为音频文件实现一个缓存机制。通过本指南,我了解了范围请求的所有陷阱,并且现在了解到,如果无法为带有范围标头的请求提供正确的响应,将会中断某些浏览器上的搜索。

看来在上述情况下,当我从 CDN 中排除我的文件时,它们是从不支持范围标头的地方提供的。当我将它们移回 CDN 时,这个问题就得到了解决,因为它必须是在明确支持流媒体的情况下构建的。

是对范围请求的正确响应的一个很好的解释。但对于在使用第三方托管服务时遇到此问题的任何人来说,只要知道他们可能不支持流媒体的范围标头就足够了。如果您想验证情况是否如此,您可以查询音频对象的持续时间。至少在 Safari 中,当无法成功发出范围请求时,持续时间会设置为无穷大,此时搜索将被禁用。