我有一个django FileField,我用它来存储亚马逊s3服务器上的wav文件。我已经设置了芹菜任务来读取该文件并将其转换为mp3并将其存储到另一个FileField。我面临的问题是我无法将输入文件传递给ffmpeg,因为该文件不是硬盘驱动器上的物理文件。为了避免这种情况,我使用stdin用django的文件字段来提供文件的输入流。这是一个例子:
output_file = NamedTemporaryFile(suffix='.mp3')
subprocess.call(['ffmpeg', '-y', '-i', '-', output_file.name], stdin=recording_wav)
其中recording_wav文件是:,实际存储在amazon s3服务器上。 上述子进程调用的错误是:
AttributeError: 'cStringIO.StringO' object has no attribute 'fileno'
我该怎么做?在此先感谢您的帮助。
修改
完整追溯:
[2012-07-03 04:09:50,336: ERROR/MainProcess] Task api.tasks.convert_audio[b7ab4192-2bff-4ea4-9421-b664c8d6ae2e] raised exception: AttributeError("'cStringIO.StringO' object has no attribute 'fileno'",)
Traceback (most recent call last):
File "/home/tejinder/envs/tmai/local/lib/python2.7/site-packages/celery/execute/trace.py", line 181, in trace_task
R = retval = fun(*args, **kwargs)
File "/home/tejinder/projects/tmai/../tmai/apps/api/tasks.py", line 56, in convert_audio
subprocess.Popen(['ffmpeg', '-y', '-i', '-', output_file.name], stdin=recording_wav)
File "/usr/lib/python2.7/subprocess.py", line 672, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
File "/usr/lib/python2.7/subprocess.py", line 1043, in _get_handles
p2cread = stdin.fileno()
File "/home/tejinder/envs/tmai/local/lib/python2.7/site-packages/django/core/files/utils.py", line 12, in <lambda>
fileno = property(lambda self: self.file.fileno)
File "/home/tejinder/envs/tmai/local/lib/python2.7/site-packages/django/core/files/utils.py", line 12, in <lambda>
fileno = property(lambda self: self.file.fileno)
AttributeError: 'cStringIO.StringO' object has no attribute 'fileno'
答案 0 :(得分:2)
使用subprocess.Popen.communicate
将输入传递给子流程:
command = ['ffmpeg', '-y', '-i', '-', output_file.name]
process = subprocess.Popen(command, stdin=subprocess.PIPE)
process.communicate(recording_wav)
为了更有趣,您可以使用ffmpeg的输出来避免NamedTemporaryFile:
command = ['ffmpeg', '-y', '-i', '-', '-f', 'mp3', '-']
process = subprocess.Popen(command, stdin=subprocess.PIPE)
recording_mp3, errordata = process.communicate(recording_wav)
答案 1 :(得分:1)
您需要创建一个管道,将管道的读取端传递给子进程,并将数据转储到写入端。