2015-09-22 87 views
0

我試圖讓熟悉Python子,這裏是我的小碼:ffmpeg的東西轉換到MP4

import subprocess 
import os 
import re 
import subprocess as sp 
import logging 

the_file = "/home/vagrant/test/out.pkg" 
out_file = "/home/vagrant/test/result.mp4" 

ffmpeg = sp.Popen(['/usr/bin/ffmpeg', '-i', the_file, out_file], stdout = sp.PIPE, stderr = sp.STDOUT) 
process_output = ffmpeg.communicate() 
print "communicate:", process_output 

結果:

communicate: ("ffmpeg version N-75410-g58fe57d Copyright (c) 2000-2015 the FFmpeg developers\n built with gcc 4.4.7 (GCC) 20120313 (Red Hat 4.4.7-16)\n configuration: --prefix=/home/vagrant/ffmpeg_build --extra-cflags=-I/home/vagrant/ffmpeg_build/include --extra-ldflags=-L/home/vagrant/ffmpeg_build/lib --bindir=/usr/local/bin --enable-gpl --enable-nonfree --enable-libfdk_aac --enable-libmp3lame --enable-libvorbis --enable-libopus --enable-libvpx --enable-libx264 --enable-libfreetype\n libavutil  55. 2.100/55. 2.100\n libavcodec  57. 3.100/57. 3.100\n libavformat 57. 2.100/57. 2.100\n libavdevice 57. 0.100/57. 0.100\n libavfilter  6. 5.100/6. 5.100\n libswscale  4. 0.100/4. 0.100\n libswresample 2. 0.100/2. 0.100\n libpostproc 54. 0.100/54. 0.100\nInput #0, tty, from '/home/vagrant/test/out.txt':\n Duration: 00:00:00.04, bitrate: 1 kb/s\n Stream #0:0: Video: ansi, pal8, 640x400, 25 fps, 25 tbr, 25 tbn, 25 tbc\nNo pixel format specified, yuv444p for H.264 encoding chosen.\nUse -pix_fmt yuv420p for compatibility with outdated media players.\n[libx264 @ 0x379f300] using cpu capabilities: MMX2 SSE2Fast SSSE3 Cache64\n[libx264 @ 0x379f300] profile High 4:4:4 Predictive, level 3.0, 4:4:4 8-bit\n[libx264 @ 0x379f300] 264 - core 148 r2597 e86f3a1 - H.264/MPEG-4 AVC codec - Copyleft 2003-2015 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=4 threads=1 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00\nOutput #0, mp4, to '/home/vagrant/test/result.mp4':\n Metadata:\n encoder   : Lavf57.2.100\n Stream #0:0: Video: h264 (libx264) ([33][0][0][0]/0x0021), yuv444p, 640x400, q=-1--1, 25 fps, 12800 tbn, 25 tbc\n Metadata:\n  encoder   : Lavc57.3.100 libx264\nStream mapping:\n Stream #0:0 -> #0:0 (ansi (native) -> h264 (libx264))\nPress [q] to stop, [?] for help\nframe= 1 fps=0.0 q=28.0 Lsize=  2kB time=00:00:00.04 bitrate= 362.4kbits/s \nvideo:1kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 78.698227%\n[libx264 @ 0x379f300] frame I:1  Avg QP:13.08 size: 326\n[libx264 @ 0x379f300] mb I I16..4: 0.4% 99.1% 0.5%\n[libx264 @ 0x379f300] 8x8 transform intra:99.1%\n[libx264 @ 0x379f300] coded y,u,v intra: 0.4% 0.0% 0.0%\n[libx264 @ 0x379f300] i16 v,h,dc,p: 0% 75% 25% 0%\n[libx264 @ 0x379f300] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 0% 92% 8% 0% 0% 0% 0% 0% 0%\n[libx264 @ 0x379f300] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 24% 35% 35% 2% 1% 0% 2% 0% 0%\n[libx264 @ 0x379f300] kb/s:65.20\n", None) 

正如所料,送我回元組(stdout,stderr)。但問題是,ffmpeg轉換任何文件(你可以看到上面,甚至pkg文件),沒有給我回錯誤或退出狀態1。stderr = None

任何人都可以解釋這是什麼錯?非常感謝。

+1

你試過在終端上運行ffmpeg嗎? – Andrew

+0

這不是ffmpeg,我認爲這是你的代碼似乎有錯誤,因爲你已經提到result.mpr作爲你的輸出文件,所以它轉換相同。閱讀更多關於ffmpeg的信息 – csharpcoder

回答

1

在這種情況下,您最好使用subprocess.check_output()

from subprocess import check_output, STDOUT, CalledProcessError 

args = ['/usr/bin/ffmpeg', '-i', the_file, out_file] 
try: 
    txt = check_output(args, stderr=STDOUT) 
except CalledProcessError as e: 
    print "conversion failed", e 
else: 
    print the_file, 'converted to', out_file 

上述代碼捕獲標準輸出和在txtffmpeg標準錯誤流。它通過捕獲異常來處理非零返回值。如果你想運行多個程序,使用Popen是不錯的。下面給出的程序並行運行ffmpeg的多個實例,以將大量視頻(例如,從相機或手機)轉換爲MP4格式。

