博客 / 詳情

返回

WEBRTC+FFMPEG+RNN 服務端實現通話背景噪聲消除

WEBRTC+FFMPEG+RNN 服務端實現通話背景噪聲消除

created by snowlyg

開源的 webrtc 項目本身內置了對音頻信號的3A算法,包括回聲消除(AEC)、噪聲抑制(ANS)、自動增益控制(AGC), 這個三個算法配合在發聲端對音頻數據進程處理,可以提高音頻質量和通話效果。

但是 webrtc 畢竟是國外的開源項目,國內的小廠商的硬件大部分都無法很好適配,而且一些低端產品的麥克風和揚聲器質量不太行,導致實際的通話效果並不理想。

小廠商的產品線又不穩定。可能過幾個月,之前的產品就淘汰了。所以修改 webrtc 項目去做適配不僅費時費力,而且很可能最終成為無用功。

在服務端中間層對音頻處理之後再發送到遠端設備,是另一種可行的解決方案。

需求依賴

  • ffmpeg
  • opus
  • webrtc
  • models

項目樣例採用開源項目 https://github.com/pion/webrtc/tree/master/examples/save-to-disk 。

  1. 編譯 save-to-disk 樣例,生成 save-to-disk 執行文件
git clone https://github.com/pion/webrtc --depth=1 
cd webrtc/[examples/save-to-disk](https://github.com/pion/webrtc/tree/master/examples/save-to-disk)
go build
  1. 在瀏覽器打開 https://jsfiddle.net/2nwt1vjq/ 地址,點擊 Copy browser SDP to clipboard 按鈕,複製瀏覽器 SDP 信息。

6585a7dd-9b74-4366-a169-d21f995c5e7d.png

  1. 執行 save-to-disk 執行文件並帶上 複製的瀏覽器SDP 信息,將控制枱輸出的 sdp 信息複製到瀏覽器的第二個輸入框,並點擊 Start Session 按鈕。

企業微信截圖_17591369315774.png

  1. 瀏覽器能看到 connected 輸出,説明 webrtc 建立完成。

bc81ccc4-1440-40ec-9a6a-78bfe1550ae8.png

同時控制枱看到正在保持 .opus 和 .ivf 文件,通過 Audacity 軟件查看可以發現有明顯的背景噪聲。

99cf9525-acb4-45d9-946c-6bc1b0e2922f.png

接下來需要花費幾分鐘時間,增加相關邏輯來消除相關噪聲

步驟分別為:

  1. OnTrack 回調方法中解碼 webrtc 音頻數據為 PCM 數據流
  2. PCM 通過 FFMPEG 過濾器將數據降噪,再重新將處理好的數據發回 webrtc

Webrtc 默認採用 opus 音頻格式,採用 https://github.com/hraban/opus/tree/v2 項目來解碼音頻數據會比較合適。

如果沒有 opus 編碼庫依賴,可以使用 https://github.com/xiph/opus 項目編譯。

var sampleRate = 48000
var channels = 2
var frameSizeMs int = 20 // if you don't know, go with 60 ms.
frameSize := channels * frameSizeMs * sampleRate / 1000
pcm := make([]int16, int(frameSize))
dec, err := opus.NewDecoder(sampleRate, channels)
if err != nil {
    return
}
for {
    packet, _, err := track.ReadRTP()
    if err != nil {
        return
    }
    n, err := dec.Decode(packet.Payload, pcm)
    if err != nil {
        return
    }
    pcm = pcm[:n*channels]

    buf := new(bytes.Buffer)
    // Write the int16 to the buffer, specifying the byte order (e.g., LittleEndian)
    if err := binary.Write(buf, binary.LittleEndian, pcm); err != nil {
        return
    }
}

把解碼後的數據發送到 ffmpeg 可以通過 pipe:0 通道傳輸

cmd := exec.Command("ffmpeg", "-v", "verbose", "-f", "s32le", "-i", "pipe:0", "-ac", "2", "-ar", "48000", "-af", "arnndn=m=models/cb.rnnn", "-vn", "-b:a", "64k", "-c:a", "libopus", "output_rnn.opus")

重複之前的信令複製過程,控制枱會顯示 ffmpeg 命令的輸出內容如下:

企業微信截圖_17591922956553.png

輸出文件為 output_rnn.opus 通過 Audacity 軟件查看可以發現之前明顯的背景噪聲,現在幾乎全部消失了。

c4e45bcb-7aad-48e9-87a2-c03cc0bd241b.png

FFMPEG 音頻過濾器還支持很多其它的效果,比如 動態均衡、混音、濾波 等等。

具體介紹可以查看 官方文檔。

完整代碼地址 https://github.com/snowlyg/webrtc_denoise_use_ffmpge

參考

  • https://github.com/pion/webrtc
  • https://ffmpeg.org/ffmpeg-filters.html
  • https://github.com/richardpl/arnndn-models
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.