ffmpeg - which video rate is correct? - php

I am using ubuntu 13.04
Version of ffmpeg is ffmpeg version N-61041-g52a2138
Through php, I am calling ffmpeg commands to extract images and do some modification in those images and again merge those images back to video.
While merging all images through ffmpeg command, I need to pass video bit rates.
Command is as below
public function mergeImagesToVideo($frame_no,$user_directory_name,$video_bit_rates,&$output,&$status){
/* merge all of frames to create one second video */
$user_frames_path=$GLOBALS["all_user_dir_path"].$user_directory_name."/";
$command= $GLOBALS['ffmpeg'].' -f image2 -r 30 -i '.
$user_frames_path.'f'.$frame_no.'_%d.png -r 30 -b:v '
.$video_bit_rates.'k '.$user_frames_path.'f'.$frame_no.'.mp4';
//echo $command;
exec($command,$output,$status);
return;
}
The call is made as below
$this->mergeImagesToVideo($start_second,$user_directory,$video_bit_rates,$output,$status);
if($status!=0){
echo "some thing went wrong in merging all images to create a video <br>";
}
Now When check bit rates through ffmpeg command output is like as below
ffmpeg -i f1.mp4
This command shows 7303 kb/s
While I right click the image and show properties, it shows 7295 kbps
Which is the correct one ?? Not getting correct line..
Thanks in advance.

Related

ffmpeg command executes via command line, but not via PHP script

I am working on a simple video upload and compression system and I am currently using the following process.
First Step
I use a multipart/form-data to upload the original video file, which I store in /var/www/site/videos_pre/video.mp4. My public folder is var/www/site/public_html/. I store an entry in my database with the video information.
Second step
I have a converter process which is very basic, but does the job (at least in CLI).
It has the following code:
public function converter($content_id)
{
$content = $this->videos_m->get($content_id);
$id = uniqid();
$name_mp4 = $content->name_slug.'_'.$id.'.mp4';
$name_webm = $content->name_slug.'_'.$id.'.webm';
$command_mp4 = 'ffmpeg -i ../videos_pre/'.$content->original_file.' -b:v 1500k -bufsize 1500k ./videos/'.$name_mp4;
system($command_mp4);
$command_webm = 'ffmpeg -i ./videos/'.$name_mp4.' -c:v vp9 -c:a libvorbis ./videos/'.$name_webm;
system($command_webm);
$update_video = new stdClass();
$update_video->archivo_mp4 = $name_mp4;
$update_video->archivo_webm = $name_webm;
$this->db->where('content_id', $content_id);
$this->db->update('Videos', $update_video);
}
Third step - where the problem occurs
I have tested this on Windows 10 and Ubuntu 18.04. The code works on Windows 10 in both php and cli. The code on Ubuntu only works with cli.
The resulting commands are something like this:
// First command to reduce the bitrate of the mp4
ffmpeg -i /var/www/site/videos_pre/video.mp4 -b:v 1500k -bufsize 1500k /var/www/site/public_html/videos/video_5e757d3e0d762.mp4
// Second command to convert the mp4 to a webm to get both types
ffmpeg -i /var/www/site/public_html/videos/video_5e757d3e0d762.mp4 -c:v vp9 -c:a libvorbis /var/www/site/public_html/videos/video_5e757d3e0d762.webm
If I execute those commands they work perfectly. If I run the php script, be it in the browser or via CLI, literally nothing happens. No error messages nothing.
I am not sure if it's a permission issue, if there's something specific for php to run this, or some module I've not activated. I have enough execution time, I have it at 600 seconds, but as I said it doesn't even take time, it just does nothing.
I can even echo the commands and they appear. So, basically the problem is I need to be able to run those commands from PHP. I did it on Windows, but Ubuntu 18.04 won't let me. Both OSs have ffmpeg recently installed and I've been able to convert on both of them.
I tried changing paths from absolute to relative, no difference at all.
So, I managed to solve it, and it turns out it was a permission problem.
I had my /var/www/site folder with permissions like this: myuser:www-data. After checking this answer on a similar issue, I changed the folder permission to www-data:root and it worked instantly.
I hope that permission change doesn't affect the rest of things, but for now everything's working fine.

PHP-FFMpeg: How to properly concatenate two videos?

