如何在HTML5中停止和恢复实时音频流而不是暂停它?

时间:2014-12-02 20:18:30

标签: html html5 audio html5-audio audio-streaming

我在HTML5中构建一个简单的音频流元素时出现的一个显着问题是,<audio>标记的行为与人们对播放和暂停实时音频流。

我使用最基本的HTML5代码来传输音频,<audio>标记带有控件,其源代码是实时流,可在此处演示:http://jsfiddle.net/uzzz03ha/ < / p>

当前结果:首次播放流时,它会按预期播放正在播放的内容。但是,当它暂停并再次播放时,音频会在之前暂停流时从其停止的位置恢复。用户现在正在侦听流的延迟版本。这种情况不是特定于浏览器的。

期望的结果:当流暂停时,我希望流停止。当它再次播放时,我希望它恢复当前流所在的位置,而不是用户暂停流时的位置。

有没有人知道如何让这个音频流在暂停后正常恢复?

我为修复这个问题做了一些失败的尝试:

  • 更改音频元素的currentTime对流音频无效。
  • 我在用户停止流播放时从DOM中删除了音频元素,并在用户恢复播放时将其添加回来。流仍然在用户离开的地方继续,更糟糕的是在幕后下载另一个流副本。
  • 每次播放流时,我都会在流URL的末尾添加一个随机GET变量,试图欺骗浏览器相信它正在播放新的流。播放仍会在用户暂停播放的位置恢复。

4 个答案:

答案 0 :(得分:5)

停止流,然后再次启动它的最佳方法似乎是删除源然后调用load:

var sourceElement = document.querySelector("source");
var originalSourceUrl = sourceElement.getAttribute("src");
var audioElement = document.querySelector("audio");

function pause() {
    sourceElement.setAttribute("src", "");
    audioElement.pause();
    // settimeout, otherwise pause event is not raised normally
    setTimeout(function () { 
        audioElement.load(); // This stops the stream from downloading
    });
}

function play() {
    if (!sourceElement.getAttribute("src")) {
        sourceElement.setAttribute("src", originalSourceUrl);
        audioElement.load(); // This restarts the stream download
    }
    audioElement.play();
}

答案 1 :(得分:1)

我在解决此问题时提出的一个解决方案是完全忽略音频元素上的播放和暂停功能,并在用户希望停止播放然后设置音量属性时将音频元素的音量属性设置为0当用户希望恢复播放时返回1.

如果你使用jQuery(also demonstrated in this fiddle),这样一个函数的JavaScript代码看起来很像:

/*
 * Play/Stop Live Audio Streams
 * "audioElement" should be a jQuery object
 */
function streamPlayStop(audioElement) {
  if (audioElement[0].paused) {
    audioElement[0].play();
  } else if (!audioElement[0].volume) {
    audioElement[0].volume = 1;
  } else {
    audioElement[0].volume = 0;
  }
}

我应该提醒一下,尽管这可以实现停止和恢复实时音频流所需的功能,但它并不理想,因为当停止时,流实际上仍在播放并在后台下载,使用了带宽。处理。

但是,此解决方案不一定比在流式音频元素上使用.play().pause()占用更多带宽。简单地使用带有流式音频的audio标签会占用大量带宽,因为一旦播放流式音频,它会在暂停时继续在后台下载流的内容。


应该注意,由于purposefully built-in limitations for iPhones and iPads,此方法在iOS 中不起作用:

  

在iOS设备上,音频级别始终在用户的物理控制之下。 volume属性在JavaScript中无法设置。阅读volume属性始终返回1

如果您选择使用此答案中的解决方法,则需要为正常使用play()pause()功能的iOS设备创建备用,否则您的界面将无法暂停流。

答案 2 :(得分:1)

当您要停止从流中下载文件时,重置音频源并调用load()方法似乎是最简单的解决方案。

由于是流媒体,因此浏览器仅在用户离线时才停止下载。必须进行重置,以防止用户刻录其蜂窝数据或避免提供浏览器暂停音频时下载的过时内容。

请记住,尽管当source属性设置为空字符串时,例如audio.src = "",音频源将改为设置为页面的主机名。如果您使用随机词,则会将该词作为路径附加。

因此,如下所示,设置audio.src =""表示audio.src === "https://stacksnippets.net/js"。设置audio.src="meow"将使源成为audio.src === "https://stacksnippets.net/js/meow"。因此3d段落不可见。

const audio1 = document.getElementById('audio1');
const audio2 = document.getElementById('audio2');
document.getElementById('p1').innerHTML = `First audio source: ${audio1.src}`;
document.getElementById('p2').innerHTML = `Second audio source: ${audio2.src}`;

if (audio1.src === "") {
  document.getElementById('p3').innerHTML = "You can see me because the audio source is set to an empty string";
}
<audio id="audio1" src=""></audio>
<audio id="audio2" src="meow"></audio>

<p id="p1"></p>

<p id="p2"></p>

<p id="p3"></p>

如果确实在特定时刻依赖音频的来源,请注意这种行为。使用about URI scheme似乎可以欺骗它,使其表现出更可靠的方式。因此,使用“ about:”或“ about:about”,“ about:blank”等可以正常工作。

const resetAudioSource = "about:"

const audio = document.getElementById('audio');
audio.src = resetAudioSource;

document.getElementById('p1').innerHTML = `Audio source: -- "${audio.src}"`;

// Somewhere else in your code...

if (audio.src === resetAudioSource){
  document.getElementById('p2').innerHTML = "You can see me because you reset the audio source."
}
<audio id="audio"></audio>
<p id="p1"></p>
<p id="p2"></p>

重置audio.src并调用.load()方法将使音频尝试加载新的源。如果您想在加载音频时显示一个微调器组件,但又不想在重置音频源时也显示该组件,则上面的方法很方便。

可以在此处找到一个有效的示例:https://jsfiddle.net/v2xuczrq/

如果使用随机单词重置了音源,那么当您还暂停音频或直到onError事件处理程序捕获到音频时,可能会显示加载器。 https://jsfiddle.net/jcwvue0s/

更新:字符串“ javascript :;”和“ javascript:void(0)”可以代替“ about:” URI来使用,这似乎效果更好,因为它还将停止由“ about:”引起的控制台警告。

答案 3 :(得分:-2)

不幸的是,HTML5中的音频流有点用词不当,因为它实际上并不是直播。 HTML5需要一个音频文件(.wav,.mp3等)来尝试下载。它不接受实时流媒体格式(在线广播,流式PCM数据等)。

您的jsfiddle.net/uzzz03ha/示例并非使用实时音频流,而是使用预先录制的文件。 HTML5稍微缓冲这个文件,然后播放它。暂停和恢复音频会暂停时间,因为它知道&#34;它是一个预先录制的文件。 Cole的回答可以帮助你解决暂停/播放问题,但是你仍然会遇到html5不接受直播流的问题。你也必须自己解决这个问题。

所以,不幸的是,我没有回答你的问题,因为我在尝试解决同样的问题时发现了你的问题。这篇文章可能会帮助您指明正确的方向:Play live audio stream - html5