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






mplayer -identify сделает свое дело. Просто вызов ffmpeg для файла также будет работать - он автоматически распечатает в начале набор информации о входном файле, независимо от того, что вы говорите ffmpeg на самом деле.
Конечно, если вы хотите сделать это из своей программы без вызова exec к внешней программе, вы можете просто включить библиотеки avcodec и напрямую запустить собственную процедуру идентификации.
Хотя вы можете реализовать собственное обнаружение, оно наверняка будет хуже существующих подпрограмм, учитывая огромное количество форматов, поддерживаемых libav *. И изобретать велосипед было бы довольно глупо.
Команда Linux «file» также может помочь, но объем распечатываемых ею данных зависит от формата видео. Например, в AVI он предоставляет всевозможные данные о разрешении, FOURCC, fps и т. д., В то время как для файла MKV он просто говорит «данные Matroska», ничего не говоря вам о внутреннем устройстве или даже об используемых видео и аудио форматах.
Вам нужно начать дальше. Вам необходимо знать формат контейнера и то, как он определяет кодек.
Поэтому я бы начал с программы, которая определяет формат контейнера (а не только из расширения, захожу в заголовок и определяю реальный контейнер).
Затем выясните, какие контейнеры будет поддерживать ваша программа, и добавьте функции, необходимые для анализа метаданных, хранящихся в контейнере, которые будут включать кодеки.
-Адам
Вам действительно нужна большая база данных двоичных идентифицирующих маркеров, которые нужно искать в начале файла. К счастью, ваш вопрос помечен как «Linux», и такая база данных уже существует; file (1) сделает всю работу за вас.
Для этого я использовал FFMPEG в сценарии Perl.
$info = `ffmpeg -i $path$file 2>&1 /dev/null`;
@fields = split(/\n/, $info);
И просто узнайте, какие элементы в @fields вам нужно извлечь.
Я бы рекомендовал использовать 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
Вы можете использовать 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],
);
}
Этого недостаточно. файл немного сообщает вам, но не кодеки, которые запрашивает OP.