2012-07-02 25 views
3

我有一個django FileField,我用它來在Amazon s3服務器上存儲wav文件。我已經設置了芹菜任務來讀取該文件並將其轉換爲mp3並將其存儲到另一個FileField。我面臨的問題是我無法將輸入文件傳遞給ffmpeg,因爲該文件不是硬盤驅動器上的物理文件。爲了避免這種情況,我使用stdin將文件的輸入流與django的文件字段一起提供。下面是例子:通過子進程傳遞Python對象到ffmpeg的文件

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

你能張貼整個回溯? –

+0

完整追溯:http://dpaste.org/I6V4c/ – tejinderss

回答

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) 
+0

感謝您的迴應,但django FileField只接受文件類型實例。我試圖直接存儲recording_mp3,但它不起作用。但Popen.communication完美無瑕。再次感謝 – tejinderss

1

你需要創建一個管道,通過管道向子進程的讀端,數據轉儲到寫結束。

+0

請給我一個例子嗎?我附上了回溯。 – tejinderss