簡體   English   中英

將音頻文件轉換為線性 PCM 16 位

[英]convert audio file to Linear PCM 16-bit

我正在嘗試通過 websocket 發送音頻文件,我意識到為此我需要將 mp3 文件轉換為線性 PCM 16 位代碼,但我找不到這樣做的方法。

這是我想做的:

 let mp3File = // the 16-bit pcm file 

    ws.on('message', async(msg) => {
        if (typeof msg === "string") {

        } else if (recognizeStream) {
            recognizeStream.write(msg);
        }
        ws.send(mp3File) <== stream back the audio file
    });
});

一些背景,stream 是一個電話(通過 vonage api)所以 ny ws 連接到電話並聽到用戶輸入,然后在我的服務器上進行一些邏輯之后,我想向用戶播放一個本地文件的 mp3 文件在我的服務器中,通過 ws.send()。

- - - - - -更新 - - - -

現在,如果我從 stream 發送 pcm 數據(來自電話的原始音頻)它的工作原理(服務器回顯電話)所以我想將 mp3 文件轉換為相同的格式,以便我可以通過 ws 發送它。發送()。

------------更新2--------

在以正確的格式制作我的音頻文件后:“Linear PCM 16-bit, with a 8kHz or a 16kHz sample rate, and a 20ms frame size”

我正在嘗試通過 web 套接字發送文件但我不知道該怎么做任何事物。

我正在嘗試執行此處指定的操作: 在此處輸入圖像描述

首先讓我們了解這意味着什么:

線性 PCM 16 位,采樣率為 8kHz 或 16kHz,幀大小為 20ms

他們在這里談論兩件事:

  1. 音頻數據的格式,即“線性 PCM 16 位,采樣率為 8kHz 或 16kHz”
  2. 您如何將此音頻數據發送給他們以及他們如何將其發送給您:以價值 20 毫秒幀的音頻數據塊

根據音頻格式,如果選擇“16bit Linear PCM with sample rate of 16K”意味着:

  • 采樣率 = 16000
  • 樣本寬度 = 16 位 = 2 字節

因此 1 秒的音頻塊將包含字節 = (16000 * 2) = 32000 字節,這意味着 20 毫秒/0.02 秒的音頻幀將相當於 (32000*0.2) = 640 字節

需要做兩件事:

  1. 將mp3轉換為wav。 在您的系統上安裝 ffmpeg 並運行此命令
    ffmpeg -i filename.mp3 -ar 16000 -sample_fmt s16 output.wav
    這會將您的filename.mp3轉換為output.wav ,這將是 16K 采樣率的線性 PCM 16 位

  2. 在您的代碼中,當您發回音頻時,您需要將stream 作為 640 字節的塊,而不是一次性發送整個文件數據 有 3 個選項:

    • 運行一個循環,將所有音頻寫入 websocket,但以 640 字節為單位。 但這有一個問題,Nexmo 只會緩沖前 20 秒的音頻。 超出此范圍的任何內容都將被丟棄
    • 啟動一個每 20ms 運行一次的異步任務,並將 640 字節的數據寫入 websocket。
    • 當您從nexmo 獲取音頻時寫入(這是我將展示的) 因為nexmo 將每20 毫秒向您發送640 字節,您可以同時發送回640 字節。

我正在使用 npm websocket package 編寫此示例。

var fs = require('fs');
var binaryData = fs.readFileSync('output.wav');
var start = 44 // discard the wav header
var chunkSize = 640

...

// ws is a websocket connection object
connection.on('message', function(message) {
  if (message.type === 'utf8') {
    // handle a text message here
  }
  else if (message.type === 'binary') {
    // print length  of audio sent by nexmo. will be 640 for 16K and 320 for 8K 
    console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');

    if (start >= binaryData.length) {
      // slice a chunk and send
      toSend = binaryData.slice(start, start + chunkSize)
      start = start + chunkSize
      connection.sendBytes(toSend); 
      console.log('Sent Binary Message of ' + toSend.length + ' bytes');
    } 
  } ...
  
});

請記住,從您將音頻從服務器發送到 nexmo 到您在另一端收聽的時間點會有一些延遲。 根據 Nexmo 數據中心的位置、運行代碼的服務器的位置、網絡速度等,它可以從半秒到更多。我觀察到它接近 0.5 秒。

暫無
暫無

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

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