2017-04-12 12 views
2

我有一臺服務器通過websocket發送原始音頻塊。我們的想法是檢索並播放它們,以儘可能平滑播放。流式處理原始音頻數據期間在webaudio播放中出現裂縫

這裏是代碼最重要的一塊:

ws.onmessage = function (event) { 
    var view = new Int16Array(event.data); 
    var viewf = new Float32Array(view.length); 

    audioBuffer = audioCtx.createBuffer(1, viewf.length, 22050); 
    audioBuffer.getChannelData(0).set(viewf); 
    source = audioCtx.createBufferSource(); 
    source.buffer = audioBuffer; 
    source.connect(audioCtx.destination); 
    source.start(0); 
}; 

這工作體面的好,但也有在播放一些裂縫:網絡延遲並不恆定,所以數據的最新塊沒有按」到達前一個正在播放的結尾,所以我可以結束兩個緩衝區一起玩一會兒或者根本不玩。

我想:

  • source.onended玩下一個,但它不是無縫的:有每塊的尾部裂紋,而每個接縫的整體累積使回放越說越比流更晚。
  • 將新數據追加到當前正在播放的緩衝區中,但這似乎是被禁止的:緩衝區的大小是固定的。

有沒有適當的解決方案來解決這個問題?唯一的要求是播放來自websocket的未壓縮音頻。

編輯:解決方法:鑑於我知道我的緩衝區長度,我可以安排播放這樣:

if(nextStartTime == 0) nextStartTime = audioCtx.currentTime + (audioBuffer.length/audioBuffer.sampleRate)/2; 
source.start(nextStartTime); 
nextStartTime += audioBuffer.length/audioBuffer.sampleRate; 

第一次,我安排播放的開始半個buffer-以後再允許最大的意外延遲。然後,我將下一個緩衝區開始時間存儲在緩衝區末尾。

回答

2

您應該從https://www.html5rocks.com/en/tutorials/audio/scheduling/開始,它很好地解釋瞭如何在WebAudio中安排時間。

對於您的使用案例,您還應該利用這一事實,即您知道PCM樣本的採樣率,並知道您已閱讀了多少樣本。這決定了播放緩衝區需要多長時間。用它來確定何時安排下一個緩衝區。

(但要注意的是,如果PCM採樣速率是不一樣的audioCtx.sampleRate,數據將被重新採樣,這可能會弄亂你的時間。

+0

謝謝,這是我所做的,而不是簡單的「現在玩」。我現在有一些聽起來更好的東西! – Ploppe

0

有一個更好的方式來處理這個問題,這些天...考慮使用Media Source擴展

相反不得不安排緩衝區並自己做所有事情,你基本上會將接收到的數據轉儲到緩衝區中,並讓瀏覽器擔心緩衝播放,就好像它是通過HTTP的文件一樣。

Chrome支持播放WAV文件。由於您的數據處於原始PCM中,因此您需要僞裝WAV文件標頭。幸運的是,這並不難:http://soundfile.sapp.org/doc/WaveFormat/

+0

不幸的是,媒體源擴展目前不支持WAV .. :(https://github.com/w3c/media-source/issues/55 – bertrandg

+0

嗨,布拉德,你有任何鏈接顯示如何使用MediaSource解碼MP3數據塊來自套接字? –