簡體   English   中英

通過 WebSockets 將音頻流式傳輸到 Web 音頻播放器

[英]Streaming audio through WebSockets to Web Audio player

我有一個有點工作的系統

  1. 在服務器上將音頻生成為 1 秒的 WAV 文件
  2. 讀取 WAV 文件並通過 websocket 發送
  3. Websocket 將二進制數據發送到 AudioContext.decodeAudioData
  4. 解碼的音頻被緩沖直到 4 個數據包(4 秒)
  5. 緩沖區被處理並發送到 AudioBufferSourceNode.start(time) where time = (clip_count * duration)

因此,如果我有 4 個音頻剪輯,則呼叫看起來像

AudioBufferSourceNode.start(0);
AudioBufferSourceNode.start(1);
AudioBufferSourceNode.start(2);
AudioBufferSourceNode.start(3);

我認為這可以完美地安排 4 秒的音頻,但我似乎面臨時鍾問題,也許是因為我希望音頻時鍾是完美的。 我已經使用增益節點來消除每個聲音片段之間的咔嗒聲(1 秒),但我立即或在很長一段時間后開始出現計時問題。 基本上,在最壞的情況下,我的音頻是這樣播放的

 ----------------------  -----------     -----------     -----------
| 1 second | 1 second |  |   950ms |     |  900ms  |    |   850ms  |
 ----------------------  -----------     -----------     -----------
                       gap          gap              gap

在此圖中,“1 秒”和“#ms”是正在播放的音頻量。 它應該總是 1 秒。 隨着音頻的進展,似乎也出現了間隙。 我想即使我告訴音頻上下文以 0 精確播放文件,它也很好,但其他預定的音頻剪輯可能會也可能不會准時。

這是正確的,還是我的系統中還有其他問題? 是否有 100% 的可靠性可以安排音頻剪輯在准確的時間播放,或者我是否需要添加一些計算來計算幾毫秒的 +/- 何時播放?

看起來服務於這個任務的東西是AudioWorkletNode

根據AudioBufferSourceNode 文檔

AudioBufferSourceNode 接口是一個 AudioScheduledSourceNode,它代表一個由內存中的音頻數據組成的音頻源,存儲在一個 AudioBuffer 中。 它對於播放對時間精度要求特別嚴格的音頻特別有用,例如必須匹配特定節奏並且可以保存在內存中而不是從磁盤或網絡播放的聲音。 要播放需要准確計時但必須從網絡流式傳輸或從磁盤播放的聲音,請使用 AudioWorkletNode來實現其播放。

本例正是實現了網絡流。 AudioBufferSourceNode並非設計為從網絡動態更新。

什么會導致不同步

  1. 由於 javascript 調度程序的性質,無法保證在准確的時間執行代碼。 節點可能同時執行另一項工作,導致信息發送延遲
  2. 定時器在發送完所有數據后運行下一個滴答,這可能需要一些時間
  3. 客戶端調度程序比服務器端調度程序有更多的限制。 通常,瀏覽器每秒可以執行大約 250 個計時器(每 4 毫秒一個)。
  4. 使用的 API 不是為該流程設計的

建議

  1. 始終保留緩沖區。 如果由於某種原因來自緩沖區的幀已經播放,那么更快地請求新的幀可能是合理的。
  2. 即時增加緩沖區。 收到兩條消息后就可以開始播放了,但是將動態緩沖消息的數量增加到大約 15 秒可能是合理的。
  3. 更喜歡使用其他工具來處理連接和數據傳輸。 Nginx 將完美服務。 如果客戶端連接緩慢,它將“保持”節點直到數據被傳輸。
  4. 如果連接中斷一秒鍾(例如在移動網絡上),應該有一些東西可以從正確的幀中恢復狀態,更新緩沖區並在不中斷的情況下執行所有這些操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM