带有管道和大文件的Python子进程

时间:2010-03-01 20:41:09

标签: python ffmpeg subprocess

我正在尝试使用python + ffmpeg + oggenc将任何音频文件转换为ogg。该计划几乎可以运作。但对于大文件(我认为> ~6mb),ffmpeg进程开始在pipe_wait上休眠。我不知道它等待哪条管道。

如果我杀了ffmpeg进程,oggenc进程会继续,我得到的结果ogg文件大约是所有声音的2:40。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from subprocess import Popen, PIPE
from sys import argv

ffmpeg = Popen([
    "ffmpeg",
    "-i", argv[1],
    "-vcodec", "null",
    "-acodec", "pcm_s16le",
    "-ac", "2",
    "-ab", "44100",
    "-f", "wav",
    "-"
],stdout = PIPE,stderr = PIPE)

oggenc = Popen([
    "oggenc",
    "-", "--raw",
    "-q", "4",
    "-o", argv[2]
],stdin = ffmpeg.stdout,stderr = PIPE)

oggenc.communicate()
ffmpeg.communicate()

编辑:

我想我可以补充说这很有效:

#!/bin/bash

ffmpeg -i "$1" -vcodec null -acodec pcm_s16le -ac 2 -ab 44100 -f wav - | oggenc - --raw -q 4 -o "$2"

2 个答案:

答案 0 :(得分:5)

您究竟对这两个管道的stderr渠道做了什么?

编码器/解码器通常会产生大量的stderr输出,作为状态更新;此输出通过管道输送到您的进程,缓冲区将变满。也许您应该在(无用的,我认为)ffmpeg.stderr.read()调用之前添加一些虚拟.communicate调用,或者甚至更好地完全删除stderr=PIPE个参数。

更新

对于等效的>/dev/null,请执行以下操作:

nulfp = open(os.devnull, "w")
…
… = subprocess.Popen(…, stderr=nulfp.fileno())

显然,您可以为要忽略的所有nulfp重复使用相同的stderr

答案 1 :(得分:0)

看看谁需要传递管道很棘手,我的意思是你应该使用像NetBeans这样的调试器来帮助收集更多线索。管道可能不是最好的方法,也许使用临时文件可以简化事情。