我正在尝试使用subprocess.Popen
构建一个序列来获取视频文件的持续时间。我一直在搜索3天,在网上找不到任何理由,为什么这段代码不起作用,但它一直给我一个空白的结果:
import sys
import os
import subprocess
def main():
the_file = "/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file], stdout = subprocess.PIPE, )
grep = subprocess.Popen(['grep', 'Duration'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )
cut = subprocess.Popen(['cut', '-d', ' ', '-f', '4'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )
sed = subprocess.Popen(['sed', 's/,//'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )
duration = sed.communicate()
print duration
if __name__ == '__main__':
main()
答案 0 :(得分:24)
正如其他人所指出的,您需要将PIPE从一个进程传递到下一个进程。 来自一个进程的stdout(PIPE)成为后续任务的标准输入。
这样的事情(从你的例子开始):
import sys
import os
import subprocess
def main():
the_file = "/Volumes/Footage/Acura/MDX/
2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file],
stdout = subprocess.PIPE)
grep = subprocess.Popen(['grep', 'Duration'],
stdin = ffmpeg.stdout, stdout = subprocess.PIPE)
cut = subprocess.Popen(['cut', '-d', ' ', '-f', '4'],
stdin = grep.stdout, stdout = subprocess.PIPE)
sed = subprocess.Popen(['sed', 's/,//'],
stdin = cut.stdout, stdout = subprocess.PIPE)
duration = sed.communicate()[0]
print duration
if __name__ == '__main__':
main()
答案 1 :(得分:15)
stderr需要重定向到stdout。此外,没有必要调用其他工具,如cut/sed
等。在Python中进行字符串操作
import subprocess
....
the_file = "/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg = subprocess.Popen(['/usr/bin/ffmpeg', '-i', the_file], stderr=subprocess.STDOUT,stdout = subprocess.PIPE )
out, err = ffmpeg.communicate()
if "Duration" in out:
print out[out.index("Duration"):].split()[1]
如果Python不是必须的,你可以直接使用shell。
the_file="/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg -i "$file" 2>&1 | awk '/Duration/{print $2}'
答案 2 :(得分:13)
使用subprocess.PIPE
不会为您神奇地连接正确的管道。
您必须将第一个进程的输出管道作为第二个进程的参数stdin
的值传递。 See the docs for an example
答案 3 :(得分:4)
Python不能以这种方式“构建整个管道” - 它可以将任务委托给shell,或者使用行中先前子进程对象的stdout
属性直接粘贴它,但是在这种特定情况下,实际上没有理由这样做,因为你可以很容易地直接用Python编写代码。 E.g:
ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file],
stdout=subprocess.PIPE)
for line in ffmpeg.stdout:
if 'Duration' not in line: continue
fields = line.split()
duration = fields[4].replace(',', '')
break