以编程方式确定视频文件格式?

时间:2008-09-20 23:54:11

标签: php linux video file-io binaryfiles

好的,我得到了视频格式的基础知识 - 有一些容器格式,然后你有核心视频/音频格式。我想编写一个基于Web的应用程序来确定文件正在使用的视频/音频编解码器。

如何以编程方式确定视频编解码器?是否最好通过系统调用使用标准库并解析其输出? (例如ffmpeg,转码等?)

6 个答案:

答案 0 :(得分:7)

mplayer -identify会做到这一点。只需在文件上调用ffmpeg也可以 - 它会在开始时自动打印一组关于输入文件的信息,无论你告诉ffmpeg实际做什么。

当然,如果你想在没有exec调用外部程序的情况下从你的程序中执行它,你可以直接包含avcodec库并运行它自己的识别例程。

虽然你可以实现自己的检测,但鉴于libav *支持绝对庞大的格式,它肯定会不如现有的例程。重新发明轮子将是一个相当愚蠢的案例。

Linux的“文件”命令也可以解决问题,但打印出来的数据量取决于视频格式。例如,在AVI上,它提供了有关分辨率,FOURCC,fps等的各种数据,而对于MKV文件,它只是说“Matroska数据”,不会告诉您内部,甚至是所使用的视频和音频格式。< / p>

答案 1 :(得分:4)

我在perl脚本中使用了FFMPEG来实现这一点。

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

然后找出你需要提取的@fields中的哪些项目。

答案 2 :(得分:1)

你需要从头开始。您需要知道容器格式以及它如何指定编解码器。

所以我从一个识别容器格式的程序开始(不只是从扩展名,进入标题并确定真正的容器)。

然后找出程序将支持哪些容器,并输入解析存储在容器中的元数据所需的函数,其中包括编解码器。

- 亚当

答案 3 :(得分:1)

您真的想要一个二进制识别标记的大型数据库,以便在文件开头附近查找。幸运的是,你的问题被标记为“Linux”,而且这样的数据库已经存在; file(1)将为您完成工作。

答案 4 :(得分:0)

我建议使用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

答案 5 :(得分:0)

您可以使用mediainfo:

sudo apt-get install mediainfo

如果您只想获得视频/音频编解码器,可以执行以下操作:

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

如果您想捕获更多信息,可以解析mediainfo返回的XML输出。这是样本函数:

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