Categories: Python

Python 使用 auditok 聲音活性偵測工具教學與範例

介紹如何在 Python 中使用 auditok 模組,偵測並分割聲音資料中有訊號(有人講話等)的區段。

Python 的 auditok 模組是一個聲音活性檢測工具,可以偵測聲音資料中是否存在訊號,可以處理即時的音訊輸入(例如麥克風)或是各種聲音檔案。

安裝 auditok 模組

auditok 模組可以透過 pip 安裝:

# 安裝 auditok 模組
pip install auditok

通常在分析聲音資料時,除了 auditok 之外,還會搭配一些其他的相關模組,所以建議一起安裝:

# 安裝相關模組
pip install pydub pyaudio tqdm matplotlib numpy

載入聲音資料

這裡我們從 zenodo 的網站上下載 Coughs: ESC-50 and FSDKaggle2018 咳嗽聲音資料,以這些資料做為示範。

引入 auditok 模組之後,使用 load() 函數載入 wav 聲音檔案:

import auditok

# 載入 wav 聲音檔案
region = auditok.load("data/coughs/fd8121bc.wav")

載入音訊之後,可以直接使用 plot() 函數繪製波形:

# 繪製波形圖
region.plot()
波形圖

如果音訊的開頭有一些沒有用的訊號,可以使用 skip 指定跳過的秒數:

# 跳過開頭 2 秒的音訊
region = auditok.load("data/coughs/fd8121bc.wav", skip=2)

這樣就可以跳過前 2 秒的資料,從 2 秒之後開始讀取。

偵測並分割聲音事件

split 函數可以根據聲音的訊號強弱,偵測出聲音事件(例如是否有人在講話),並將各個聲音事件分割出來,這個函數是 auditok 模組中最重要的函數之一,其常用的參數與意義如下:

min_dur
聲音事件的最短長度,單位為秒。如果這個值太高,會讓較短的聲音事件偵測不出來;如果這個值太低,可能會偵測出許多沒用的雜訊。
max_dur
聲音事件的最長長度,單位為秒。如果偵測到的聲音事件長度超過這個值,則超出的部分就會被截斷。
max_silence
聲音事件中容許無訊號(沒聲音)區段最長的長度,單位為秒。一個聲音事件中可能包含多個無訊號區段。
max_silence
聲音事件中容許無訊號(沒聲音)區段最長的長度,單位為秒。一個聲音事件中可能包含多個無訊號區段。
drop_trailing_silence
是否要去除聲音事件結尾處的無訊號區段,通常為了避免聲音太突兀,都會保留結尾的無訊號區段。
analysis_window
分析聲音用的窗(window)大小,單位為秒。
large_file
指定是否為大型檔案,用於直接指定檔案路徑的情況,僅支援 wav 與 raw 檔,可用的選項為 TrueFalse,若設定為 True 則可分批載入檔案,節省記憶體。
energy_threshold
偵測聲音事件的門檻值,當一段區間的各窗所計算出來的能量值超過這個門檻值的時候,該區間就會被視為一個聲音事件。預設值為 50,能量值的計算方式可參考 auditok 的官方文件

若要將剛剛讀取出來的 region 音訊資料進行偵測並分割聲音事件,可以執行:

# 偵測並分割聲音事件
audio_regions = region.split(
    min_dur=0.2,        # 聲音事件的最短長度
    max_dur=4,          # 聲音事件的最長長度
    max_silence=0.3,    # 聲音事件中無訊號最長長度
    energy_threshold=55 # 偵測聲音事件的能量門檻值
)

將聲音事件分割出來之後,可以透過迴圈逐一處理每一段音訊,或是將每一段音訊儲存成個別的聲音檔案:

# 輸出分割聲音事件結果
for i, r in enumerate(audio_regions):
    # 輸出每段分割音訊的起始與結束時間點
    print("Region {i}: {r.meta.start:.3f}s -- {r.meta.end:.3f}s".format(i=i, r=r))

    # 撥放每段分割音訊
    # r.play(progress_bar=True)

    # 儲存每段分割音訊
    filename = r.save("region_{meta.start:.3f}-{meta.end:.3f}.wav")
    print("儲存為:{}".format(filename))
