移动设备上的HTML 5音频.play()延迟

时间:2015-03-11 02:02:02

标签: javascript jquery html html5 audio

我刚刚使用socket.io构建了一个实时应用程序,其中一个" master"用户可以在接收设备(桌面浏览器,移动浏览器)上触发声音。该主用户可以看到声音文件列表,并可以点击"播放"在声音文件上。

音频播放在浏览器上即时播放。然而,在手机上,延迟时间为0.5-2秒(我的Nexus 4和iPhone 5约为1秒,iPhone 3GS为1-2秒)。

我已经尝试了几项优化音频播放的功能,以便在手机上更快。现在(在最佳"阶段"它的优化我会说),我将所有的mp3组合在一个音频文件中(它创建.mp3,.ogg和。 mp4文件)。我需要有关如何进一步修复/改善此问题的想法。瓶颈似乎真的出现在hmtl 5音频方法中,例如.play()

在我使用的接收器上:

<audio id="audioFile" preload="auto">
  <source src="/output.m4a" type="audio/mp4"/>
  <source src="/output.mp3" type="audio/mpeg"/>
  <source src="/output.ogg" type="audio/ogg"/>
  <p>Your browser does not support HTML5 audio.</p>
</audio>

在我的JS中:

var audioFile = document.getElementById('audioFile');

  // Little hack for mobile, as only a user generated click will enable us to play the sounds
  $('#prepareAudioBtn').on('click', function () {
    $(this).hide();
    audioFile.play();
    audioFile.pause();
    audioFile.currentTime = 0;
  });

// Master user triggered a sound sprite to play
socket.on('playAudio', function (audioClip) {
  if (audioFile.paused)
    audioFile.play();

  audioFile.currentTime = audioClip.startTime;

  // checks every 750ms to pause the clip if the endTime has been reached. 
  // There is a second of "silence" between each sound sprite so the pause is sure to happen at a correct time.
  timeListener(audioClip.endTime);
});

function timeListener(clipEndTime) {
  this.clear = function () {
    clearInterval(interval);
    interval = null;
  };

  if (interval !== null) {
    this.clear();
  }

  interval = setInterval(function () {
    if (audioFile.currentTime >= clipEndTime) {
      audioFile.pause();
      this.clear();
    }
  }, 750);
}

对于每种声音也被认为是blob,但是有些声音可以持续几分钟,这就是为什么我将所有声音组合在一起用于1个大音频文件(优于页面上的几个audio标签夹)

4 个答案:

答案 0 :(得分:1)

我不是暂停/播放,而是在不应该播放时将音量设置为0,在应该播放时将音量设置为1。即使在iPhone 3GS上,Audio方法currentTimevolume也不会减慢音频播放速度。

我还在音频元素中添加了'loop'属性,因此不必再次.play()

将所有mp3声音组合在一起非常有成效,因为这种解决方案可以正常运行。

编辑:audioElement.muted = true或audioElement.muted = false更有意义。

Edit2:无法代表用户在iOS上控制音量,因此我必须暂停()并播放()音频元素,而不是将其静音和取消静音。

答案 1 :(得分:1)

在手机上进行测试时,我遇到了同样的延迟问题。我发现一些HTML 5游戏正在使用音频,因为游戏需要非常低的延迟。有些人正在使用SoundJS。我建议您尝试一下该库。

您可以在此处找到使用HTML Audio标签与使用SoundJS之间的速度比较:

http://www.nickfrazier.com/javascript/audio/ui/2016/08/14/js-sound-libraries.html

(在手机中进行测试以了解不同之处)

通过我的测试 SoundJS 更快。

实际上,它足以在游戏中使用,或在用户界面中用于声音反馈。

答案 2 :(得分:0)

由于preload属性,您的设置在桌面上运行良好。

不幸的是,这里Apple on the subject of preload

  

iOS上的Safari永远不会预加载。

这里MDN

  

注意:此值通常会在移动平台上被忽略。

移动平台正在进行权衡以节省电池和数据使用量,以便在用户实际与用户进行互动或以编程方式播放时加载媒体(autoplay通常不会用于类似原因)。

我认为您要做的最好的事情就是将您的曲目组合在一起,正如您所说的那样,所以您不必支付初始加载费用&#34;成本&#34;同样多。

答案 3 :(得分:0)

老问题,但这是我使用上面答案之一的解决方案:

const el = document.createElement("audio");
el.muted = true;
el.loop = true;

const source = document.createElement("source");
source.src = lineSe;
source.type = "audio/mpeg";

el.appendChild(source);

// need to call this function after user first interaction, or safari won't do it.
function firstPlay() {
    el.play();
}

let timeout = null;

function play() {
    // In case user press the button too fast, cancel last timeout
    if (lineSeTimeout) {
        clearTimeout(timeout);
    }

    // Back to beginning
    el.currentTime = 0;

    // unmute
    el.muted = false;

    // set to mute after the audio finish. In my case 500ms later
    // onended event won't work because loop=tue
    timeout = setTimeout(() => {
        // mute audio again
        el.muted = true;
    }, 500);
}