查询音频/视频文件的信息

发布于 2024-09-27 04:43:12 字数 965 浏览 13 评论 0原文

我想要一个 PHP 函数,它接收文件的路径并返回有关该文件的信息数组。 PHP文件可以调用FFmpeg。

返回的数据应该类似于

Array(
    [mime]          => video/ogg
    [container]     => Ogg
    [video]         => Theora
    [audio]         => Vorbis
    [duration]      => 20.3 // in seconds
)

Array(
    [mime]          => audio/ogg
    [container]     => Ogg
    [video]         =>
    [audio]         => FLAC
    [duration]      => 3
)

Array(
    [mime]          => image/gif
    [container]     => GIF
    [video]         => Animated GIF
    [audio]         =>
    [duration]      => 2
)

Array(
    [mime]          => video/webm
    [container]     => WebM
    [video]         => VP8
    [audio]         => Vorbis
    [duration]      => 900.7
)

false // not a media file

我从未使用过 FFmpeg 或 PHP 的 shell_exec() 函数,但 FFmpeg 似乎会以相当难以理解的方式提供有关视频(或音频文件)的信息解析格式。不过,我认为这样的事情是可能的。

I want a PHP function which receives the path to a file and returns an array of information about it. The PHP file can call FFmpeg.

Returned data should be something like

Array(
    [mime]          => video/ogg
    [container]     => Ogg
    [video]         => Theora
    [audio]         => Vorbis
    [duration]      => 20.3 // in seconds
)

Array(
    [mime]          => audio/ogg
    [container]     => Ogg
    [video]         =>
    [audio]         => FLAC
    [duration]      => 3
)

Array(
    [mime]          => image/gif
    [container]     => GIF
    [video]         => Animated GIF
    [audio]         =>
    [duration]      => 2
)

Array(
    [mime]          => video/webm
    [container]     => WebM
    [video]         => VP8
    [audio]         => Vorbis
    [duration]      => 900.7
)

false // not a media file

I've never worked with FFmpeg or with PHP's shell_exec() function, but it seems that FFmpeg will give information about videos (or audio files) in a fairly hard-to-parse format. I assume that something like this is possible, though.

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

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

发布评论

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

