Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parse ffmpeg info in PHP?

Tags:

php

ffmpeg

How does one go about getting specific pieces of information, like the 'duration' from the output of ffmpeg -i /var/thismovie.avi ?

I need frame height, frame width, duration of movie and frame rate. All of these are in the out put of the above command but how do i get the bits i need individually and put them in a variable in PHP?

I've given up on trying to install ffmpeg-php which is what I used before this to do the same job.

Thanks

ffmpeg -i /var/thismovie.avi produce an output like this

ffmpeg version N-43171-ga763caf Copyright (c) 2000-2012 the FFmpeg developers built on Aug 3 2012 07:56:19 with gcc 4.1.2 (GCC) 20080704 (Red Hat 4.1.2-52) configuration: --enable-version3 --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvpx --enable-libfaac --enable-libmp3lame --enable-libtheora --enable-libvorbis --enable-pic --enable-libx264 --enable-libxvid --disable-ffplay --enable-shared --enable-gpl --enable-postproc --enable-nonfree --enable-avfilter --enable-pthreads --extra-cflags=-fPIC libavutil 51. 66.100 / 51. 66.100 libavcodec 54. 48.100 / 54. 48.100 libavformat 54. 22.100 / 54. 22.100 libavdevice 54. 2.100 / 54. 2.100 libavfilter 3. 5.102 / 3. 5.102 libswscale 2. 1.100 / 2. 1.100 libswresample 0. 15.100 / 0. 15.100 libpostproc 52. 0.100 / 52. 0.100 [avi @ 0x18e8e240] non-interleaved AVI [avi @ 0x18e8e240] max_analyze_duration 5000000 reached at 5000000 Input #0, avi, from '/var/www/vhosts/mysite.com/httpdocs/movie.avi': Duration: 00:00:10.76, start: 0.000000, bitrate: 5180 kb/s Stream #0:0: Video: h264 (High) (H264 / 0x34363248), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 25 fps, 25 tbr, 25 tbn, 50 tbc Stream #0:1: Audio: ac3 ([0] [0][0] / 0x2000), 48000 Hz, stereo, s16, 128 kb/s At least one output file must be specified` 
like image 683
Jizbo Jonez Avatar asked Aug 04 '12 01:08

Jizbo Jonez


4 Answers

Based on ffprobe solution suggested by @blahdiblah and inspired by another question answer: https://github.com/paulofreitas/php-ffprobe

Note: requires ffmpeg 0.9+, supports ALL ffmpeg supported file types

Using the class

// Example 1
$info = new ffprobe($filename);
var_dump($info->format->format_long_name); // e.g. string(10) "AVI format"
var_dump($info->streams[0]->duration);     // e.g. string(11) "5674.674675"

// Example 2 (prettified)
$info = new ffprobe($filename, true);
var_dump($info->format->format_long_name); // e.g. string(10) "AVI format"
var_dump($info->streams[0]->duration);     // e.g. string(14) "1:34:34.674675"

Extending the class

class ffprobe_ext extends ffprobe
{
    public function __construct($filename)
    {
        parent::__construct($filename);
    }

    public function getVideoStream()
    {
        foreach ($this->streams as $stream) {
            if ($stream->codec_type == 'video') {
                return $stream;
            }
        }
    }

    public function getVideoInfo()
    {
        $stream = $this->getVideoStream();
        $info   = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS);
        $info->duration     = (float) $stream->duration;
        $info->frame_height = (int) $stream->height;
        $info->frame_width  = (int) $stream->width;
        eval("\$frame_rate = {$stream->r_frame_rate};");
        $info->frame_rate   = (float) $frame_rate;

        return $info;
    }
}

$ffprobe = new ffprobe_ext($filename);
$info = $ffprobe->getVideoInfo();
var_dump($info->duration); // e.g. float(5674.674675)

Welcome to further improvements! :-)

like image 59
Paulo Freitas Avatar answered Oct 29 '22 07:10

Paulo Freitas


Use ffprobe instead.

ffprobe is the tool packaged with FFmpeg for exactly the sort've purpose you're after: extracting video info. It outputs a variety of easily parsed formats and will be far easier than parsing the incidental information that FFmpeg outputs.

For example:

$ ffprobe -show_format -loglevel quiet mptestsrc.mp4 
[FORMAT]
filename=mptestsrc.mp4
nb_streams=1
format_name=mov,mp4,m4a,3gp,3g2,mj2
format_long_name=QuickTime/MPEG-4/Motion JPEG 2000 format
start_time=0.000000
duration=12.040000
size=237687
bit_rate=157931
TAG:major_brand=isom
TAG:minor_version=512
TAG:compatible_brands=isomiso2avc1mp41
TAG:encoder=Lavf54.20.100
[/FORMAT]
like image 22
blahdiblah Avatar answered Oct 29 '22 08:10

blahdiblah


You can use ffprobe which has an option to output JSON format.

Take a look at this example:

ffprobe -v quiet -print_format json -show_format Ramp\ -\ Apathy.mp3

Which produces the follwing output:

{
    "format": {
        "filename": "Ramp - Apathy.mp3",
        "nb_streams": 2,
        "format_name": "mp3",
        "format_long_name": "MP2/3 (MPEG audio layer 2/3)",
        "start_time": "0.000000",
        "duration": "203.638856",
        "size": "4072777",
        "bit_rate": "159999",
        "tags": {
            "title": "Apathy",
            "artist": "Ramp",
            "album": "Evolution Devolution Revolution",
            "date": "1999",
            "genre": "Metal"
        }
    }
}

I'm using ffprobe version 1.0.7.

like image 8
Paulo Fidalgo Avatar answered Oct 29 '22 08:10

Paulo Fidalgo


$output = `ffmpeg -i /var/thismovie.avi`; //note that back quote is like exec
preg_match('/Duration: (.*?),.*?Video:.*?0x.*?([0-9]+)x([[0-9]+).*?([0-9]+) fps/i'
    ,$output , $result);

output of $result array should be like this:

Array
(
    [0] => Duration: 00:00:10.76, start: 0.000000, bitrate: 5180 kb/s Stream #0:0: Video: h264 (High) (H264 / 0x34363248), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 25 fps
    [1] => 00:00:10.76
    [2] => 1280
    [3] => 720
    [4] => 25
)

UPDATE

The actual output is multi line, so please update the pattern into

/Duration: (.*?),.*?([0-9]+)x([0-9]+) \[.*?([0-9]+) fps/is

like image 3
Hawili Avatar answered Oct 29 '22 09:10

Hawili