2008-09-20 82 views
6

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

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

回答

7

mplayer -identify会做伎俩。只需在文件上调用ffmpeg也将起作用 - 它将在输入文件的开始处自动打印一组信息,无论您是在告诉ffmpeg实际执行什么操作。

当然,如果你想从你的程序没有exec调用外部程序来完成它,你可以直接包含avcodec库并运行它自己的识别程序。

尽管您可以实现自己的检测,但由于libav *支持绝对数量的格式,它肯定会劣于现有的例程。这将是一个相当愚蠢的重新发明车轮的情况。

Linux的“文件”命令也可以做到这一点,但打印出的数据量取决于视频格式。例如,在AVI上,它提供了关于分辨率,FOURCC,fps等各种数据,而对于MKV文件,它只是说“Matroska数据”,不会告诉你关于内部,甚至是所用的视频和音频格式。

1

您需要开始更进一步。您需要知道容器格式以及它如何指定编解码器。

因此,我将从一个程序开始,该程序标识容器格式(不仅仅来自扩展,进入标题并确定真正的容器)。

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

- 亚当

1

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

+0

这不够远。文件告诉你一点,但不是OP所要求的编解码器。 – 2008-09-21 06:08:03

4

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

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

只需找出@fields中需要提取的项目。

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 
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], 
    ); 
} 
相关问题