實時獲取 subprocess 管道輸出在 ffmpeg 上的封裝

    目前對視頻的編碼,轉碼,支持最好的就是 ffmpeg 。由於視頻的封裝,編碼,都是重 cpu 操做,並且目前 python,golang 並無能替代ffmpeg 的庫,因此,若是這裏不處理圖片,使用 python 作 agent 開發效率仍是很高的。目前的作法就是使用 subprocess 調用 ffmpeg ,主要作的是實時解析標準輸出,反饋任務的進度。python

該文章後續仍在不斷的更新修改中, 請移步到原文地址http://dmwan.ccgit

    下面是本身的封裝:github

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 的 全部輸出都是標準都輸出在標準錯誤輸出上。golang

    另外,這裏使用的是忙輪訓的方式去獲取標準錯誤輸出。其實,還能夠使用 select 去監聽 fd,這樣會比較省資源。shell

    一個subprocess 的標準輸出的循環解析封裝參考:編碼

https://github.com/rfyiamcool/func_instancecode

相關文章
相關標籤/搜索