运行PyTorch音频预处理教程代码遇LibsndfileError求助
PyTorch音频元数据读取报错问题解决
问题场景
学习PyTorch音频预处理教程时,运行以下代码获取远程WAV文件的元数据时抛出错误:
print("Source:", SAMPLE_WAV_URL) with requests.get(SAMPLE_WAV_URL, stream=True) as response: metadata = torchaudio.info(response.raw) print(metadata)
错误输出
Source: https://pytorch-tutorial-assets.s3.amazonaws.com/steam-train-whistle-daniel_simon.wav 忽略cffi回调函数<function SoundFile._init_virtual_io.<locals>.vio_get_filelen at 0x000002487DE62C10>的异常: 回溯(最近的调用最后): 文件 "C:\Users\me\anaconda3\envs\myenv\lib\site-packages\soundfile.py", line 1228, in vio_get_filelen file.seek(0, SEEK_END) io.UnsupportedOperation: seek --------------------------------------------------------------------------- LibsndfileError Traceback (most recent call last) 输入 In [5], in <cell line: 2>() 1 print("Source:", SAMPLE_WAV_URL) 2 with requests.get(SAMPLE_WAV_URL, stream=True) as response: ----> 3 metadata = torchaudio.info(response.raw) 4 print(metadata) 文件 ~\anaconda3\envs\myenv\lib\site-packages\torchaudio\backend\soundfile_backend.py:103, in info(filepath, format) 84 @_mod_utils.requires_soundfile() 85 def info(filepath: str, format: Optional[str] = None) -> AudioMetaData: 86 """获取音频文件的信号信息。 87 88 注意: (...) 101 102 """ --> 103 sinfo = soundfile.info(filepath) 104 return AudioMetaData( 105 sinfo.samplerate, 106 sinfo.frames, (...) 109 encoding=_get_encoding(sinfo.format, sinfo.subtype), 110 ) 文件 ~\anaconda3\envs\myenv\lib\site-packages\soundfile.py:464, in info(file, verbose) 456 def info(file, verbose=False): 457 """返回包含SoundFile信息的对象。 458 459 参数: (...) 462 是否打印额外信息。 463 """ --> 464 return _SoundFileInfo(file, verbose) 文件 ~\anaconda3\envs\myenv\lib\site-packages\soundfile.py:409, in _SoundFileInfo.__init__(self, file, verbose) 407 def __init__(self, file, verbose): 408 self.verbose = verbose --> 409 with SoundFile(file) as f: 410 self.name = f.name 411 self.samplerate = f.samplerate 文件 ~\anaconda3\envs\myenv\lib\site-packages\soundfile.py:655, in SoundFile.__init__(self, file, mode, samplerate, channels, subtype, endian, format, closefd) 652 self._mode = mode 653 self._info = _create_info_struct(file, mode, samplerate, channels, 654 format, subtype, endian) --> 655 self._file = self._open(file, mode_int, closefd) 656 如果set(mode).issuperset('r+')且self.seekable(): 657 # 像Python文件对象一样将写入位置移到0 658 self.seek(0) 文件 ~\anaconda3\envs\myenv\lib\site-packages\soundfile.py:1213, in SoundFile._open(self, file, mode_int, closefd) 1210 如果file_ptr == _ffi.NULL: 1211 # 获取实际错误代码 1212 err = _snd.sf_error(file_ptr) --> 1213 raise LibsndfileError(err, prefix="打开{0!r}时出错: ".format(self.name)) 1214 如果mode_int == _snd.SFM_WRITE: 1215 # 由于libsndfile版本<=1.0.25的bug,以SFM_WRITE模式打开命名管道时frames != 0 1216 # 参见http://github.com/erikd/libsndfile/issues/77。 1217 self._info.frames = 0
最终错误提示:
LibsndfileError: 打开<urllib3.response.HTTPResponse object at 0x000002487DDD02B0>时出错: WAV文件错误。找不到'data'块标记。
问题原因
requests.get(..., stream=True)返回的response.raw是单向流式HTTP响应对象,不支持随机访问(seek操作)。- torchaudio底层依赖的libsndfile库在读取WAV元数据时,需要通过
seek跳转文件指针来定位WAV文件的"data"块,流式对象无法满足这个需求,导致解析失败。
解决方法
方法1:先下载文件到本地再读取
适合处理大音频文件,避免占用过多内存:
import requests import torchaudio import os SAMPLE_WAV_URL = "https://pytorch-tutorial-assets.s3.amazonaws.com/steam-train-whistle-daniel_simon.wav" local_file = "steam_train.wav" # 下载文件到本地 with requests.get(SAMPLE_WAV_URL) as resp: with open(local_file, "wb") as f: f.write(resp.content) # 读取本地文件的元数据 metadata = torchaudio.info(local_file) print(metadata)
方法2:将响应内容转为支持seek的内存对象
适合小音频文件,直接在内存中处理:
import requests import torchaudio from io import BytesIO SAMPLE_WAV_URL = "https://pytorch-tutorial-assets.s3.amazonaws.com/steam-train-whistle-daniel_simon.wav" with requests.get(SAMPLE_WAV_URL) as resp: # 将响应内容转为BytesIO,支持seek操作 audio_buffer = BytesIO(resp.content) metadata = torchaudio.info(audio_buffer) print(metadata)
内容的提问来源于stack exchange,提问作者Imago
相关产品推荐
相关产品推荐

