2011-09-09 116 views
7

如何從ffmpeg的信息輸出中獲取視頻的高度和寬度。例如,下面的輸出 -從ffmpeg獲取視頻尺寸-i

$ ffmpeg -i 1video.mp4 
... 

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/david/Desktop/1video.mp4': 
    Metadata: 
    major_brand  : isom 
    minor_version : 1 
    compatible_brands: isomavc1 
    creation_time : 2010-01-24 00:55:16 
    Duration: 00:00:35.08, start: 0.000000, bitrate: 354 kb/s 
    Stream #0.0(und): Video: h264 (High), yuv420p, 640x360 [PAR 1:1 DAR 16:9], 597 kb/s, 25 fps, 25 tbr, 25k tbn, 50 tbc 
    Metadata: 
     creation_time : 2010-01-24 00:55:16 
    Stream #0.1(und): Audio: aac, 44100 Hz, stereo, s16, 109 kb/s 
    Metadata: 
     creation_time : 2010-01-24 00:55:17 
At least one output file must be specified 

如何,我會得到height = 640, width= 360?謝謝。

回答

7

看看mediainfo處理大部分格式。

如果你正在尋找一種方式來解析從ffmpeg的輸出,使用正則表達式\d+x\d+

例用perl:

$ ./ffmpeg -i test020.3gp 2>&1 | perl -lane 'print $1 if /(\d+x\d+)/' 
176x120 

示例使用python(不完美):

$ ./ffmpeg -i /nfshome/enilfre/pub/test020.3gp 2>&1 | python -c "import sys,re;[sys.stdout.write(str(re.findall(r'(\d+x\d+)', line))) for line in sys.stdin]" 

[] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] ['176x120'] [] [] []]

的Python單行不如perl的那些:-)

+0

完美,非常感謝你。 – David542

+1

這個測試失敗,因爲流信息是流#0:0:視頻:mjpeg(MJPG/0x47504A4D),yuvj420p(pc,bt470bg /未知/未知),733x446 [SAR 1:1 DAR 733: 446],7516 kb/s,60 fps,60 tbr,60 tbn,60 tbc',所以結果是[] [] [] [] [] [] [] [] [] [] [] [] [] ['0x47504','733x446'] []' –

3

