2011-09-09 44 views
7

Làm cách nào để nhận được chiều cao và chiều rộng của video từ đầu ra thông tin của ffmpeg. Ví dụ: với đầu ra sau -Lấy kích thước video từ 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 

Làm cách nào để nhận được height = 640, width= 360? Cảm ơn bạn.

Trả lời

7

Hãy xem mediainfo Xử lý hầu hết các định dạng trên mạng.

Nếu bạn tìm kiếm một cách để phân tích đầu ra từ ffmpeg, sử dụng regexp \d+x\d+

Ví dụ sử dụng perl:

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

Ví dụ sử dụng python (không hoàn hảo):

$ ./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 một lớp lót không phải là hấp dẫn như những perl :-)

+0

Perfect, cảm ơn bạn rất nhiều. – David542

+1

Điều này không thành công khi tôi kiểm tra, vì thông tin luồng là 'Luồng # 0: 0: Video: mjpeg (MJPG/0x47504A4D), yuvj420p (pc, bt470bg/không xác định/không xác định), 733x446 [SAR 1: 1 DAR 733: 446], 7516 kb/s, 60 fps, 60 tbr, 60 tbn, 60 tbc', do đó kết quả là '[] [] [] [] [] [] [] [] [] [] [] [] [] ['0x47504', '733x446'] [] ' –

3

Từ đầu Fredrik của trên, đây là cách tôi đã làm nó bằng 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

Trong this blog post theres một giải pháp thô trong 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 

Tuy nhiên điều này giả định là 3 chữ số x 3 chữ số (ví dụ: 854x480), bạn sẽ cần phải lặp qua các độ dài có thể kích thước, như (1280x720):

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,})')] 

và kiểm tra xem trận đấu trở về None trên mỗi bước:

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) 

Có thể đẹp hơn, nhưng công trinh.

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 

TỐT ([0-9] {2,} x [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

hoặc (\ d {2,} x \ d +) –

0

mà không cần mô-đun

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") 

Edit: không phải là một câu trả lời tốt bởi vì không phải tất cả video có mà "cải cách hành chính" thông tin :(

1

Cách tốt nhất để trả lời câu hỏi này là dành cho nhà phát triển ffmpeg để giải thích chính xác định dạng của đầu ra ffmpeg được mong đợi là gì và liệu chúng ta có thể giả định kích thước được đặt trong một ngữ cảnh cụ thể bên trong nó hay không. Cho đến lúc đó, chúng tôi chỉ có thể đoán từ ví dụ về định dạng thường là gì.

Đây là nỗ lực của tôi. It's verbose so với những "one-liners", nhưng đó là bởi vì tôi muốn biết tại sao nó không thành công khi nó cuối cùng.

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

Sử dụng ffprobe:

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

gì các tùy chọn làm:

  • -v error Thực hiện một đầu ra yên tĩnh, nhưng cho phép các lỗi sẽ được hiển thị. Không bao gồm thông tin đầu ra FFmpeg chung thông thường bao gồm các chi tiết phiên bản, cấu hình và đầu vào.

  • -show_entries stream=width,height Chỉ hiển thị thông tin widthheight luồng.

  • -of default=noprint_wrappers=1 Điều này sẽ bỏ qua trình bao bọc [STREAM]...[/STREAM] thường được hiển thị ở đầu ra. Nếu bạn cũng muốn bỏ qua các phím width=height=, thì hãy sử dụng -of default=noprint_wrappers=1:nokey=1.

  • Các tùy chọn định dạng đầu ra khác có sẵn để phù hợp với nhu cầu của bạn. Chúng có thể được đặt thông qua tùy chọn -of (aka -print_format) và các định dạng là: mặc định, nhỏ gọn, csv, phẳng, ini, json, xml. Xem FFprobe Documentation: Writers để biết mô tả về từng định dạng và để xem các tùy chọn bổ sung.

  • -select_streams v:0 Điều này có thể được thêm vào trong trường hợp dữ liệu nhập của bạn chứa nhiều luồng video. v:0 sẽ chỉ chọn luồng video đầu tiên. Nếu không, bạn sẽ nhận được nhiều kết quả đầu ra là widthheight khi có luồng video.

  • Xem FFprobe DocumentationFFmpeg Wiki: FFprobe Tips để biết thêm thông tin.

+0

Điều này là hữu ích, nhưng tôi nghĩ OP muốn nắm bắt các giá trị trong python. – Geoff

+0

@Geoff Điều này sẽ cung cấp các giá trị cần thiết và sẽ đáng tin cậy hơn so với phương pháp khác được hiển thị ở đây. Làm thế nào nó được sử dụng với Python là tùy thuộc vào người dùng. – LordNeckbeard

+0

Thật vậy. Nó đã giúp tôi rất nhiều. Cảm ơn. Rất dễ dàng để phân tích cú pháp với 're.search' bằng cách sử dụng gói' subprocess' để nắm bắt đầu ra. Xin lỗi vì có âm. – Geoff

2

Như đã đề cập ở đây, ffprobe cung cấp cách lấy dữ liệu về tệp video. Tôi tìm thấy lệnh sau hữu ích ffprobe -v quiet -print_format json -show_streams input-video.xxx để xem loại dữ liệu nào bạn có thể kiểm tra.

sau đó tôi đã viết một chức năng chạy lệnh trên và trả về chiều cao và chiều rộng của các tập tin video:

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 
Các vấn đề liên quan