我們在處理音檔時常常會使用到 [soundfile](https://pypi.org/project/soundfile/) 這套工具, 當我們試圖讀取檔案時卻發生了這樣的錯誤訊息…
TypeError: Not allowed for existing files (except 'RAW'): samplerate, channels, format, subtype, endian
關於 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 這些屬性。
如何解決?
那麼如此一來事情就簡單了。
- 格式為 RAW, 自行填入取樣率、頻道、格式…等資訊。
message, _ = sf.read(
file=file,
dtype='float32',
format='RAW',
subtype='PCM_16',
samplerate='16000',
channels=1,
endian='FILE',
)
- 直接讀取, 不更改取樣率、頻道、格式…等資訊。
message, _ = sf.read(
file=file,
dtype='float32'
)
結語
音訊處理果然又是一個坑,相較於單純的文字處理, 需要具備更多底層的知識, 雖然困難, 但掌握起來後成就感會非常的大, 因此我們應該勇於學習, 讓自己的實力更加深厚, 共勉之。