THE SITUATION:
I need it to concatenate multiple videos into one single video.
I am using the library PHP-FFMpeg.
But I don't manage to make it working.
THE VIDEOS:
The videos are recordings made with the MediaRecorder Web API.
The video format is: video/webm;codecs=h264
The audio format is opus.
recorder = new MediaRecorder(this.stream, {
mimeType: 'video/webm;codecs=h264'
})
CONCAT USING PHP-FFMPEG (using saveFromSameCodecs):
This is how I try to concat them using saveFromSameCodecs:
(I have checked the paths and are correct)
$video = $ffmpeg->open( $path1 );
$video
->concat([$path1, $path2])
->saveFromSameCodecs($path_output, TRUE);
But it failed with the following error message:
ffmpeg failed to execute command '/usr/local/bin/ffmpeg' '-f' 'concat' '-safe' '0' '-i' '/private/var/folders/dw/919v2nds7s78pz_qhp7z9rcm0000gn/T/ffmpeg-concath1kHiX' '-c' 'copy' '/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/output.mp4'
CONCAT USING FFMPEG COMMAND LINE:
On suggestion on #RolandStarke and #LordNeckbeard I have tried using the ffmpeg command line to get a better insight on what is going on.
If I use the following command line:
ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4
I get the following error, related to the audio opus codec.
If I use the following command line, converting the audio coded to acc:
ffmpeg -f concat -safe 0 -i mylist.txt -c:v copy -c:a aac output.mp4
The final video is properly created, as a concatenation of the other videos.
CONCAT USING PHP-FFMPEG: (using saveFromDifferentCodecs)
It seems the problem is ONLY related to the codec.
So I have tried using saveFromDifferentCodecs:
$format = new FFMpeg\Format\Video\X264('libfdk_aac', 'libx264');
$result = $video1
->concat([$path1, $path2])
->saveFromDifferentCodecs($format, $output_path);
But I still get an error:
ffmpeg failed to execute command '/usr/local/bin/ffmpeg' '-i' '/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/test1.mp4' '-i' '/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/test2.mp4' '-filter_complex' '[0:v:0] [0:a:0] [1:v:0] [1:a:0] concat=n=2:v=1:a=1 [v] [a]' '-map' '[v]' '-map' '[a]' '-b:a' '128k' '/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/output.mp4'
CONCAT USING PHPFFMPEG (but with different videos):
If the problem is only related to the codec, then using two different videos with video codec: h264 and audio codec aac, it should work, but it doesn't:
ffmpeg failed to execute command '/usr/local/bin/ffmpeg' '-f' 'concat' '-safe' '0' '-i' '/private/var/folders/dw/919v2nds7s78pz_qhp7z9rcm0000gn/T/ffmpeg-concatoJGhLt' '-c' 'copy' '/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/output.mp4'
But using the command line it works smoothly: ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4
CONCAT USING shell_exec:
I have tried using shell_exec, with the first two videos (opus codec):
echo shell_exec("/usr/local/bin/ffmpeg -f concat -safe 0 -i /Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/mylist.txt -c:v copy -c:a aac /Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/output.mp4 2>&1");
And it works smoothly.
The final output is created, and with the acc audio codec.
TESTING THE LIBRARY:
To see if php-mpeg was actually working, I test it by making a basic resize of a video and it worked correctly.
RESUME:
Using ffmpeg command lines everything works fine
Using shell_exec everything works fine
Using php-ffmpeg I always get the error ffmpeg failed to execute command
QUESTION:
How can I concat videos using php-ffmpeg?
Is the issue caused by wrong encoding?
Thanks!
When encountering issues with php-ffmpeg the best approach is to copy the command from the error message and paste it in terminal. This will give you a better error message.
In your case the the error is
ffmpeg failed to execute command '/usr/local/bin/ffmpeg' '-f' 'concat' '-safe' '0' '-i' '/private/var/folders/dw/919v2nds7s78pz_qhp7z9rcm0000gn/T/ffmpeg-concath1kHiX' '-c' 'copy' '/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/output.mp4
Debugging this is a bit harder as the temp file /private/var/[...]/ffmpeg-concath1kHiX is deleted when you try to execute the ffmpeg command in the terminal. To test it you can create the temp file yourself like:
$vidoes = [__DIR__ . '/small.mp4', __DIR__ . '/small.mp4'];
file_put_contents('videolist.txt', implode("\n", array_map(function ($path) {
return 'file ' . addslashes($path);
}, $vidoes)));
Now you can run the ffmpeg command in the terminal
ffmpeg -f concat -safe 0 -i videolist.txt -c copy /Users/[...]/videos/output.mp4
#[...]
#File '/Users/[...]/videos/output.mp4' already exists. Overwrite ? [y/N]
#Not overwriting - exiting
So you your case the error is that the output file already existed. The solution is to use an other non-existing output file or delete it before concatenating your videos.
Here an example how to concatenate files (small.mp4 taken from http://techslides.com/sample-webm-ogg-and-mp4-video-files-for-html5)
<?php
require 'vendor/autoload.php';
$ffmpeg = FFMpeg\FFMpeg::create();
$video = $ffmpeg->open(__DIR__ . '/small.mp4');
$video
->concat([__DIR__ . '/small.mp4', __DIR__ . '/small.mp4'])
->saveFromSameCodecs(__DIR__ . '/out-'. time() . '.mp4', true);
The correct answer is the one from #RolandStarke.
Here I just want to put together a list of suggestions that may be useful to debug other similar problems in dealing with ffmpeg:
Make a reinstall of ffmpeg. It may be a missing option or a missing codec. Here is how to install (for mac), including all possible options (september 2018). It took me 30minutes so be patient.
brew install ffmpeg --with-chromaprint --with-fdk-aac --with-fontconfig --with-freetype --with-frei0r --with-game-music-emu --with-libass --with-libbluray --with-libbs2b --with-libcaca --with-libgsm --with-libmodplug --with-librsvg --with-libsoxr --with-libssh --with-libvidstab --with-libvorbis --with-libvpx --with-opencore-amr --with-openh264 --with-openjpeg --with-openssl --with-opus --with-rtmpdump --with-rubberband --with-sdl2 --with-snappy --with-speex --with-srt --with-tesseract --with-theora --with-tools --with-two-lame --with-wavpack --with-webp --with-x265 --with-xz --with-zeromqlibzeromq --with-zimg
To have the updated options list you can run: brew options ffmpeg or just google it.
Try to do the same thing you are trying to do, but using the ffmpeg command line only. It will more insight and a better error reporting. For example for concat:
ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4
Check that PHP-FFMpeg is properly working. Concat it's a bit more difficult operation. You can try with a simpler one and see if it's working and if the library is properly installed. For example you can try a simple conversion:
FFMpeg::fromDisk('local')
->open('public/videos/test.mp4')
->export()
->toDisk('local')
->inFormat(new FFMpeg\Format\Video\X264('libmp3lame', 'libx264'))
->save('public/videos/converted_test.mp4');
Double check every path. And in the case of concat, make sure the output file doesn't already exists.
It may be an encoding problem. Try other types of files with different codecs to see if that's actually the issue. In case you can convert beforehand to the proper codec.
Add line breaks in the source code. In my case I was getting the generic error: Unable to save concatenated video. Here is the source code:
try {
$this->driver->command($commands);
} catch (ExecutionFailureException $e) {
$this->cleanupTemporaryFile($outputPathfile);
$this->cleanupTemporaryFile($sourcesFile);
throw new RuntimeException('Unable to save concatenated video', $e->getCode(), $e);
}
But if I dump the execution and then die it, right before that block:
dd($this->driver->command($commands));
It was giving me a more detailed error message.
You can also dump the commands array: dd($commands);
Finally here is a list of similar issue with PHP-FFMpeg that you can check to see if the solution has already been given: https://github.com/pascalbaljetmedia/laravel-ffmpeg/wiki/FFmpeg-failed-to-execute-command
If you have other suggestions feel free to comment or edit the answer.

PHP and FFMPEG advice/solution for a unknown issue

I am having a live video streaming website and I allow people to upload all the video files to the site till now everything is ok.
What I am doing is that I am using FFMPEG to convert the video to mp4 and also get a image out of the video after 20 seconds.
The code that I am using is that:
require 'vendor/autoload.php';
$getEXT_check=substr(#$_FILES['profileimage99']['name'],-3);
if($getEXT_check !='mp4' && $getEXT_check !='MP4'){
exec('ffmpeg -i '.$uploadfile.' -f mp4 -s 896x504 '.$new_flv.''); }
//execute ffmpeg and create thumb
exec('ffmpeg -i '.$uploadfile.' -ss 00:00:20 -vframes 1 '.$new_image_path);
$theduration=exec('ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 '.$uploadfile.' 2>&1');
$theduration_val=round($theduration/60, 2);
What issue I am having is that
sometimes the code dosent extract the image out of video
video conversation takes very long time for non mp4 video (I am not converting mp4 videos)
Some info what I have done on server. During the development of site I installed ffmpeg on my pc and downloaded the vendor directory by composer.json file. But I have not done these things on my server I have a dedicated server from bluehost and have ffmpeg installed at this location.
/usr/local/bin/ffmpeg
/usr/local/bin/mplayer
/usr/local/bin/mencoder
/usr/bin/flvtool2
/usr/local/bin/MP4Box
/usr/local/bin/yamdi
During uploading the site what I did is that I also uploaded the vendor directory and all the files and made the site live. I haven't used any of the path as given by my server admin after asking.
Please suggest me something where I am doing wrong.

Codeigniter - exec ffmpeg (win 8.1 with xampp)

i want to merge some image files (jpeg,png) to a short stop motion video clip.
The User can upload the images and the webapp will do a short movie... Thats the plan.
I have tried some variations i found in www -> exec, shell_exec
The ffmpeg.exe is in my root Folder (xampp/htdocs/xxx/ffmpeg.exe)
I put a function in my controller to do the clip.
public function render() {
// Save the Session ID into the variable sessionId
$sessionId = $this->session->userdata('session_id');
// Path to the Userimage-Folder
$image_path = "C:\xampp\htdocs\xxx\uploads\$sessionId";
$command = "C:\xampp\htdocs\xxx\ffmpeg -framerate 1/5 -i".$image_path."/img_%03d.JPG -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4";
exec($command);
}
The images are already in the same format and have a consecutive numbering.
I'am still a beginner, so please help me.
regards :)

FFMPEG command doesn't work in PHP. (Incompatibilty with MAMP)

I'm a bit of a beginner when it comes to PHP, and I'm trying to create a simple(ish) system where files are input, and then converted to html5 video in various resolutions.
I've sorted out how to handle multiple file uploads etc, but now I'm having a problem.
I can't seem to get exec to execute FFMPEG in PHP.
For example, if I type this into my command line (Terminal on Mac OSX 10.8), It converts the video correctly:
ffmpeg -i /Users/charlieryan/Desktop/MOV01785.MPG websample.mov
This correctly outputs the converted video file into my home directory.
However if I run this in PHP as follows:
exec('ffmpeg -i /Users/charlieryan/Desktop/MOV01785.MPG websample.mov');
Absolutely nothing happens ... my stat monitor doesn't register any change in processor use, and I can't find the output file anywhere on my system.
Since I'm a bit of a noob at this, I'm assuming I'm doing something wrong, but what is it?
Thanks,
Charlie
After alot of help from birgire and a lot of fiddling around I've sorted it.
This problem comes from an incompatibility with the MAMP sandbox. Which can be solved as follows:
Go to Terminal and type:
sudo nano /Applications/MAMP/Library/bin/envvars
Then comment out the following lines with a hash (#)
# DYLD_LIBRARY_PATH="/Applications/MAMP/Library/lib:$DYLD_LIBRARY_PATH"
# export DYLD_LIBRARY_PATH
And then add the following line to the file
export PATH="$PATH:/opt/local/bin"
Then, go back to MAMP and restart your servers, navigate back to the page, and you'll be good to go.
You should first try to see if exec() is allowed:
<?php echo exec('echo "exec() is working"');?>
if it's working you should get
exec() is working
If it works you should try
exec('/full/path/to/ffmpeg -i /Users/charlieryan/Desktop/MOV01785.MPG websample.mov');
I had the same problem, If you use MAMP, the problem is because mamp's php can't find the correct library, I don't know why!, so.. here's the trick.
- You should use system's php to execute the php which will call to ffmpeg
In your php code (ex: lib.php | index.php):
function callToSysPHP ($videoName) {
// $cmd = '/path to php/php <your php script> args';
// In my case
$cmd = '/usr/bin/php myffmpeg.php ' . $videoName;
shell_exec($cmd);
}
In myffmpeg.php:
$videoName = $argv[1];
//$cmd = 'path to your ffmpeg/your ffmpeg command';
// In my case my ffmpeg cmd looks like
$cmd = '/usr/sbin/' . 'ffmpeg -f image2 -framerate 25 -i ./files/pngs/%1d.png -vf scale=480:640 -vcodec libx264 -refs 16 -preset ultrafast ./files/pngs/'. $videoName .'.mp4 2>&1';
echo '<pre>'; print_r(shell_exec($cmd)); echo '</pre>';
Basically from your mamp php, call a system php to execute a php file wich calls a ffmpeg throught shell_exec();
I hope this can help you.
have you ffmpeg installed on windows machine? what happens if you run the same command from command line without php, does it work? If it doesn't, it hasn't to do anything with PHP.
If '/usr/local/bin/' is the directory where you can find the ffmepg executable try this one:
<?php
$cmd = 'PATH="/usr/local/bin/"; ffmpeg -i /your/file/destination/batman.mp4 2>&1';
echo "<pre>".shell_exec($cmd)."</pre>";
?>

Categories