首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在音频中的特定点触发JavaScript事件

在音频中的特定点触发JavaScript事件
EN

Stack Overflow用户
提问于 2020-10-10 13:04:43
回答 1查看 162关注 0票数 0

我正在使用Audio对象在JavaScript中播放ogg文件。我试图同步视觉事件与音频的位置。

audio.ontimeupdate似乎以特定的规律性触发。是否有一种方法,我可以设置时间标记,并使事件的触发尽可能接近准确的时刻,音频播放的点在样本。

代码语言:javascript
复制
        let audio = new Audio(`audio/${filename}`);

        let timings = [1, 1.1, 1.2, 1.3, 1.4, 1.5, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5];
        audio.ontimeupdate = function () {
            let time = audio.currentTime;
            while (timings.length > 0 && timings[0] <= time) {
                console.log(`Waiting for ${timings[0]}, audio time = ${time} : late by ${time - timings[0]}`);
                timings.splice(0, 1);
            }
        }

这里的输出与订阅点不够接近。一个人迟到了一刻秒。

等待1,音频时间= 1.160022 : 0.1600220000000001

  • Waiting延迟1.1,音频时间= 1.160022 : 0.06002200000000002

  • =>等待1.2,音频时间= 1.441972 : 0.24197200000000008

  • Waiting延迟1.3,音频时间= 1.441972 : 0.141972

  • Waiting延迟1.4,音频时间= 1.441972 : 0.04197200000000012

  • Waiting延迟1.5,音频时间= 1.719637 : 0.21963700000000008

  • Waiting延迟2,音频时间= 2.000272 : 0.00027199999999982793

  • Waiting延迟2.1,音频时间= 2.277074 : 0.17707399999999973

  • Waiting延迟2.2,音频时间= 2.277074 : 0.07707399999999964

  • =>等待2.3,音频时间= 2.556553 : 0.25655300000000025

  • Waiting延迟2.4,音频时间= 2.556553 : 0.15655300000000016

  • Waiting延迟2.5,音频时间= 2.556553 :被0.056553000000000075

延迟

EN

回答 1

Stack Overflow用户

发布于 2020-10-10 20:15:28

我就是这么做的。我为第一个事件时间设置了一个超时,然后开始播放音频。

当事件被触发时,我会检查它是否太快(延迟播放音频),如果是的话,我会为nextEventTime - currentTime设置另一个超时。

当事件被触发且时间不太早时,我将事件时间排到将来的下一个值。这给了我一个大约20毫秒的差距,这绝对足够好!

代码语言:javascript
复制
class AudioClip {
    constructor(url, eventTimings) {
        this._audio = new Audio(url);
        this._filename = filename;
        this._eventTimings = eventTimings || [];
        this._timeoutId = null;
    }

    play() {
        if (!this._audio.paused) {
            return;
        }
        this._setTimeoutForNextEvent();
        this._audio.play();
    }

    pause() {
        if (this._audio.paused) {
            return;
        }
        this._clearTimeout();
        this._audio.pause();
    }

    dispose() {
        this.pause();
    }

    _setTimeoutForNextEvent() {
        let _this = this;

        this._clearTimeout(this);
        if (this._eventTimings.length > 0) {
            let delayMs = this._eventTimings[0] - (this._audio.currentTime * 1000);
            this._timeoutId = setTimeout(() => { _this._triggerCurrentEvent(); }, delayMs);
        }
    }

    _triggerCurrentEvent() {
        this._clearTimeout();

        // If we are too early, wait
        let nextEventTimeSeconds = this._eventTimings[0] / 1000;
        let audioTime = this._audio.currentTime;
        if (audioTime < nextEventTimeSeconds) {
            this._setTimeoutForNextEvent();
            return;
        }

        // Otherwise, trigger the event
        while (this._eventTimings.length > 0 && this._eventTimings[0] <= audioTime) {
            console.log(`At ${this._audio.currentTime}: Event = ${this._eventTimings[0]}`);
            this._eventTimings.splice(0, 1);
        }
        this._setTimeoutForNextEvent(this);
    }

    _clearTimeout() {
        if (this._timeoutId) {
            clearTimeout(this._timeoutId);
            this._timeoutId = null;
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64293756

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档