scipy.io.wavfile.read() 来自 FFmpeg 的标准输出
scipy.io.wavfile.read() the stdout from FFmpeg
找了半天,还是没找到用scipy.io.wavfile.read()
读取FFmpeg3.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.
有什么方法可以解决这个问题吗?
显然当ffmpeg
的输出发送到stdout时,程序没有填写文件头的RIFF块大小。相反,块大小应该在的四个字节都是 0xFF。 scipy.io.wavfile.read()
期望该值是正确的,因此它认为块的长度是 0xFFFFFFFF 字节。
当您给 ffmpeg
一个要写入的输出文件时,它会正确填充 RIFF 块大小,因此 wavfile.read()
能够在这种情况下读取文件。
您的代码的 work-around 是在数据通过 io.BytesIO()
对象传递到 wavfile.read()
之前手动修补 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())
找了半天,还是没找到用scipy.io.wavfile.read()
读取FFmpeg3.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.
有什么方法可以解决这个问题吗?
显然当ffmpeg
的输出发送到stdout时,程序没有填写文件头的RIFF块大小。相反,块大小应该在的四个字节都是 0xFF。 scipy.io.wavfile.read()
期望该值是正确的,因此它认为块的长度是 0xFFFFFFFF 字节。
当您给 ffmpeg
一个要写入的输出文件时,它会正确填充 RIFF 块大小,因此 wavfile.read()
能够在这种情况下读取文件。
您的代码的 work-around 是在数据通过 io.BytesIO()
对象传递到 wavfile.read()
之前手动修补 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())