Using ffmpeg via PHP - weird problem with output

Discussion in 'PHP' started by PoPSiCLe, Sep 28, 2016.

  1. #1
    Okay, I'm using ffmpeg to create a thumbnail from a video I upload. That part works just fine, but accessing the $output-array from ffmpeg after it has been executed... that's a completely different matter.

    It outputs an array with different information (based on type of file etc) - what I want is the one line with the name of the newly created image-file.

    Here's the line I use for ffmpeg:
    
    exec("/usr/local/bin/ffmpeg -i $video -deinterlace -an -ss 1 -t 00:00:01 -r 1 -y -vcodec mjpeg -f mjpeg $thumbnail 2>&1",$output,$retval);
    
    PHP:
    This works fine - the video is saved, the image is created, and $output is populated. So far so good.
    An example output:
    
    Array
    (
    [0] => ffmpeg version 2.8.4 Copyright (c) 2000-2015 the FFmpeg developers
    [1] => built with Apple LLVM version 7.0.2 (clang-700.1.81)
    [2] => configuration: --prefix=/usr/local/Cellar/ffmpeg/2.8.4 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-opencl --enable-libx264 --enable-libmp3lame --enable-libvo-aacenc --enable-libxvid --enable-vda
    [3] => libavutil 54. 31.100 / 54. 31.100
    [4] => libavcodec 56. 60.100 / 56. 60.100
    [5] => libavformat 56. 40.101 / 56. 40.101
    [6] => libavdevice 56. 4.100 / 56. 4.100
    [7] => libavfilter 5. 40.101 / 5. 40.101
    [8] => libavresample 2. 1. 0 / 2. 1. 0
    [9] => libswscale 3. 1.101 / 3. 1.101
    [10] => libswresample 1. 2.101 / 1. 2.101
    [11] => libpostproc 53. 3.100 / 53. 3.100
    [12] => Input #0, flv, from '/Applications/MAMP/htdocs/medialist/users/public/video/videofile.flv':
    [13] => Duration: 00:11:33.04, start: 0.000000, bitrate: 1013 kb/s
    [14] => Stream #0:0: Video: h264 (Main), yuv420p(tv), 800x600 [SAR 1:1 DAR 4:3], 30.30 fps, 30 tbr, 1k tbn, 60 tbc
    [15] => Stream #0:1: Audio: speex, 16000 Hz, mono
    [16] => [swscaler @ 0x7f9109870c00] deprecated pixel format used, make sure you did set range correctly
    [17] => Output #0, mjpeg, to '/Applications/MAMP/htdocs/medialist/users/public/pictures/thumbs/videofile.flv.jpg':
    [18] => Metadata:
    [19] => encoder : Lavf56.40.101
    [20] => Stream #0:0: Video: mjpeg, yuvj420p(pc), 800x600 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 1 fps, 1 tbn, 1 tbc
    [21] => Metadata:
    [22] => encoder : Lavc56.60.100 mjpeg
    [23] => Stream mapping:
    [24] => Stream #0:0 -> #0:0 (h264 (native) -> mjpeg (native))
    [25] => Press [q] to stop, [?] for help
    [26] => frame= 1 fps=0.0 q=4.5 Lsize= 23kB time=00:00:01.00 bitrate= 188.1kbits/s
    [27] => video:23kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
    )
    
    PHP:
    Seems like a completely normal array to me. I need to get the line that starts with "Output #0, mjpeg" - unfortunately, it's not consistently at #17, so I can't use $output[17] to get the right information.

    Okay - let's say we use array_search() - this:
    
    if (($key = array_search('Output',$output)) != false) {
    echo $output[$key];
    }
    
    PHP:
    does not work - it just returns false if I do a var_dump();

    If I try to do the same with in_array('Output',$output) same result. Ie, the information I get seems to not be in the array.

    I also try to parse the array through a foreach, and do a strpos() on the $value - still it didn't trigger on the "output" - I'm lost. I have no idea why I don't get the information I want - if I var_dump() each $value in the foreach, they get returned as string(XX) and the content of value. So they are strings, and should work as strings/regular arrays. But they don't, and I'm at a loss for why.

    Anybody got any bright ideas?
     
    PoPSiCLe, Sep 28, 2016 IP
  2. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #2
    Oh, well, I'm usually good at finding solutions for my own problems. Did a bit more research, and found that if I did like this:
    
    $output = shell_exec("/usr/local/bin/ffmpeg -i $video -deinterlace -an -ss 1 -t 00:00:01 -r 1 -y -vcodec mjpeg -f mjpeg $thumbnail 2>&1");
    //and parsed it like this:
    echo explode(':',explode('to',$output)[1])[0];
    
    PHP:
    I got exactly what I needed
     
    PoPSiCLe, Sep 28, 2016 IP
  3. ThePHPMaster

    ThePHPMaster Well-Known Member

    Messages:
    737
    Likes Received:
    52
    Best Answers:
    33
    Trophy Points:
    150
    #3
    In case you are wondering why array_search didn't work it is because it was looking for an exact match (==). It has a third param when set to true does an exact type match (===).
     
    ThePHPMaster, Sep 30, 2016 IP
  4. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #4
    Okay, I can see how that might be right, but why would in_array() not work either? I'm suspecting there was another issue with the return values, but since I figured out how to do it regardless, I'm not gonna bother investigating it right now, at least.
     
    PoPSiCLe, Sep 30, 2016 IP
  5. ThePHPMaster

    ThePHPMaster Well-Known Member

    Messages:
    737
    Likes Received:
    52
    Best Answers:
    33
    Trophy Points:
    150
    #5
    The same reason as array_search. All search functionality for arrays (unlike strings) don't do partial search, it has to be the full needle you are looking for.
     
    ThePHPMaster, Oct 1, 2016 IP
  6. Einheijar

    Einheijar Well-Known Member

    Messages:
    539
    Likes Received:
    13
    Best Answers:
    3
    Trophy Points:
    165
    #6
    
    function array_find($needle, array $haystack)
    {
    foreach ($haystack as $key => $value) {
    if (false !== stripos($value, $needle)) {
    return $key;
    }
    }
    return false;
    }
    
    Code (php):
    You're probably looking for something like this, it's messy but it works
     
    Einheijar, Oct 2, 2016 IP