查询音频/视频文件以获取信息

TRi*_*RiG 5 php ffmpeg shell-exec

我想要一个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
Run Code Online (Sandbox Code Playgroud)

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

ste*_*esu 10

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`
Run Code Online (Sandbox Code Playgroud)

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

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

ffmpeg -i MOVIE.AVI 2>&1表示显示-iMOVIE.AVI的info().该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
Run Code Online (Sandbox Code Playgroud)

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

sed s/,//意味着毫无意义地替换','.这可能是一个很好的理由.

在此之后,我创建了三个变量hour,minute以及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`;
Run Code Online (Sandbox Code Playgroud)

请注意,我将小时设置为输出echo $fulltime | cut -d ':' -f 1.如果我要在每个冒号分开时间,抓住第一部分(:)

我做了与分钟类似的事情,然后我用秒做同样的事情我只在最后砍掉任何小数.如果您在shell中工作,则必须删除此十进制数,因为该expr命令(我用于计算小时,分钟和秒的秒数)仅执行整数数学运算.如果你希望保持小数的持续时间,你将在这一点上必须返回PHP的小时,分​​钟和秒,并在那里进行解析.通过将以上内容替换为以下内容,最容易实现:

echo $fulltime
Run Code Online (Sandbox Code Playgroud)

这将在您调用之后向PHP返回一个字符串,例如"00:30:00.1" shell_exec(),然后您可以使用它轻松解析explode(':',$string).

要继续直接从shell获取秒数:

在获得了几小时,几分钟和几秒钟之后,出现了神奇的界限:

echo `expr 3600 \* $hour + 60 \* $minute + $second`
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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