python執(zhí)行ffmpeg命令
- 能拿到ffmpeg正常輸出
- ffmpeg拋出異常時可以拿到異常信息
- 返回ffmpeg處理進(jìn)度
以下代碼依賴的pexpect,progressbar需要安裝下
import pexpect
import subprocess
import progressbar
import logging
def exec_progress(command, video_duration_seconds):
"""
執(zhí)行ffmpeg命令座享,并根據(jù)ffmpeg輸出中的"time=xxx"匹配進(jìn)度, ffmpeg執(zhí)行失敗時拋出FfmpegException
:param command: ffmpeg命令
:param video_duration_seconds: 視頻總時長
"""
thread = pexpect.spawn(command)
cpl = thread.compile_pattern_list([pexpect.EOF,
"frame=.*time=([\d:\.]*)(.*)",
'(.+)'])
progress = progressbar.ProgressBar(max_value=video_duration_seconds).start()
output_list = []
while True:
i = thread.expect_list(cpl, timeout=None)
if i == 0:
progress.finish()
break
elif i == 1:
seconds = duration_to_seconds(thread.match.group(1))
progress.update(seconds)
elif i == 2:
logging.debug(thread.match.group(0))
output_list.append(thread.match.group(0))
pass
thread.close()
if thread.exitstatus:
raise FfmpegException(thread.exitstatus, command, "\n".join(output_list))
def exec_output(command):
"""
執(zhí)行ffmpeg命令并返回所有輸出,如果執(zhí)行失敗翁涤,拋出FfmpegException
:param command: ffmpeg命令
:return: ffmpeg標(biāo)準(zhǔn)輸出
"""
try:
process = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
return process
except subprocess.CalledProcessError as err:
raise FfmpegException(err.returncode, err.cmd, err.output)
# 這個方法應(yīng)該單獨(dú)抽到別的模塊
def duration_to_seconds(duration):
time_arr = duration[0:duration.find(".")].split(":")
if len(time_arr) == 3:
return int(time_arr[0]) * 3600 + int(time_arr[1]) * 60 + int(time_arr[2])
logging.error("unrecognized duration %s", duration)
return 0
class FfmpegException(Exception):
"""
使用ffmpeg報(bào)錯時拋出
"""
def __init__(self, returncode, cmd, output=None):
self.returncode = returncode
self.cmd = cmd
self.output = output
def __str__(self):
return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
簡單說明下
- exec_progress執(zhí)行耗時較長需要實(shí)時拿到處理進(jìn)度的場景雪营,如壓縮仪召,裁剪等
- exec_output執(zhí)行耗時較短直接拿到輸出結(jié)果的場景肛度,如獲取視頻信息等