查询音频/视频文件以获取信息 [英] Querying an audio/video file for information

查看:184
本文介绍了查询音频/视频文件以获取信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



返回的数据应该像

 数组(
[mime] => video / ogg
[container] => Ogg
[video] =&The Theory
[audio] => Vorbis
[duration] => 20.3 // in seconds


数组(
[mime] => audio / ogg
[container] => Ogg
[video] =>
[audio] => FLAC
[duration] => 3


数组(
[mime] => image / gif
[container] => GIF
[video] =>动画GIF
[音频] =>
[duration] => 2


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


false //不是媒体文件

我从来没有使用过FFmpeg或PHP的 shell_exec()函数,但是似乎FFmpeg将以相当难以解析的格式给出关于视频(或音频文件)的信息。

解决方案

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

  fulltime =`ffmpeg -i MOVIE.AVI 2& amp ; 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外壳还允许即时变量创建。要创建一个变量,你只需要说 var = value 。要调用此变量,您必须使用美元符号,例如 $ var



我的命令本质上是输出 ffmpeg -i MOVIE.AVI 2>& 1 | grep'Duration'| cut -d''-f 4 | sed s /,// 并将其存储为 fulltime 。此命令进一步细分:



ffmpeg -i MOVIE.AVI 2>& 1 表示显示信息( -i )为MOVIE.AVI。 2>& 1 我认为将输出重定向到管道而不是屏幕(这是永远之前,所以我不清楚)



grep'持续时间'将输入(这是 ffmpeg -i MOVIE的输出)。 AVI 2& 1 ),找到持续时间一词,只输出包含该单词的行。



cut -d''-f 4 将采用输入(上一个语句的输出),将其分割成每个空格(''),并且只输出其中的第四个。这是因为FFmpeg的输出看起来像:

  MOVIE.AVI 
视频编码器,yada yada
音频编码器,yada yada
比特率和东西
持续时间:hh:mm:ss fulltime:00:30:00.1

$换句话说,包含持续时间的行的第四个段是实际持续时间...以小时,分钟和秒(小数点后1位)。



sed s /,// 表示替换','没有任何东西。这可能是一个很好的理由。



此后,我创建了三个变量 hour 分钟

  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 $ fulltime | cut -d':'-f 1 。如果我要分割每个冒号的时间,请抓住第一部分(



,那么我做同样的时间只有我把任何十进制的结尾。由于 expr 命令(我用于计算从小时,分钟和秒的秒数)的命令只能执行整数运算,所以必须删除该小数位。如果您希望保持十进制持续时间,您将在此时返回PHP的小时,分​​钟和秒数,并在那里进行解析。通过以下方式替换以下内容,最容易做到这一点:

  echo $ fulltime 
调用 shell_exec(),然后您可以使用 explode(':',$ string)轻松地解析。



继续直接从shell获取秒数:



获得小时,分钟和秒钟后,出现了神奇的线条:

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

expr 命令表示执行数学表达式。不幸的是,这很愚蠢首先,需要转义特殊字符( * 是UNIX中的通配符,因此您必须使用 \ * 意思是乘法)。接下来,它只执行整数数学。这是相当容易的,你可以看到,乘以3600,几分钟乘以60,并将它们全部加在一起。



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



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

  ffmpeg -i MOVIE.AVI 2>& 1 | grep你想要的线条独特的东西| cut -d''-f<你想要的部分> 

这个输出可以继续在shell中解析(就像我在上面那样)或者它可以传递给PHP。


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.

解决方案

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.

这篇关于查询音频/视频文件以获取信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