Получение размера видео из ffmpeg -i - PullRequest
10 голосов
/ 09 сентября 2011

Как бы получить высоту и ширину видео из вывода информации ffmpeg. Например, со следующим выводом -

$ 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? Спасибо.

Ответы [ 8 ]

36 голосов
/ 12 апреля 2015

Использование ffprobe

Пример 1: с ключами / именами переменных

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

Пример 2. Просто ширина х высота

ffprobe -v error -show_entries stream=width,height -of csv=p=0:s=x input.m4v
1280x720

Пример 3: JSON

ffprobe -v error -show_entries stream=width,height -of json input.mkv 
{
    "programs": [

    ],
    "streams": [
        {
            "width": 1280,
            "height": 720
        },
        {

        }
    ]
}

Что делают опции:

  • -v error Сделайте тихий вывод, но позвольте отображать ошибки. Исключает обычную общую информацию вывода FFmpeg, включая версию, конфигурацию и данные ввода.

  • -show_entries stream=width,height Просто покажите информацию о потоке width и height.

  • -of опция выбирает формат вывода (по умолчанию, компактный, CSV, плоский, INI, JSON, XML). См. Документация FFprobe: Writers для описания каждого формата и просмотра дополнительных параметров форматирования.

  • -select_streams v:0 Это можно добавить, если ваш вход содержит несколько видеопотоков. v:0 выберет только первый видеопоток. В противном случае вы получите столько же выходов width и height, сколько имеется видеопотоков.

  • См. документацию FFprobe и FFmpeg Wiki: Советы FFprobe для получения дополнительной информации.

10 голосов
/ 09 сентября 2011

Посмотрите на 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: -)

3 голосов
/ 17 октября 2012

В этом сообщении в блоге есть грубое решение в 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 цифры (то есть 854x480), вам нужно будет пройти черезвозможные длины измерения, такие как (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,})')]

и проверьте, возвращает ли совпадение 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)

Может быть красивее, но работает.

3 голосов
/ 10 сентября 2011

Из приведенного выше совета Фредрика, вот как я это сделал, используя 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'
2 голосов
/ 18 декабря 2015

Как уже упоминалось, 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
1 голос
/ 12 апреля 2015

Лучший способ ответить на этот вопрос - это для разработчика 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]
1 голос
/ 12 июля 2013

ПЛОХО (\ 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

ХОРОШО ([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 голосов
/ 15 апреля 2014

без повторного модуля

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" :(

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...