搜索了很长时间后,我仍然找不到使用scipy.io.wavfile.read()
从FFmpeg 3.3.6的stdout
读取字节的解决方案。
这是完美的示例代码。但是,它需要将转换后的文件保存到磁盘。
import subprocess
import scipy.io.wavfile as wavfile
command = 'ffmpeg -i in.mp3 out.wav'
subprocess.run(command)
with open('out.wav', 'rb') as wf:
rate, signal = wavfile.read(wf)
print(rate, signal)
以下是我尝试从stdout获取FFmpeg输出并将其加载到scipy wavfile中的代码。
import io
import subprocess
import scipy.io.wavfile as wavfile
command = 'ffmpeg -i in.mp3 -f wav -'
proc = subprocess.run(command, stdout=subprocess.PIPE)
rate, signal = wavfile.read(io.BytesIO(proc.stdout))
print(rate, signal)
可悲的是,它引发了ValueError
。
Traceback (most recent call last):
File ".\err.py", line 8, in <module>
rate, signal = wavfile.read(io.BytesIO(proc.stdout))
File "C:\Users\Sean Wu\AppData\Local\Programs\Python\Python36\lib\site-
packages\scipy\io\wavfile.py", line 246, in read
raise ValueError("Unexpected end of file.")
ValueError: Unexpected end of file.
有没有办法解决这个问题?
答案 0 :(得分:0)
显然,当ffmpeg
的输出发送到stdout时,程序不会填写文件头的RIFF块大小。相反,块大小应该是的四个字节都是0xFF。 scipy.io.wavfile.read()
期望该值是正确的,因此它认为块的长度是0xFFFFFFFF字节。
当您给ffmpeg
输出文件写入时,它会正确填写RIFF块大小,因此wavfile.read()
能够在这种情况下读取文件。
代码的解决方法是在数据通过wavfile.read()
对象传递到io.BytesIO()
之前手动修补RIFF块大小。这是对您的脚本的修改。注意:我必须使用command.split()
作为subprocess.run()
的第一个参数。我在Mac OS X上使用Python 3.5.2。另外,我的测试文件名是“mpthreetest.mp3”。
import io
import subprocess
import scipy.io.wavfile as wavfile
command = 'ffmpeg -i mpthreetest.mp3 -f wav -'
proc = subprocess.run(command.split(), stdout=subprocess.PIPE)
riff_chunk_size = len(proc.stdout) - 8
# Break up the chunk size into four bytes, held in b.
q = riff_chunk_size
b = []
for i in range(4):
q, r = divmod(q, 256)
b.append(r)
# Replace bytes 4:8 in proc.stdout with the actual size of the RIFF chunk.
riff = proc.stdout[:4] + bytes(b) + proc.stdout[8:]
rate, signal = wavfile.read(io.BytesIO(riff))
print("rate:", rate)
print("len(signal):", len(signal))
print("signal min and max:", signal.min(), signal.max())