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

发布于 2024-07-05 23:19:04 字数 158 浏览 10 评论 0原文

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

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

Ok, I get the basics of video format - there are some container formats and then you have core video/audio formats. I would like to write a web based application that determines what video/audio codec a file is using.

How best can I programmatically determine a video codec? Would it be best to use a standard library via system calls and parse its output? (eg ffmpeg, transcode, etc?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

神爱温柔 2024-07-12 23:19:04

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

当然,如果您想从程序中执行此操作,而不需要对外部程序进行 exec 调用,则可以仅包含 avcodec 库并直接运行其自己的识别例程。

虽然您可以实现自己的检测,但考虑到 libav* 支持的格式绝对数量巨大,它肯定会不如现有例程。 这将是一个相当愚蠢的重新发明轮子的例子。

Linux 的“file”命令也可以做到这一点,但它打印出的数据量取决于视频格式。 例如,在 AVI 上,它提供有关分辨率、FOURCC、fps 等的各种数据,而对于 MKV 文件,它只显示“Matroska 数据”,不告诉您任何有关内部结构的信息,甚至不告诉您所使用的视频和音频格式。

mplayer -identify will do the trick. Just calling ffmpeg on a file will also work--it will automatically print a set of info at the start about the input file regardless of what you're telling ffmpeg to actually do.

Of course, if you want to do it from your program without an exec call to an external program, you can just include the avcodec libraries and run its own identify routine directly.

While you could implement your own detection, it will surely be inferior to existing routines given the absolutely enormous number of formats that libav* supports. And it would be a rather silly case of reinventing the wheel.

Linux's "file" command can also do the trick, but the amount of data it prints out depends on the video format. For example, on AVI it gives all sorts of data about resolution, FOURCC, fps, etc, while for an MKV file it just says "Matroska data," telling you nothing about the internals, or even the video and audio formats used.

我在 perl 脚本中使用 FFMPEG 来实现此目的。

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

只需找出您需要提取@fields 中的哪些项目即可。

I have used FFMPEG in a perl script to achieve this.

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

And just find out what items in @fields you need to extract.

远昼 2024-07-12 23:19:04

你需要从更远的地方开始。 您需要了解容器格式以及它如何指定编解码器。

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

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

-亚当

You need to start further down the line. You need to know the container format and how it specifies the codec.

So I'd start with a program that identifies the container format (not just from the extension, go into the header and determine the real container).

Then figure out which containers your program will support, and put in the functions required to parse the meta data stored in the container, which will include the codecs.

-Adam

囍孤女 2024-07-12 23:19:04

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

You really want a big database of binary identifying markers to look for near the start of the file. Luckily, your question is tagged "Linux", and such a dabase already exists there; file(1) will do the job for you.

静若繁花 2024-07-12 23:19:04

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

I would recommend using ffprobe and force output format to json. It would be so much easier to parse. Simplest example:

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

Be warned that in the case of corrupted file you will get null as result and warning depending on your error reporting settings. Complete example with proper error handling:

$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
任性一次 2024-07-12 23:19:04

您可以使用 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],
    );
}

You can use mediainfo:

sudo apt-get install mediainfo

If you just want to get video/audio codec, you can do the following:

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

In case you want to capture more info, you can parse XML output returned by mediainfo. Here is sample function:

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],
    );
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文