【问题标题】:Passing python's file like object to ffmpeg via subprocess通过子进程将python的类似对象的文件传递给ffmpeg
【发布时间】:2012-07-03 08:25:09
【问题描述】:

我有一个 django FileField,用于在 Amazon s3 服务器上存储 wav 文件。我已经设置了 celery 任务来读取该文件并将其转换为 mp3 并将其存储到另一个 FileField。我面临的问题是我无法将输入文件传递给 ffmpeg,因为该文件不是硬盘驱动器上的物理文件。为了规避这种情况,我使用标准输入将文件的输入流与 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'

【问题讨论】:

标签: python django ffmpeg celery


【解决方案1】:

你需要创建一个管道,把管道的读端传给子进程,把数据转储到写端。

【讨论】:

  • 你能给我举个例子吗?我已附上回溯。
【解决方案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)

【讨论】:

  • 感谢您的回复,但 django FileField 仅接受文件类型实例。我尝试直接存储recording_mp3,但它不起作用。但 Popen.communication 完美无缺。再次感谢
猜你喜欢
  • 2021-05-23
  • 2012-10-31
  • 2017-07-04
  • 1970-01-01
  • 2021-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-07
相关资源
最近更新 更多