【问题标题】:Web Audio API and real current time when playing an audio file播放音频文件时的 Web Audio API 和实时当前时间
【发布时间】:2017-03-22 15:47:50
【问题描述】:

当我想知道使用 Web Audio API 播放文件的当前时间时,我遇到了问题。我的代码可以很好地播放文件,当涉及到快速加载的短文件时,getCurrentTime() 函数返回的当前时间足够准确。

但是当我尝试加载大文件时,有时getCurrentTime() 函数返回的当前时间是准确的,有时不是。有时,在等待例如 20 秒以听到文件播放后,当它开始播放时,它说当前时间约为 20 秒(这不是真的,因为它只是在播放文件的开头)。任何音频格式(OGG、MP3、WAV...)都会发生这种情况,但只是有时。

我使用的是慢速系统(Asus EEE PC 901,Intel Atom 1.60 Ghz 和 2 GB RAM,Windows XP Home Edition 和 SP3)和 Firefox 41.0.1。

我不确定,但似乎source.start() 方法开始播放声音的方式为时已晚,所以调用该方法后的行,我为startTime 变量设置值的地方,并不是真正的开始时间。

这里是代码(简化):

var context, buffer, startTime, source;
var stopped = true;
function load(file, startAt)
{
    //Here creates the AudioContext and loads the file through XHR (AJAX) and gets the buffer. All works fine.
    //When it gots the buffer through XHR (AJAX) and all is fine, it calls play(startAt) function immediately.
    //Note: normally, startAt is 0.
}

function play(startAt)
{
    source = context.createBufferSource(); //Context created before.
    source.buffer = buffer; //Buffer got before from XHR (AJAX).

    //Creates a gain node to be able to set the volume later:
    var gainNode = context.createGain();
    source.connect(gainNode);
    gainNode.connect(context.destination);

    //Plays the sound:
    source.loop = false;
    source.start(startAt, 0, buffer.duration - 3); //I don't want the last 3 seconds.

    //Stores the start time (useful for pause/resume):
    startTime = context.currentTime - startAt; //Here I store the startTime but maybe the file has still not begun to play (should it be just startTime = context.currentTime?).
    stopped = false;
}

function stop()
{
    source.stop(0);
    stopped = true;
}

function getCurrentTime()
{
    return (stopped) ? 0 : context.currentTime - startTime;
}

如何检测source.start() 方法何时开始播放文件?所以我可以在那个时候设置startTime 变量值,之前从来没有。

提前非常感谢您。我非常感谢任何形式的帮助。

【问题讨论】:

    标签: javascript html web-audio-api


    【解决方案1】:

    来自MDN(https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/start),关于start()函数的第一个参数:

    when(可选)

    在 AudioContext 使用的同一时间坐标系中,声音应该开始播放的时间(以秒为单位)。 如果when小于(AudioContext.currentTime,或者为0,则立即开始播放声音。默认值为0。

    您的代码没有明显的问题(尽管没有调用play() 的示例):如果您调用play(0)play(context.currentTime + someDelayInSeconds)start() 应该按预期运行。不幸的是,这里的问题是 AudioBufferSource 不适用于大文件。再次来自 AudioBuffer (https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer) 的 MDN 文档:

    这些类型的对象设计用于保存小型音频 sn-ps,通常小于 45 秒。

    我怀疑对于“声音立即开始播放”假设(我也经历过,虽然 20 秒似乎太多了......)。不幸的是,目前还没有办法在 WebAudio 中获取 AudioBufferSource 的确切开始时间。

    如果您没有任何真正的理由使用 AudioBufferSource 加载这个大文件,我建议您使用 MediaElementSourceNode (https://developer.mozilla.org/en-US/docs/Web/API/MediaElementAudioSourceNode):从链接文档上的示例中可以看到,它允许您将一个简单的 HTML5 Audio 元素插入 AudioContext。然后,您可以对元素本身进行所有通常的控制,即您还可以访问 audioElement.currentTime 属性,它告诉您当前的播放时间(在这种情况下是文件本身,这就是您所需要的)。此外,您不必在内存中处理文件的加载,并且可以在一些数据可用时立即开始播放。

    【讨论】:

      【解决方案2】:

      context.currentTime 从您创建上下文对象的那一刻开始计算。这意味着如果您的音频加载需要 20 秒,context.currentTime == 20

      为了解决这种延迟,您可以设置一个简单的计时器,从您创建上下文到音频加载完成。

      var context; //Create your context here
      var audioLoadStart = new Date();
      //Do audio load
      var audioLoadOffset = (new Date() - audioLoadStart) / 1000;
      currentTime = context.currentTime - audioLoadOffset - startTime;
      

      【讨论】:

      • 非常感谢您的回复。但是通过我的代码,我观察到以下情况:我调用 load() 函数(它创建了 AudioContnext),加载文件后,我等待 5 分钟调用 play 方法。按照你说的,现在的时间应该是5分钟以上。但是播放开始时显示的当前时间为零,这是正确的,这就是我想要的。如果 AudioContext 是在五分钟前创建的,为什么会发生这种情况?
      • 抱歉,我无法编辑上面的评论。请注意,每次我调用 play 方法时,我计算 startTime 时已经考虑了当前时间执行“startTime = context.currentTime - startAt;”。
      猜你喜欢
      • 1970-01-01
      • 2020-07-10
      • 1970-01-01
      • 1970-01-01
      • 2017-10-28
      • 2016-07-26
      • 2021-06-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多