HTML5 <audio> LIVE流媒体的糟糕选择?</audio>

时间:2013-12-18 16:17:25

标签: html5 audio mp3 live-streaming lame

正如在previous question中讨论的那样,我已经构建了一个原型(使用MVC Web API,NAudio和NAudio.Lame),在将其转换为mp3后实时流式传输低质量音频。源流是PCM:8K,16位,单声道,我正在使用html5的音频标签。

两者 Chrome和IE11上,在从浏览器听到音频之前有一个 15-34秒延迟(高延迟),我被告知,对我们的最终用户来说是不可接受的。理想情况下,延迟不会超过 5秒。即使在我的音频标签中使用preload =“none”属性,也会发生延迟。

仔细观察这个问题,似乎两个浏览器在收到~32K音频数据之前不会开始播放音频。考虑到这一点,我可以通过更改Lame的MP3'比特率'设置来影响延迟。但是,如果我减少延迟(通过向浏览器发送更多数据以获得相同长度的音频),我将在稍后介绍音频丢失。

示例:

  • 如果我使用Lame的V0编码,延迟将近34秒,这需要近0.5 MB的源音频。
  • 如果我使用Lame的ABR_32编码,我可以将延迟减少到10-15秒,但我会在整个听力会话中遇到暂停和辍学。

问题

  1. 任何想法如何最小化启动延迟(延迟)?
  2. 我是否应该继续调查各种Lame'预设'以期选择“正确的”?
  3. 实时流媒体的最佳格式是
  4. 切换到Ogg / Vorbis(或Ogg / OPUS)会有帮助吗?
  5. 我们是否需要放弃 HTML5的音频代码并使用Flash或Java小程序?
  6. 感谢。

1 个答案:

答案 0 :(得分:5)

您无法减少延迟,因为您无法控制浏览器代码和缓冲大小。 HTML5规范没有强制执行任何约束,因此我没有看到任何改进的原因。

然而,您可以使用webaudio API实现解决方案(它非常简单),您可以自己处理流式传输。

如果您可以将固定大小的MP3块分开(以便事先知道每个MP3块大小,或者至少在接收时间),那么您可以使用20行代码进行实时流式传输。块大小将是您的延迟。

关键是使用AudioContext :: decodeAudioData。

// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var offset = 0;
var byteOffset = 0;
var minDecodeSize = 16384; // This is your chunk size

var request = new XMLHttpRequest();
request.onprogress = function(evt)
{
   if (request.response)
   {
       var size = request.response.length - byteOffset;
       if (size < minDecodeSize) return;
       // In Chrome, XHR stream mode gives text, not ArrayBuffer.
       // If in Firefox, you can get an ArrayBuffer as is
       var buf;
       if (request.response instanceof ArrayBuffer)
           buf = request.response;
       else
       { 
           ab = new ArrayBuffer(size);
           buf = new Uint8Array(ab);
           for (var i = 0; i < size; i++) 
               buf[i] = request.response.charCodeAt(i + byteOffset) & 0xff;
       }
       byteOffset = request.response.length;
       context.decodeAudioData(ab, function(buffer) {
           playSound(buffer);
       }, onError);
   }
};
request.open('GET', url, true);
request.responseType = expectedType; // 'stream' in chrome, 'moz-chunked-arraybuffer' in firefox, 'ms-stream' in IE
request.overrideMimeType('text/plain; charset=x-user-defined');
request.send(null);

function playSound(buffer) {
    var source = context.createBufferSource(); // creates a sound source
    source.buffer = buffer;                    // tell the source which sound to play
    source.connect(context.destination);       // connect the source to the context's destination (the speakers)
    source.start(offset);                           // play the source now
                                           // note: on older systems, may have to use deprecated noteOn(time);
    offset += buffer.duration;
}