Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FFMpeg working in command line but not in PHP script

I am using FFMpeg to convert videos and it is working fine from the command line. I am using the following command:

ffmpeg -i input.avi -ab 56 -ar 44100 -b 200 -r 15 -s 320x240 -f flv output.flv

However, when I run the command using PHP script, the output video is not encoded.

exec("ffmpeg -i input.avi -ab 56 -ar 44100 -b 200 -r 15 -s 320x240 -f flv output.flv",$output, $returnvalue);

$returnvalue = 127;

FFMPEG installed path :

[root@localhost ~]# which ffmpeg

/root/bin/ffmpeg

My Script Path :

www.domainname.com/core/foldername/ffmpeg.php

Please provide me solution for the same ASAP.

Thank you.

like image 385
Jitendra Prajapati Avatar asked Nov 07 '14 04:11

Jitendra Prajapati


3 Answers

The natural way to run ffmpeg from PHP scripts is something like:

<?php
    echo "Starting ffmpeg...\n\n";
    echo shell_exec("ffmpeg -i input.avi output.avi &");
    echo "Done.\n";
?>

There are several issues that need to be pointed out here. The first one is that, although we specified we want ffmpeg to be executed in the background (using the ampersand operator "&"), PHP script will not continue it's execution until ffmpeg has finished its execution. This is due to the fact, mentioned in one of the notes for the ​PHP's exec() function that says:

If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.

Don't be confused about the example showing ​shell_exec() call instead of ​exec(). All of the ​PHP's Program execution functions share the similar code base and limitations.

So, to work around this issue, we need to do something like this:

<?php
    echo "Starting ffmpeg...\n\n";
    echo shell_exec("ffmpeg -i input.avi output.avi >/dev/null 2>/dev/null &");
    echo "Done.\n";
?>

The part that says ">/dev/null" will redirect the standard OUTPUT (stdout) of the ffmpeg instance to /dev/null (effectively ignoring the output) and "2>/dev/null" will redirect the standard ERROR (stderr) to /dev/null (effectively ignoring any error log messages). These two can be combined into a shorter representation: ">/dev/null 2>&1". If you like, you can ​read more about I/O Redirection.

An important note should be mentioned here. The ffmpeg command-line tool uses stderr for output of error log messages and stdout is reserved for possible use of pipes (to redirect the output media stream generated from ffmpeg to some other command line tool). That being said, if you run your ffmpeg in the background, you'll most probably want to redirect the stderr to a log file, to be able to check it later.

One more thing to take care about is the standard INPUT (stdin). Command-line ffmpeg tool is designed as an interactive utility that accepts user's input (usually from keyboard) and reports the error log on the user's current screen/terminal. When we run ffmpeg in the background, we want to tell ffmpeg that no input should be accepted (nor waited for) from the stdin. We can tell this to ffmpeg, using I/O redirection again ** "ffmpeg command-line tool in the background would be similar to this:

<?php
    echo "Starting ffmpeg...\n\n";
    echo shell_exec("ffmpeg -y -i input.avi output.avi </dev/null >/dev/null 2>/var/log/ffmpeg.log &");
    echo "Done.\n";
?>

The ​"-y" option is used to auto-overwrite the output file (output.avi) without asking for yes/no confirmation. If you need the opposite scenario, to auto-cancel the entire process if the output file already exists, then use "-n" option instead.

Wrapper Libraries

Some PHP libraries allow wrapping ffmpeg calls into PHP objects, and give you a nice syntax to work with if you don't like to use the command line. One of these is the actively maintained ​PHP-FFMpeg. It only requires you to ​download a recent ffmpeg and ffprobe build apart from installing the PHP components. Then you can run PHP code like this:

$ffmpeg = FFMpeg\FFMpeg::create();
$video = $ffmpeg->open('video.mpg');
$video
    ->filters()
    ->resize(new FFMpeg\Coordinate\Dimension(320, 240))
    ->synchronize();
$video
    ->save(new FFMpeg\Format\Video\X264(), 'export-x264.mp4')

Of course you need to take care of running such a task in the background. Libraries such as ​GearmanClient facilitate this.

Note: ​ffmpeg-php is an extension that is not developed since 2007 (and requires "ffmpeg-0.4.9_pre1 or higher"), which means that you are restricted to use a very old version of ffmpeg, without possibility to update it to the latest version. Since a lot of changes/improvements are being made, inside ffmpeg's code, every day, it makes ffmpeg-php incompatible with the latest ffmpeg.

Read the official documentation for more info.

like image 199
Bud Damyanov Avatar answered Nov 19 '22 01:11

Bud Damyanov


I covered the solution that helps most people that I spoke to about this in another thread.

https://stackoverflow.com/a/38626752/2074077

Essentially, your user needs access to the public directories.

<?php 
   exec('whoami'); // Gives you the running user; often it's www-data
?>

Then change your public ownership to the whoami user.

sudo chown -R www-data:root /var/www
like image 23
Kalob Taulien Avatar answered Nov 19 '22 02:11

Kalob Taulien


This happened to me, I found this on another forum; the trick inside of PHP is to give the absolute path to FFMPEG. Try running it like this..

exec("/root/bin/ffmpeg -i input.avi -ab 56 -ar 44100 -b 200 -r 15 -s 320x240 -f flv output.flv",$output, $returnvalue);

Something about the fact that php is a different user than you are when typing straight into the command line. I guess it doesn't have the same shortcut list or whatever it is.

Not sure exactly why but it worked for me!

Good luck.

like image 2
B Rad C Avatar answered Nov 19 '22 01:11

B Rad C