2024-01-16|閱讀時間 ‧ 約 26 分鐘

【💊 Python的解憂錦囊】soundfile Not allowed for existing files (e

我們在處理音檔時常常會使用到 [soundfile](https://pypi.org/project/soundfile/) 這套工具, 當我們試圖讀取檔案時卻發生了這樣的錯誤訊息…

TypeError: Not allowed for existing files (except 'RAW'): samplerate, channels, format, subtype, endian


用於讀取和寫入音頻文件。它提供了一種簡單而靈活的方式來處理各種音頻格式的數據,例如 WAV、FLAC、AIFF、OGG 等等。


關於 soundfile

  • 讀取和寫入音頻文件:支持多種常見音頻格式的讀取和寫入,包括但不限於 WAV、FLAC、AIFF、OGG 等。
  • 與 NumPy 整合:可以方便地將音頻數據加載到 NumPy 陣列中,這使得對音頻數據進行分析和處理變得更加容易和靈活。
  • 支持不同採樣率和位深度:可以處理不同採樣率和位深度的音頻文件。
  • 跨平台支持soundfile 跨平台運行,在 Windows、MacOS 和 Linux 等操作系統上都能夠使用。

使用 soundfile 可以讓使用者輕鬆地處理音頻文件,從而進行聲音處理、信號處理、音樂分析等各種應用。


讀取檔案時很正常 😁

簡單的讀取音檔我們可以這樣做。

data, samplerate = sf.read('existing_file.wav')


這樣的讀取方式沒問題, soundfile 會根據我們的副檔名進行相關的格式轉換, 但凡事總有一些例外狀況。


當我們讀取來自網路傳輸的資料時, 卻… 😟

處理音訊時, 通常我們不會一次的連接就傳送所有的資料, 這樣對於效率來說太沒效率了, 尤其是大檔案, 我們通常會搭配websocket + asyncio來接收傳送的檔案並處理, 因此假設我們的伺服端皆收到檔案資料並試圖解碼時…

message = await socket.recv()
if message == 'Done':
return None, None

with io.BytesIO(message) as file:
message, _ = sf.read(
file=file,
dtype='float32',
format='WAV',
)

這時候就發生了以下狀況:

TypeError: Not allowed for existing files (except 'RAW'): samplerate, channels, format, subtype, endian


究竟是為什麼呢? 讓我們來好好探索一番 🕵️

首先我們根據線索查到原始碼區段, 🔍 請參考這裡


原來是當我們的來源不是RAW時, 不允許隨意去更改 samplerate, channels, format, subtype, endian 這些屬性。

如何解決?

那麼如此一來事情就簡單了。

  1. 格式為 RAW, 自行填入取樣率、頻道、格式…等資訊。
message, _ = sf.read(
file=file,
dtype='float32',
format='RAW',
subtype='PCM_16',
samplerate='16000',
channels=1,
endian='FILE',
)
  1. 直接讀取, 不更改取樣率、頻道、格式…等資訊。
message, _ = sf.read(
file=file,
dtype='float32'
)

結語

音訊處理果然又是一個坑,相較於單純的文字處理, 需要具備更多底層的知識, 雖然困難, 但掌握起來後成就感會非常的大, 因此我們應該勇於學習, 讓自己的實力更加深厚, 共勉之。

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.