实时获取 subprocess 管道输出在 ffmpeg 上的封装

2017-10-19 10:23:26来源:oschina作者:caucy人点击

分享

目前对视频的编码,转码,支持最好的就是 ffmpeg 。因为视频的封装,编码,都是重 cpu 操作,而且目前 python,golang 并没有能替代ffmpeg 的库,所以,如果这里不处理图片,使用 python 做 agent 开发效率还是很高的。目前的做法就是使用 subprocess 调用 ffmpeg ,主要做的是实时解析标准输出,反馈任务的进度。


下面是自己的封装:


def test_ffmpeg(input_file, output_file, param_list=[]):
cmd_list = ["ffmpeg", "-i", input_file] + param_list + [output_file]
print "cmd list ", cmd_list
p = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=False)
fl = fcntl.fcntl(p.stdout.fileno(), fcntl.F_GETFL)
fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, fl | os.O_NONBLOCK)
last_out = ""
all_time = ""
while True:
if p.poll() is not None:
if p.returncode:
data = {
"code": 200,
"msg": {
"error": last_out
}
}
break
try:
time.sleep(30)
out = os.read(p.stderr.fileno(), 1024)
if out:
last_out = out
dura_time = re.findall("Duration:/s/d/d:/d/d:/d/d/./d/d", out)
if dura_time:
all_time = dura_time
current_time = re.findall("time=/d/d:/d/d:/d/d/./d/d", out)
if len(current_time):
data = {
"code": 100,
"msg": {
"all_time": all_time,
"current_time": current_time[-1]
}
}
except Exception, e:
continue

比较核心的就是实用fcntl, 将管道读取设置成非阻塞,然后有个坑,就是 ffmpeg 的 所有输出都是标准都输出在标准错误输出上。


另外,这里使用的是忙轮训的方式去获取标准错误输出。其实,还可以使用 select 去监听 fd,这样会比较省资源。


一个subprocess 的标准输出的循环解析封装参考:


https://github.com/rfyiamcool/func_instance


微信扫一扫

第七城市微信公众平台