目前对视频的编码,转码,支持最好的就是 ffmpeg 。因为视频的封装,编码,都是重 cpu 操作,而且目前 python,golang 并没有能替代ffmpeg 的库,所以,如果这里不处理图片,使用 python 做 agent 开发效率还是很高的。目前的做法就是使用 subprocess 调用 ffmpeg ,主要做的是实时解析标准输出,反馈任务的进度。
该文章后续仍在不断的更新修改中, 请移步到原文地址http://dmwan.cc
下面是自己的封装:
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