Python的子进程与管道及大文件
我正在尝试使用 Python、ffmpeg 和 oggenc 将任何音频文件转换为 ogg 格式。这个程序几乎可以正常工作。但是对于大文件(我觉得大于大约 6MB),ffmpeg 进程在 pipe_wait 时开始挂起。我不知道它在等待哪个管道。
如果我结束 ffmpeg 进程,oggenc 进程会继续运行,我会得到一个大约 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
要搞清楚谁需要传递数据有点棘手,呃,我是说你应该使用像NetBeans这样的调试工具来帮助你收集更多线索。使用管道可能不是最好的方法,也许用一个临时文件会让事情变得简单一些。
5
你到底是怎么处理这两个管道的 stderr
通道的呢?
编码器和解码器通常会产生很多 stderr
输出,作为状态更新;这些输出会被传送到你的程序中,导致缓冲区变满。也许你应该在 (我觉得没什么用的) .communicate
调用之前,添加一些无用的 ffmpeg.stderr.read()
调用,或者更好的是,完全去掉 stderr=PIPE
的参数。
更新
如果你想要和 >/dev/null
一样的效果,可以这样做:
nulfp = open(os.devnull, "w")
…
… = subprocess.Popen(…, stderr=nulfp.fileno())
显然,你可以重复使用同一个 nulfp
来处理所有你想忽略的 stderr
。