评论(4

酒绊 2024-10-04 04:43:12

FFmpeg 几乎可以完成您想要的所有操作,但您是对的,它的格式几乎无法解析。如果您在基于 UNIX 的系统上使用操作系统和 FFmpeg 的功能来进行解析,而不是让 PHP 尝试理解输出,实际上会更快。几个月前,我出于类似的目的开发了以下 shell 命令。

fulltime=`ffmpeg -i MOVIE.AVI 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//`;hour=`echo $fulltime | cut -d ':' -f 1`;minute=`echo $fulltime | cut -d ':' -f 2`;second=`echo $fulltime | cut -d ':' -f 3 | cut -d '.' -f 1`;echo `expr 3600 \* $hour + 60 \* $minute + $second`

管道 (|) 告诉 UNIX 将上一个命令的输出作为下一个命令的输入传递。分号 (;) 告诉 UNIX 开始一个新命令。 UNIX shell 还允许动态创建变量。要创建变量,您只需输入var=value。要调用此变量,您必须使用美元符号,例如 $var

我的命令本质上采用 ffmpeg -i MOVIE.AVI 2>&1 | 的输出grep '持续时间' |切 -d ' ' -f 4 | sed s/,// 并将其存储为 fulltime。该命令进一步细分为:

ffmpeg -i MOVIE.AVI 2>&1 表示显示 MOVIE.AVI 的信息 (-i)。我相信 2>&1 将输出重定向到管道而不是屏幕(很久以前就做了这个,所以我不清楚)

grep 'Duration' 将获取输入(这是 ffmpeg -i MOVIE.AVI 2>&1 的输出),找到单词“Duration”,并仅输出包含该单词的行。

cut -d ' ' -f 4 将获取输入(上一条语句的输出),在每个空格处将其分割 (' '),并仅输出其中第四个。这是因为 FFmpeg 的输出看起来像这样:

MOVIE.AVI
video encoder, yada yada
audio encoder, yada yada
bitrates and stuff
Duration: hh:mm:ss fulltime: 00:30:00.1

换句话说,包含“Duration”的行的第四个“部分”是实际持续时间...以小时、分钟和秒为单位(带 1 位小数)。

sed s/,// 表示将 ',' 替换为空。这可能是有充分理由的。

之后,我创建了三个变量 hourmonthsecond

hour=`echo $fulltime | cut -d ':' -f 1`;
minute=`echo $fulltime | cut -d ':' -f 2`;
second=`echo $fulltime | cut -d ':' -f 3 | cut -d '.' -f 1`;

请注意,我将 hour 设置为 echo 的输出$全职|剪切 -d ':' -f 1。如果我要在每个冒号处分割时间(:),抓住第一部分,

我对分钟做类似的事情,然后我只对秒做同样的事情,我在末尾截掉任何小数。如果您在 shell 中工作,则必须删除此小数,因为 expr 命令(我用它来根据小时、分钟和秒计算秒)仅执行整数数学运算。如果您希望保留持续时间的小数,此时您必须将小时、分钟和秒返回给 PHP 并在那里进行解析。通过将上面的内容替换为最容易做到这一点:

echo $fulltime

在调用 shell_exec() 后,这将向 PHP 返回一个字符串,例如“00:30:00.1”,然后您可以使用以下命令轻松解析该字符串爆炸(':',$string)

继续直接从 shell 获取秒:

获取小时、分钟和秒后,出现了神奇的一行:

echo `expr 3600 \* $hour + 60 \* $minute + $second`

expr 命令表示执行数学表达式。不幸的是,这是相当愚蠢的。首先,特殊字符需要转义(*在UNIX中是通配符,所以必须使用\*来表示乘法)。接下来,它仅执行整数数学运算。正如您所看到的,将小时乘以 3600、分钟乘以 60,然后将它们全部相加,这是相当容易的。

整个庞大命令的输出只是一个数字。视频持续的秒数。它应该适用于所有视频格式。

请注意,这只是持续时间。至于视频编码器和音频编码器,您需要使用类似的方法,减去最后的数学。一个通用的解决方案是:

ffmpeg -i MOVIE.AVI 2>&1 | grep 'Something unique to the line you want' | cut -d ' ' -f <the "section" you want>

它的输出可以继续在 shell 中解析(就像我上面所做的那样),也可以将其传递给 PHP。

FFmpeg can do just about everything you want, but you're correct that it's in a nearly impossible to parse format. It's actually quicker if you're on a UNIX-based system to use the Operating System and the features of FFmpeg to do the parsing rather than have PHP try to understand the output. I developed the following shell command several months ago for a similar purpose.

fulltime=`ffmpeg -i MOVIE.AVI 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//`;hour=`echo $fulltime | cut -d ':' -f 1`;minute=`echo $fulltime | cut -d ':' -f 2`;second=`echo $fulltime | cut -d ':' -f 3 | cut -d '.' -f 1`;echo `expr 3600 \* $hour + 60 \* $minute + $second`

The pipe (|) tells UNIX to pass the output of the previous command as the input to the next command. The semi-colon (;) tells UNIX to begin a new command. The UNIX shell also allows for on-the-fly variable creation. To create a variable you just say var=value. To recall this variable you must use a dollar-sign, such as $var.

My command essentially takes the output of ffmpeg -i MOVIE.AVI 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,// and stores it as fulltime. This command is further broken down:

ffmpeg -i MOVIE.AVI 2>&1 means to display info (-i) for MOVIE.AVI. The 2>&1 I believe redirected the output to a pipe rather than to the screen (made this forever ago, so I'm not clear on that)

grep 'Duration' will take the input (which was the output of ffmpeg -i MOVIE.AVI 2>&1), find the word 'Duration', and output only the line that contained that word.

cut -d ' ' -f 4 will take the input (the output of the previous statement), split it up at every space (' '), and output only the fourth of these. This is because the output of FFmpeg looks something like:

MOVIE.AVI
video encoder, yada yada
audio encoder, yada yada
bitrates and stuff
Duration: hh:mm:ss fulltime: 00:30:00.1

In other words, the fourth "section" of the line containing "Duration" is the actual duration... In hours, minutes, and seconds (with 1 decimal place).

sed s/,// means to replace ',' with nothing. There was probably a good reason for this.

After this I created the three variables hour, minute, and second:

hour=`echo $fulltime | cut -d ':' -f 1`;
minute=`echo $fulltime | cut -d ':' -f 2`;
second=`echo $fulltime | cut -d ':' -f 3 | cut -d '.' -f 1`;

Notice that I'm setting hour to the output of echo $fulltime | cut -d ':' -f 1. Grabbing the first portion if I were to split the time at every colon (:)

I do similar with minutes, then I do the same with seconds only I chop off any decimal at the end. This decimal has to be removed if you're working in shell since the expr command (which I used to calculate seconds from hours, minutes, and seconds) only performs integer math. If you wish to keep the decimal for duration, you will at this point have to return the hours, minutes, and seconds to PHP and do the parsing there. This would be most easily done by replacing the above with:

echo $fulltime

This will return a string such as "00:30:00.1" to PHP after you have called shell_exec(), which you can then easily parse using explode(':',$string).

To continue with getting the seconds directly from shell:

After getting the hours, minutes, and seconds came the magical line:

echo `expr 3600 \* $hour + 60 \* $minute + $second`

The expr command says to perform a mathematical expression. Unfortunately it's rather stupid. First, special characters need to be escaped (* is a wildcard in UNIX, so you have to use \* to mean multiply). Next, it only performs integer math. It was fairly easy, as you can see, to multiply hours by 3600, minutes by 60, and add them all together.

The output of this entire, massive command, will just be a single number. The number of seconds that the video lasts. It should work for all video formats.

Mind you this is just duration. As for video encoder and audio encoder you would want to use similar methods, minus the math at the end. A generic solution would be:

ffmpeg -i MOVIE.AVI 2>&1 | grep 'Something unique to the line you want' | cut -d ' ' -f <the "section" you want>

The output of this can either continue to be parsed in shell (as I did above with the time) or it can be passed to PHP.

猫腻 2024-10-04 04:43:12

我会看一下 Mediainfo。如果你传入 --Output=XML,它会给你这样的东西:

<?xml version="1.0" encoding="UTF-8"?>
<Mediainfo>
<File>
<track type="General">
<Complete_name>Movie.webm</Complete_name>
<Format>Matroska</Format>
<File_size>215 MiB</File_size>
<Duration>28mn 39s</Duration>
<Overall_bit_rate>1 049 Kbps</Overall_bit_rate>
<Movie_name>Safari</Movie_name>
<Writing_application>Lavf52.78.0</Writing_application>
<Writing_library>Lavf52.78.0</Writing_library>
</track>

<track type="Video">
<ID>1</ID>
<Format>V_VP8</Format>
<Codec_ID>V_VP8</Codec_ID>
<Duration>28mn 39s</Duration>
<Bit_rate>529 Kbps</Bit_rate>
<Width>768 pixels</Width>
<Height>432 pixels</Height>
<Display_aspect_ratio>16:9</Display_aspect_ratio>
<Frame_rate>25.000 fps</Frame_rate>
<Bits__Pixel_Frame_>0.064</Bits__Pixel_Frame_>
<Stream_size>108 MiB (50%)</Stream_size>
<Language>Norwegian</Language>
</track>

<track type="Audio">
<ID>2</ID>
<Format>Vorbis</Format>
<Format_settings__Floor>1</Format_settings__Floor>
<Codec_ID>A_VORBIS</Codec_ID>
<Duration>28mn 39s</Duration>
<Bit_rate_mode>Constant</Bit_rate_mode>
<Bit_rate>500 Kbps</Bit_rate>
<Channel_s_>2 channels</Channel_s_>
<Sampling_rate>48.0 KHz</Sampling_rate>
<Resolution>16 bits</Resolution>
<Stream_size>102 MiB (48%)</Stream_size>
<Writing_library>libVorbis 20090709 (UTC 2009-07-09)</Writing_library>
<Language>Norwegian</Language>
</track>
</File>
</Mediainfo>

I'd take a look at Mediainfo. If you pass in --Output=XML, it'll give you something like this:

<?xml version="1.0" encoding="UTF-8"?>
<Mediainfo>
<File>
<track type="General">
<Complete_name>Movie.webm</Complete_name>
<Format>Matroska</Format>
<File_size>215 MiB</File_size>
<Duration>28mn 39s</Duration>
<Overall_bit_rate>1 049 Kbps</Overall_bit_rate>
<Movie_name>Safari</Movie_name>
<Writing_application>Lavf52.78.0</Writing_application>
<Writing_library>Lavf52.78.0</Writing_library>
</track>

<track type="Video">
<ID>1</ID>
<Format>V_VP8</Format>
<Codec_ID>V_VP8</Codec_ID>
<Duration>28mn 39s</Duration>
<Bit_rate>529 Kbps</Bit_rate>
<Width>768 pixels</Width>
<Height>432 pixels</Height>
<Display_aspect_ratio>16:9</Display_aspect_ratio>
<Frame_rate>25.000 fps</Frame_rate>
<Bits__Pixel_Frame_>0.064</Bits__Pixel_Frame_>
<Stream_size>108 MiB (50%)</Stream_size>
<Language>Norwegian</Language>
</track>

<track type="Audio">
<ID>2</ID>
<Format>Vorbis</Format>
<Format_settings__Floor>1</Format_settings__Floor>
<Codec_ID>A_VORBIS</Codec_ID>
<Duration>28mn 39s</Duration>
<Bit_rate_mode>Constant</Bit_rate_mode>
<Bit_rate>500 Kbps</Bit_rate>
<Channel_s_>2 channels</Channel_s_>
<Sampling_rate>48.0 KHz</Sampling_rate>
<Resolution>16 bits</Resolution>
<Stream_size>102 MiB (48%)</Stream_size>
<Writing_library>libVorbis 20090709 (UTC 2009-07-09)</Writing_library>
<Language>Norwegian</Language>
</track>
</File>
</Mediainfo>
献世佛 2024-10-04 04:43:12

可能想尝试一下这个人。当你可以利用库时总是好的:
http://www.phpclasses.org/browse/file/1582.html

Might want to try this guy out. Always good when you can leverage a library:
http://www.phpclasses.org/browse/file/1582.html

旧街凉风 2024-10-04 04:43:12

在搜索 php 音频解析器时发现 http://getid3.sourceforge.net/

希望这有帮助,

Cears

Found http://getid3.sourceforge.net/ when searching for php audio parser

Hope this helps,

Chears

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