Запрос аудио/видео файла для получения информации
Мне нужна функция 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 предоставит информацию о видео (или аудиофайлах) в довольно сложном для анализа формате. Однако я предполагаю, что нечто подобное возможно.
4 answers
FFMPEG может делать практически все, что вы хотите, но вы правы, что его практически невозможно разобрать в формате. На самом деле быстрее, если вы работаете в системе на базе UNIX, использовать операционную систему и функции FFmpeg для выполнения синтаксического анализа, а не пытаться понять вывод PHP. Я разработал следующую команду оболочки несколько месяцев назад для аналогичной цели.
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 также позволяет создавать переменные "на лету". Чтобы создать переменную, вы просто говорите 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 'Duration'
примет ввод (который был выводом ffmpeg -i MOVIE.AVI 2>&1
), найдет слово "Длительность" и выведет только строку, содержащую это слово.
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
Другими словами, четвертый "раздел" строка, содержащая "Продолжительность", является фактической продолжительностью... В часах, минутах и секундах (с 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`;
Обратите внимание, что я устанавливаю час на выход echo $fulltime | cut -d ':' -f 1
. Хватаю первую порцию, если бы мне пришлось делить время на каждую двоеточие (:
)
Я делаю то же самое с минутами, затем я делаю то же самое с секундами, только я отрубаю любую десятичную дробь в конце. Это десятичное число должно быть удалено, если вы работаете в оболочке, так как команда expr
(которую я использовал для вычисления секунд из часов, минут и секунд) выполняет только целочисленную математику. Если вы хотите сохранить десятичную дробь для продолжительности, на этом этапе вам придется вернуть часы, минуты и секунды в PHP и выполнить синтаксический анализ там. Это было бы проще всего сделать, заменив вышеприведенное на:
echo $fulltime
Это вернет строку, такую как "00:30:00.1" на PHP после того, как вы вызвали shell_exec()
, который затем вы можете легко проанализировать с помощью explode(':',$string)
.
Чтобы продолжить получение секунд непосредственно из оболочки:
После получения часов, минут и секунд появилась волшебная строка:
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>
Вывод этого может либо продолжать анализироваться в оболочке (как я делал выше со временем), либо его можно передать в PHP.
Я бы взглянул на 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>
Возможно, вам захочется попробовать этого парня. Всегда хорошо, когда вы можете использовать библиотеку: http://www.phpclasses.org/browse/file/1582.html