#!/usr/bin/env python3 
# vim:fileencoding=utf-8:ft=python 
# 
# Author: R.F. Smith <[email protected]> 
# Last modified: 2015-09-22 21:41:17 +0200 
# 
# To the extent possible under law, Roland Smith has waived all copyright and 
# related or neighboring rights to vid2mp4.py. This work is published from the 
# Netherlands. See http://creativecommons.org/publicdomain/zero/1.0/ 

"""Convert all video files given on the command line to H.264/AAC streams in 
an MP4 container.""" 

__version__ = '1.1.1' 

from multiprocessing import cpu_count 
from time import sleep 
import logging 
import os 
import subprocess 
import sys 


def main(argv): 
    """ 
    Entry point for vid2mp4. 

    Arguments: 
     argv: All command line arguments. 
    """ 
    if len(argv) == 1: 
     binary = os.path.basename(argv[0]) 
     print("{} version {}".format(binary, __version__), file=sys.stderr) 
     print("Usage: {} [file ...]".format(binary), file=sys.stderr) 
     sys.exit(0) 
    logging.basicConfig(level="INFO", format='%(levelname)s: %(message)s') 
    checkfor(['ffmpeg', '-version']) 
    vids = argv[1:] 
    procs = [] 
    maxprocs = cpu_count() 
    for ifile in vids: 
     while len(procs) == maxprocs: 
      manageprocs(procs) 
     procs.append(startencoder(ifile)) 
    while len(procs) > 0: 
     manageprocs(procs) 


def checkfor(args, rv=0): 
    """ 
    Make sure that a program necessary for using this script is available. 

    Arguments: 
     args: String or list of strings of commands. A single string may 
      not contain spaces. 
     rv: Expected return value from evoking the command. 
    """ 
    if isinstance(args, str): 
     if ' ' in args: 
      raise ValueError('no spaces in single command allowed') 
     args = [args] 
    try: 
     rc = subprocess.call(args, stdout=subprocess.DEVNULL, 
          stderr=subprocess.DEVNULL) 
     if rc != rv: 
      raise OSError 
    except OSError as oops: 
     outs = "required program '{}' not found: {}." 
     logging.error(outs.format(args[0], oops.strerror)) 
     sys.exit(1) 


def startencoder(fname): 
    """ 
    Use ffmpeg to convert a video file to H.264/AAC streams in an MP4 
    container. 

    Arguments: 
     fname: Name of the file to convert. 

    Returns: 
     A 3-tuple of a Process, input path and output path. 
    """ 
    basename, ext = os.path.splitext(fname) 
    known = ['.mp4', '.avi', '.wmv', '.flv', '.mpg', '.mpeg', '.mov', '.ogv'] 
    if ext.lower() not in known: 
     ls = "File {} has unknown extension, ignoring it.".format(fname) 
     logging.warning(ls) 
     return (None, fname, None) 
    ofn = basename + '.mp4' 
    args = ['ffmpeg', '-i', fname, '-c:v', 'libx264', '-crf', '29', '-flags', 
      '+aic+mv4', '-c:a', 'libfaac', '-sn', ofn] 
    with open(os.devnull, 'w') as bitbucket: 
     try: 
      p = subprocess.Popen(args, stdout=bitbucket, stderr=bitbucket) 
      logging.info("Conversion of {} to {} started.".format(fname, ofn)) 
     except: 
      logging.error("Starting conversion of {} failed.".format(fname)) 
    return (p, fname, ofn) 


def manageprocs(proclist): 
    """ 
    Check a list of subprocesses tuples for processes that have ended and 
    remove them from the list. 

    Arguments: 
     proclist: a list of (process, input filename, output filename) 
    tuples. 
    """ 
    nr = '# of conversions running: {}\r'.format(len(proclist)) 
    logging.info(nr, end='') 
    sys.stdout.flush() 
    for p in proclist: 
     pr, ifn, ofn = p 
     if pr is None: 
      proclist.remove(p) 
     elif pr.poll() is not None: 
      logging.info('Conversion of {} to {} finished.'.format(ifn, ofn)) 
      proclist.remove(p) 
    sleep(0.5) 


if __name__ == '__main__': 
    main(sys.argv) 
+0

你可以使用'e.output'來獲取異常處理程序中的ffmpeg錯誤信息。並行任務處理看起來很複雜。你可以[使用線程池來簡化它:'for pool.imap_unordered(convert_video,vids):...'](http://stackoverflow.com/a/14533902/4279)。使用'subprocess.DEVNULL'而不是'bitbucket'。 – jfs

+0

使用'subprocess.DEVNULL'是我肯定會用到的一種改進!起初我使用(進程)'Pool'來啓動子進程,但這看起來很浪費。我會給線程池一個嘗試。 –

+0

你可能也想設置'stdin = DEVNULL'(它可以改變輸出格式(如果stdin不是tty))。 – jfs

1

檢查ffmpeg.returncode,查看退出狀態。

設置stderr=sp.PIPEcommunicate()中獲取相應的非無值。