問題描述
我想要一個 PHP 函數,它接收文件的路徑并返回有關它的信息數組.PHP文件可以調用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.
返回的數據應該類似于
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'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 幾乎可以做您想做的一切,但您說得對,它幾乎無法解析格式.如果您在基于 UNIX 的系統上使用操作系統和 FFmpeg 的功能進行解析,而不是讓 PHP 嘗試理解輸出,那么實際上會更快.幾個月前,我出于類似目的開發了以下 shell 命令.
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`
管道 (|
) 告訴 UNIX 將前一個命令的輸出作為輸入傳遞給下一個命令.分號 (;
) 告訴 UNIX 開始一個新命令.UNIX shell 還允許動態創建變量.要創建變量,您只需說var=value
.要調用此變量,您必須使用美元符號,例如 $var
.
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
.
我的命令基本上采用 ffmpeg -i MOVIE.AVI 2>&1 | 的輸出grep '持續時間' |剪切 -d ' ' -f 4 |sed s/,//
并將其存儲為 fulltime
.此命令進一步細分:
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
表示顯示 MOVIE.AVI 的信息(-i
).2>&1
我相信將輸出重定向到管道而不是屏幕(這是很久以前做的,所以我不清楚)
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'
將獲取輸入(這是 ffmpeg -i MOVIE.AVI 2>&1
的輸出),找到單詞 'Duration', 并僅輸出包含該單詞的行.
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
將獲取輸入(前一條語句的輸出),在每個空格處將其拆分(' '
),然后只輸出其中的第四個.這是因為 FFmpeg 的輸出看起來像:
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
換句話說,包含持續時間"的行的第四個部分"是實際持續時間……以小時、分鐘和秒為單位(保留 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/,//
表示將 ',' 替換為空.這可能是有充分理由的.
sed s/,//
means to replace ',' with nothing. There was probably a good reason for this.
在此之后,我創建了三個變量 hour
、minute
和 second
:
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`;
請注意,我正在為 echo $fulltime | 的輸出設置小時.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 (:
)
我對分鐘做了類似的處理,然后我對秒做同樣的處理,只是在最后去掉了任何小數點.如果您在 shell 中工作,則必須刪除這個小數點,因為 expr
命令(我曾經用它從小時、分鐘和秒計算秒)只執行整數數學運算.如果您希望在持續時間內保留小數,此時您必須將小時、分鐘和秒返回給 PHP 并在那里進行解析.將以上內容替換為:
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
這將在您調用 shell_exec()
后向 PHP 返回一個字符串,例如00:30:00.1",然后您可以使用 explode(':',$string)
.
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)
.
繼續直接從 shell 獲取秒數:
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`
expr
命令表示執行數學表達式.不幸的是,它相當愚蠢.首先,需要對特殊字符進行轉義(*
在 UNIX 中是通配符,因此必須使用 *
表示乘法).接下來,它只執行整數數學.如您所見,將小時乘以 3600,分鐘乘以 60,然后將它們加在一起是相當容易的.
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>
這個輸出可以繼續在 shell 中解析(就像我在上面所做的那樣)或者它可以傳遞給 PHP.
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.
這篇關于查詢音頻/視頻文件的信息的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!