從上面弗雷德裏克的舌尖上口,這裏是我做到了使用的MediaInfo(http://mediainfo.sourceforge.net/en):

>>> p1 = subprocess.Popen(['mediainfo', '--Inform=Video;%Width%x%Height%',   
    '/Users/david/Desktop/10stest720p.mov'],stdout=PIPE) 
>>> dimensions=p1.communicate()[0].strip('\n') 
>>> dimensions 
'1280x688' 
3

this blog post那裏有一個粗略的解決方案在python:

import subprocess, re 
pattern = re.compile(r'Stream.*Video.*([0-9]{3,})x([0-9]{3,})') 

def get_size(pathtovideo): 
    p = subprocess.Popen(['ffmpeg', '-i', pathtovideo], 
         stdout=subprocess.PIPE, 
         stderr=subprocess.PIPE) 
    stdout, stderr = p.communicate() 
    match = pattern.search(stderr) 
    if match: 
     x, y = map(int, match.groups()[0:2]) 
    else: 
     x = y = 0 
    return x, y 

然而,這假定它是3個位數×3個位數(即854×480),你會通過可能的尺寸長度,如(1280×720),需要循環:

possible_patterns = [re.compile(r'Stream.*Video.*([0-9]{4,})x([0-9]{4,})'), \ 
      re.compile(r'Stream.*Video.*([0-9]{4,})x([0-9]{3,})'), \ 
re.compile(r'Stream.*Video.*([0-9]{3,})x([0-9]{3,})')] 

,並檢查是否匹配返回None每一步:

for pattern in possible_patterns: 
    match = pattern.search(stderr) 
    if match!=None: 
     x, y = map(int, match.groups()[0:2]) 
     break 

if match == None: 
    print "COULD NOT GET VIDEO DIMENSIONS" 
    x = y = 0 

return '%sx%s' % (x, y) 

可能是更漂亮,但作品。

1

BAD(\ d + X \ d +)

$ echo 'Stream #0:0(eng): Video: mjpeg (jpeg/0x6765706A), yuvj420p, 1280x720, 19939 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc' | perl -lane 'print $1 if /(\d+x\d+)/' 
> 0x6765706 

GOOD([0-9] {2,}×[0-9] +)

$ echo 'Stream #0:0(eng): Video: mjpeg (jpeg/0x6765706A), yuvj420p, 1280x720, 19939 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc' | perl -lane 'print $1 if /([0-9]{2,}x[0-9]+)/' 
> 1280x720 
+0

或(\ d {2,} x \ d +) –

0

無需重新模塊

out = error_message.split()    # make a list from resulting error string 
out.reverse() 
for index, item in enumerate(out):  # extract the item before item= "[PAR" 
    if item == "[PAR":      # 
     dimension_string = out[i+1]   # 
     video_width, video_height = dimension_string.split("x") 

編輯:不太好回答,因爲不是所有的影片有 「PAR」 信息:(

1

要回答這個問題,最好的方法是讓ffmpeg開發人員準確解釋ffmpeg輸出的格式應該是什麼,以及我們是否可以始終假定大小位於其中的指定上下文中。在此之前,我們只能從例子中猜出通常的格式。

這是我的嘗試。與這些「單線」相比,這是一個冗長的問題,但那是因爲我想知道爲什麼它最終會失敗。

import subprocess 

def get_video_size(video_filename): 
    """Returns width, height of video using ffprobe""" 
    # Video duration and hence start time 
    proc = subprocess.Popen(['ffprobe', video_filename], 
     stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
    res = proc.communicate()[0] 

    # Check if ffprobe failed, probably on a bad file 
    if 'Invalid data found when processing input' in res: 
     raise ValueError("Invalid data found by ffprobe in %s" % video_filename) 

    # Find the video stream 
    width_height_l = [] 
    for line in res.split("\n"): 
     # Skip lines that aren't stream info 
     if not line.strip().startswith("Stream #"): 
      continue 

     # Check that this is a video stream 
     comma_split = line.split(',') 
     if " Video: " not in comma_split[0]: 
      continue 

     # The third group should contain the size and aspect ratio 
     if len(comma_split) < 3: 
      raise ValueError("malform video stream string:", line) 

     # The third group should contain the size and aspect, separated 
     # by spaces 
     size_and_aspect = comma_split[2].split()   
     if len(size_and_aspect) == 0: 
      raise ValueError("malformed size/aspect:", comma_split[2]) 
     size_string = size_and_aspect[0] 

     # The size should be two numbers separated by x 
     width_height = size_string.split('x') 
     if len(width_height) != 2: 
      raise ValueError("malformed size string:", size_string) 

     # Cast to int 
     width_height_l.append(map(int, width_height)) 

    if len(width_height_l) > 1: 
     print "warning: multiple video streams found, returning first" 
    return width_height_l[0] 
29

使用ffprobe

$ ffprobe -v error -show_entries stream=width,height \ 
    -of default=noprint_wrappers=1 input.mp4 
width=1280 
height=720 

什麼選擇呢:

  • -v error安靜地輸出,但允許顯示錯誤。排除通常的FFmpeg輸出信息,包括版本,配置和輸入詳細信息。

  • -show_entries stream=width,height只顯示widthheight流信息。

  • -of default=noprint_wrappers=1這將省略通常在輸出中顯示的[STREAM]...[/STREAM]包裝。如果您還想要省略width=height=鍵,請使用-of default=noprint_wrappers=1:nokey=1

  • 其他輸出格式選項可滿足您的需求。這些可以通過-of(又名-print_format)選項進行設置,格式爲:default,compact,csv,flat,ini,json,xml。請參閱FFprobe Documentation: Writers瞭解每種格式的說明並查看其他選項。

  • -select_streams v:0如果您的輸入包含多個視頻流,則可以添加此選項。 v:0將只選擇第一個視頻流。否則,您將獲得儘可能多的widthheight輸出,因爲有視頻流。

  • 查看FFprobe DocumentationFFmpeg Wiki: FFprobe Tips瞭解更多信息。

+0

這很有幫助,但我認爲OP希望捕獲python中的值。 – Geoff

+0

@Geoff這將提供所需的值,並且比此處顯示的其他方法更可靠。它如何與Python一起使用取決於用戶。 – LordNeckbeard

+0

確實。這對我幫助很大。謝謝。使用'subprocess'軟件包''re.search'很容易解析並捕獲輸出。抱歉,聽起來不利。 – Geoff

2

如上所述,ffprobe提供了一種檢索關於視頻文件的數據的方法。我發現以下命令有用ffprobe -v quiet -print_format json -show_streams input-video.xxx來查看可以結帳的數據類型。

我然後寫運行上面的命令,並返回視頻文件的高度和寬度的函數:

import subprocess 
import shlex 
import json 

# function to find the resolution of the input video file 
def findVideoResolution(pathToInputVideo): 
    cmd = "ffprobe -v quiet -print_format json -show_streams" 
    args = shlex.split(cmd) 
    args.append(pathToInputVideo) 
    # run the ffprobe process, decode stdout into utf-8 & convert to JSON 
    ffprobeOutput = subprocess.check_output(args).decode('utf-8') 
    ffprobeOutput = json.loads(ffprobeOutput) 

    # find height and width 
    height = ffprobeOutput['streams'][0]['height'] 
    width = ffprobeOutput['streams'][0]['width'] 

    return height, width