Region 0: 0.150s -- 0.700s
儲存為:region_0.150-0.700.wav
Region 1: 1.450s -- 1.800s
儲存為:region_1.450-1.800.wav
Region 2: 1.900s -- 3.650s
儲存為:region_1.900-3.650.wav
Region 3: 5.450s -- 6.250s
儲存為:region_5.450-6.250.wav
Region 4: 8.600s -- 9.000s
儲存為:region_8.600-9.000.wav

繪製偵測結果圖形

如果需要透過圖形查看聲音事件的偵測結果,可以將 split() 改為 split_and_plot() 函數,參數用法都相同,只是替換函數名稱而已:

# 偵測並分割聲音事件,同時繪圖
audio_regions = region.split_and_plot(
    min_dur=0.2,        # 聲音事件的最短長度
    max_dur=4,          # 聲音事件的最長長度
    max_silence=0.3,    # 聲音事件中無訊號最長長度
    energy_threshold=55 # 偵測聲音事件的門檻值
)

這樣就會自動畫出聲音事件的偵測結果。

聲音事件偵測結果

大型檔案

如果要處理大型的聲音檔案,可以改用指定檔案路徑的方式來呼叫 split() 函數,並將 large_file 參數指定為 True,這樣可以讓 auditok 不要一次將整個檔案載入,改以分段批次處理的方式,以節省所需的記憶體:

# 處理大型檔案
audio_regions = auditok.split(
    "large_file.wav",   # 大型檔案
    min_dur=0.2,        # 聲音事件的最短長度
    max_dur=4,          # 聲音事件的最長長度
    max_silence=0.3,    # 聲音事件中無訊號最長長度
    energy_threshold=55,# 偵測聲音事件的能量門檻值
    large_file=True     # 處理大型檔案
)

auditok 指令工具

auditok 除了 Python 的模組之外,也同時提供了指令工具,基本概念與參數用法都跟 split() 函數類似:

# 使用 auditok 指令工具偵測聲音事件
auditok --min-duration 0.2 --max-duration 4 --max-silence 0.3 \
  --energy-threshold 55 data/coughs/fd8121bc.wav
1 0.190 0.710
2 0.790 1.220
3 1.460 1.790
4 1.900 3.690
5 4.760 5.070
6 5.460 6.250
7 8.590 9.020

auditok 指令預設會輸出每個聲音事件的起始與結束時間點。

我們也可以透過 --save-detections-as 儲存每段偵測到的聲音事件音訊:

# 儲存每段偵測到的聲音事件音訊
auditok --min-duration 0.2 --max-duration 4 --max-silence 0.3 \
  --energy-threshold 55 --save-detections-as "{id}_{start}_{end}.wav" \
  data/coughs/fd8121bc.wav

這樣就會將每段偵測到的聲音事件音訊,依據編號、起始與結束時間來儲存為不同的聲音檔案。

auditok 指令也可以使用 --plot 參數將聲音事件偵測結果畫出來,並以 --save-image 參數輸出的圖檔:

# 偵測聲音事件與繪圖
auditok --min-duration 0.2 --max-duration 4 --max-silence 0.3 \
  --energy-threshold 55 --plot --save-image "plot.png" \
  data/coughs/fd8121bc.wav
聲音事件偵測結果

auditok 指令也可以從標準輸入讀取聲音資料,例如:

# 從標準輸入讀取聲音資料
rec -q -t raw -r 16000 -c 1 -b 16 -e signed - | auditok - -r 16000 -w 2 -c 1

參考資料

Share
Published by
Office Guide

Recent Posts

Python 使用 PyAutoGUI 自動操作滑鼠與鍵盤

本篇介紹如何在 Python ...

1 年 ago

Ubuntu Linux 以 WireGuard 架設 VPN 伺服器教學與範例

本篇介紹如何在 Ubuntu ...

1 年 ago

Linux 網路設定 ip 指令用法教學與範例

本篇介紹如何在 Linux 系...

1 年 ago

Linux 以 Cryptsetup、LUKS 加密 USB 隨身碟教學與範例

介紹如何在 Linux 系統中...

1 年 ago