带有管道和大文件的 Python 子进程
Posted
技术标签:
【中文标题】带有管道和大文件的 Python 子进程【英文标题】:Python's subprocessing with pipes and large files 【发布时间】:2011-01-22 11:16:21 【问题描述】:我正在尝试使用 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"
【问题讨论】:
检查我的答案更新以获取您的“>/dev/null”等效项。 【参考方案1】:你对两个管道的stderr
通道究竟做了什么?
编码器/解码器通常会产生大量标准错误输出,作为状态更新;此输出通过管道传输到您的进程,并且缓冲区将变满。也许您应该在(我认为没用的).communicate
调用之前添加一些虚拟的ffmpeg.stderr.read()
调用,或者更好的是,完全删除stderr=PIPE
参数。
更新
对于 >/dev/null
等效项,请执行以下操作:
nulfp = open(os.devnull, "w")
…
… = subprocess.Popen(…, stderr=nulfp.fileno())
显然,您可以对所有要忽略的stderr
s 重复使用相同的nulfp
。
【讨论】:
我使用 stderr 管道的原因是因为我不希望它向终端写入任何内容。我尝试在 ffmpeg 上使用“-loglevel quiet”来查看它是否有效,但所有内容都直接停止了。首先,我认为是 .communicate 终止了程序,但事实证明:ffmpeg 不喜欢“-loglevel quiet”,所以它自行终止了。当我删除 stderr=PIPE 参数时一切正常,感谢您的帮助!现在我只需要弄清楚如何不显示 sdterr 数据... 只是做了同样的事情,但没有 .fileno(),使用它有什么优点/缺点吗? 都是一样的,没有优缺点。当你给它一个文件对象时,子进程模块将在内部获取.fileno()
。
感谢您的提示!供将来参考:仍然需要做null = open(os.devnull,'w')
。【参考方案2】:
很难看出谁需要通过管道,呃我的意思是你应该使用像 NetBeans 中的调试器来帮助收集更多线索。管道可能不是最好的方法,也许使用临时文件会简化事情。
【讨论】:
嗯,临时文件是我的第一个想法,但它会花费几乎两倍的时间,首先 ffmpeg 将文件转换为原始音频,然后 oggenc 将其转换为 ogg/vorbis。使用管道,他们可以同时进行,从而节省时间。 ……管道将更好地利用多核(如果可用)。以上是关于带有管道和大文件的 Python 子进程的主要内容,如果未能解决你的问题,请参考以下文章