Python 如何在flask server中使用ffmpeg在音频格式之间转换,而不将文件写入磁盘?
我成功地在python中使用ffmpeg转换了一些音频文件的格式,如下所示:Python 如何在flask server中使用ffmpeg在音频格式之间转换,而不将文件写入磁盘?,python,flask,ffmpeg,Python,Flask,Ffmpeg,我成功地在python中使用ffmpeg转换了一些音频文件的格式,如下所示: command = "ffmpeg -i audio.wav -vn -acodec pcm_s16le output.wav" subprocess.call(command, shell=True) 但是,我希望在内存中执行此操作,并避免将输入和输出文件保存到磁盘 我找到了以下代码来执行此操作(): 但我很难在我的上下文中使用它 作为多部分/表单数据请求的一部分,我正在服务器上接收该文件 @server.rout
command = "ffmpeg -i audio.wav -vn -acodec pcm_s16le output.wav"
subprocess.call(command, shell=True)
但是,我希望在内存中执行此操作,并避免将输入和输出文件保存到磁盘
我找到了以下代码来执行此操作():
但我很难在我的上下文中使用它
作为多部分/表单数据请求的一部分,我正在服务器上接收该文件
@server.route("/api/getText", methods=["POST"])
def api():
if "multipart/form-data" not in request.content_type:
return Response("invalid content type: {}".format(request.content_type))
# check file format
file = request.files['file']
if file:
print('**found file', file.filename)
现在我将该文件作为FileStorage对象()。此对象有一个流,可以使用read方法访问该流。所以我想我可以用它作为ffmpeg的输入,比如:
f = file.read()
command = ['ffmpeg', '-y', '-i', '-', '-f', 'wav', '-']
process = subprocess.Popen(command, stdin=subprocess.PIPE)
wav, errordata = process.communicate(f)
但是,这会产生以下错误:
AssertionError: Given audio file must be a filename string or a file-like object
TypeError: a bytes-like object is required, not '_io.BytesIO'
我还尝试了另一种我在网上找到的方法,使用io.BytesIO,我再也找不到来源了:
memfile = io.BytesIO() # create file-object
memfile.write(file.read()) # write in file-object
memfile.seek(0) # move to beginning so it will read from beginning
然后再试一次:
command = ['ffmpeg', '-y', '-i', '-', '-f', 'wav', '-']
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
wav, errordata = process.communicate(memfile)
这会导致以下错误:
AssertionError: Given audio file must be a filename string or a file-like object
TypeError: a bytes-like object is required, not '_io.BytesIO'
有人知道怎么做吗
更新
第一条错误消息实际上不是ffmpeg抛出的错误消息。正如v25在他的回答中正确指出的那样,第一种方法还返回一个bytes对象,也是一种有效的解决方案
试图处理修改后的文件时,库(语音识别)抛出错误消息。在不太可能的情况下,如果有人遇到相同的问题,请在此提供解决方案:
如错误消息所示,ffmpeg(变量wav)返回的反对字节必须转换为类似文件的对象。这样做很容易:
command = "ffmpeg -i audio.wav -vn -acodec pcm_s16le output.wav"
subprocess.call(command, shell=True)
memfileOutput=io.BytesIO(wav)根据您的评论,这似乎已由以下人员修复:
wav, errordata = process.communicate(memfile.read())
我不能100%确定为什么在这里传递f
不起作用,因为:
import io
print ('file.read()', type(file.read()))
memfile = io.BytesIO()
memfile.write(file.read())
memfile.seek(0)
print ('memfile', type(memfile))
print ('memfile.read()', type(memfile.read()))
给
file.read() <class 'bytes'> # (f)
memfile <class '_io.BytesIO'>
memfile.read() <class 'bytes'>
file.read()#(f)
内存文件
memfile.read()
因此,在您的案例中,f
和memfile.read()
属于同一类型
我不确定为什么前者会产生,
AssertionError:给定的音频文件必须是文件名字符串或类似对象的文件
如何wav,errordata=process.communicate(memfile.read())
我自己也不清楚。等我有机会再看一次。能否将此添加到答案中:process=subprocess.Popen(command,stdin=subprocess.PIPE,stdout=subprocess.PIPE)?没有它,wav将一无是处。没有问题!我认为这可能不应该添加,因为该部分包含在问题中,并且答案包括相关的问题行。我之所以提到它,是因为我没有将其包含在问题(标准部分)中。但无论如何,我可以编辑这个问题,以防将来有人遇到它。我还弄明白了为什么我在第一种方法中会收到错误消息。这是我的错,实际上不是ffmpeg抛出的错误消息。我已经在这个问题上写了一些更新,以防有人怀疑。