Программно определить формат видео файла? - PullRequest
6 голосов
/ 21 сентября 2008

Хорошо, я понимаю основы видео формата - есть несколько форматов контейнеров, а затем у вас есть основные видео / аудио форматы. Я хотел бы написать веб-приложение, которое определяет, какой видео / аудио кодек использует файл.

Как лучше всего программно определить видеокодек? Будет ли лучше использовать стандартную библиотеку через системные вызовы и анализировать ее вывод? (например, ffmpeg, транскод и т. д.?)

Ответы [ 6 ]

7 голосов
/ 21 сентября 2008

mplayer -identify сделает свое дело. Простой вызов ffmpeg для файла также сработает - он автоматически напечатает в начале набор информации о входном файле независимо от того, что вы говорите ffmpeg на самом деле.

Конечно, если вы хотите сделать это из своей программы без вызова exec внешней программы, вы можете просто включить библиотеки avcodec и напрямую запустить собственную процедуру идентификации.

Хотя вы можете реализовать собственное обнаружение, оно, безусловно, будет уступать существующим процедурам, учитывая огромное количество форматов, которые поддерживает libav *. И это был бы довольно глупый случай изобретать колесо.

Команда Linux "file" также может помочь, но объем выводимых данных зависит от формата видео. Например, в AVI он предоставляет все виды данных о разрешении, FOURCC, fps и т. Д., В то время как для файла MKV он просто говорит «данные Matroska», ничего не сообщая о внутренних компонентах или даже используемых видео и аудио форматах. 1009 *

4 голосов
/ 23 сентября 2008

Я использовал FFMPEG в сценарии perl для достижения этой цели.

$info = `ffmpeg -i $path$file 2>&1 /dev/null`;
@fields = split(/\n/, $info);

И просто выясните, какие элементы в @fields вам нужно извлечь.

1 голос
/ 21 сентября 2008

Вы действительно хотите, чтобы большая база двоичных идентификационных маркеров искала в начале файла. К счастью, ваш вопрос помечен как «Linux», и такая база данных уже существует; Файл (1) сделает всю работу за вас.

1 голос
/ 21 сентября 2008

Вы должны начать дальше вниз по линии. Вам нужно знать формат контейнера и как он определяет кодек.

Итак, я бы начал с программы, которая идентифицирует формат контейнера (а не только из расширения, зайдите в заголовок и определите настоящий контейнер).

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

-Adam

0 голосов
/ 14 мая 2014

Вы можете использовать mediainfo:

sudo apt-get install mediainfo

Если вы просто хотите получить видео / аудио кодек, вы можете сделать следующее:

$videoCodec = `mediainfo --Inform="Video;%Format%" $filename`;
$audioCodec = `mediainfo --Inform="Audio;%Format%" $filename`;

Если вы хотите получить больше информации, вы можете проанализировать вывод XML, возвращенный mediainfo. Вот пример функции:

function getCodecInfo($inputFile)
{
    $cmdLine = 'mediainfo --Output=XML ' . escapeshellarg($inputFile);

    exec($cmdLine, $output, $retcode);
    if($retcode != 0)
        return null;

    try
    {
        $xml = new SimpleXMLElement(join("\n",$output));
        $videoCodec = $xml->xpath('//track[@type="Video"]/Format');
        $audioCodec = $xml->xpath('//track[@type="Audio"]/Format');
    }
    catch(Exception $e)
    {
        return null;
    }

    if(empty($videoCodec[0]) || empty($audioCodec[0]))
        return null;

    return array(
        'videoCodec' => (string)$videoCodec[0],
        'audioCodec' => (string)$audioCodec[0],
    );
}
0 голосов
/ 01 октября 2013

Я бы порекомендовал использовать ffprobe и форсировать формат вывода в json. Было бы намного проще разобрать. Простейший пример:

$meta = json_decode(join(' ', `ffprobe -v quiet -print_format json -show_format -show_streams /path/to/file 2>&1`));

Имейте в виду, что в случае поврежденного файла вы получите null как результат и предупреждение в зависимости от ваших настроек отчетов об ошибках. Полный пример с правильной обработкой ошибок:

$file = '/path/to/file';
$cmd = 'ffprobe -v quiet -print_format json -show_format -show_streams ' . escapeshellarg($file).' 2>&1';

exec($cmd, $output, $code);
if ($code != 0) {
    throw new ErrorException("ffprobe returned non-zero code", $code, $output);
}

$joinedOutput = join(' ', $output);
$parsedOutput = json_decode($joinedOutput);
if (null === $parsedOutput) {
    throw new ErrorException("Unable to parse ffprobe output", $code, $output);
}

//here we can use $parsedOutput as simple stdClass
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...