2013-12-18 64 views
5

正如在previous question中所討論的,我已經建立了一個原型(使用MVC Web API,NAudio和NAudio.Lame),將其轉換爲mp3之後流式傳輸低質量音頻。源流是PCM:8K,16位,單聲道,我正在使用html5的音頻標籤。HTML5 <audio> LIVE streaming的不好選擇?

Chrome和IE11存在15-34第二延遲(高延遲)音頻從中,我告訴瀏覽器聽說過,是我們的最終用戶無法接受的。理想情況下,延遲時間不會超過5秒。即使在我的音頻標籤中使用preload =「none」屬性時也會出現延遲。

仔細觀察這個問題,看起來好像兩個瀏覽器在他們接收到~32K的音頻數據之前都不會開始播放音頻。考慮到這一點,我可以通過更改Lame的MP3'比特率'設置來影響延遲。但是,如果我減少延遲(通過向瀏覽器發送更多數據到相同長度的音頻),稍後我會引入音頻丟失。

實例:

  • 如果我使用拉梅V0編碼延遲爲近34秒,這需要幾乎0.5 MB源的音頻。
  • 如果我使用Lame的ABR_32編碼,我可以將延遲減少到10-15秒,但在整個聽音過程中我會遇到暫停和退出。

問題

  1. 任何想法如何,我可以最小化啓動延遲(潛伏期)?
  2. 我是否應該繼續研究各種Lame'預設',希望能選擇「正確」的?
  3. 難道說MP3是不是最佳格式爲直播流?
  4. 切換到Ogg/Vorbis(或Ogg/OPUS)有幫助嗎?
  5. 我們是否需要放棄 HTML5的音頻標籤並使用Flash或Java applet?

謝謝。

回答

4

由於您無法控制瀏覽器代碼和緩衝大小,因此無法減少延遲。 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; 
}