I'm trying to convert a large (40mb) mov file to mp4 using ffmpeg and php.
But it gives me a 504 time-out error on server. Can i fix this without changing set_time_limit ?
Here is my php code.
shell_exec($this->getFFmpegPath() . ' -i ' . $path . ' -vcodec libx264 -pix_fmt yuv420p -profile:v baseline -preset slower -crf 18 -vf "scale=trunc(in_w/2)*2:trunc(in_h/2)*2" ' . $convertedPath . '.mp4');
So, any ideas on how to convert this without a timeout ? Any help will be much appreciated.
You might want to run the converting in the background. I found this question that addresses that, but please do some more investigate on that subject. You can then allow the user to refresh to see whether the process is finished.
It might give a better user experience as well (better then looking at a page loading for a long time. There are many places in the connection that may decide to consider it a timeout: php engine, webserver, proxy, browser, depending on the infra.
Also you should be REALLY careful with shell_exec. The chances of somebody on the web misusing it to do whatever they want with your machine are quite high. Maybe not in the way you are using it today (depending on where $path and $convertedPath come from), but maybe in a future update of this code where you allow the user to specify the resulting filename for example.
When I try to upload videos captured from my iPhone in my app, the server performs a conversion from .mov to .mp4 so that it can be played in other platforms. However the problem is that when I shoot the video (in portrait orientation) and it is converted (using ffmpeg) and then played back from the server, it appears to be rotated. Any idea?
FFMPEG changed the default behavior to auto rotate video sources with rotation metadata in 2015. This was released as v2.7.
If your ffmpeg version is v2.7 or newer, but your rotation metadata isn't respected, the problem is likely that you are using custom rotation based on metadata. This will cause the same logic to be applied twice, changing or cancelling out the rotation.
In addition to removing your custom rotation (recommended), there's an option to turn off auto rotation with -noautorotate.
ffmpeg -noautorotate -i input.mp4...
This will also work in some older releases.
For sake of completeness, the reason this is happening is that iPhones only actually capture video in one fixed orientation. The measured orientation is then recorded in Apple-specific metadata.
The effect is that Quicktime Player reads the metadata and rotates the video to the correct orientation during playback, but other software (e.g., VLC) does not and shows it as oriented in the actual codec data.
This is why rotate=90 (or vflip, or transpose, or etc.) will work for some people, but not others. Depending on how the camera is held during recording, the rotation necessary could be 90, 180, or even 270 degrees. Without reading the metadata, you're just guessing at how much rotation is necessary and the change that fixes one video will fail for another.
What you can also do is remove the QuickTime specific metadata when rotate the .mov.
This will make sure that the video is rotated the same way in VLC and QuickTime
ffmpeg -i in.mov -vf "transpose=1" -metadata:s:v:0 rotate=0 out.mov
Here's the documentation on the -metadata option (from http://ffmpeg.org/ffmpeg.html):
-metadata[:metadata_specifier] key=value (output,per-metadata)
Set a metadata key/value pair.
An optional metadata_specifier may be given to set metadata on streams or chapters. See -map_metadata documentation for details.
This option overrides metadata set with -map_metadata. It is also possible to delete metadata by using an empty value.
For example, for setting the title in the output file:
ffmpeg -i in.avi -metadata title="my title" out.flv
To set the language of the first audio stream:
ffmpeg -i INPUT -metadata:s:a:1 language=eng OUTPUT
Depending on which version of ffmpeg you have and how it's compiled, one of the following should work...
ffmpeg -vf "transpose=1" -i input.mov output.mp4
...or...
ffmpeg -vfilters "rotate=90" -i input.mov output.mp4
Use the vflip filter
ffmpeg -i input.mov -vf "vflip" output.mp4
Rotate did not work for me and transpose=1 was rotating 90 degrees
So - I too ran into this issue, and here my $0.02 on it:
1.) some videos DO have Orientation/Rotation metadata, some don't:
MTS (sony AVHCD) or the AVIs I have - DO NOT have an orientation tag.
MOVs and MP4s (ipad/iphone or samsung galaxy note2) DO HAVE it.
you can check the setting via 'exiftool -Rotation file'.
My videos often have 90 or 180 as the rotation.
2.) ffmpeg - regardless of the man-page with the metadata-tag, just doesn't EVER seem to set it in the output file. - the rotation-tag is ALWAYS '0'.
it correctly reports it in the output - but it's never set right to be reported by exiftool. - But hey - at least it's there and always 0.
3.) rotation angles:
if you want rotate +/- 90: transpose=1 for clockwise 90, 2 ccw
now if you need 180 degree - just add this filter TWICE.
remember - it's a filter-chain you specify. :-) - see further down.
4.) rotate then scale:
this is tricky - because you quickly get into MP4 output format violations.
Let's say you have a 1920x1080 MOV.
rotate by 90 gives 1080x1920
then we rescale to -1:720 -> 1080*(720/1920) = 405 horiz
And 405 horizontal is NOT divisable by 2 - ERROR. fix this manually.
FIXING THIS automatically - requires a bit of shell-script work.
5.) scale then rotate:
you could do it this way - but then you end up with 720x1280. yuck.
But the filter-example here would be:
"-vf yadif=1,scale=-1:720,transpose=1"
It's just not what I want - but could work quite OK.
Putting it all together: - NOTE - 'intentionally WRONG Rotation-tag', just to demonstrate - it won't show up AT ALL in the output !
This will take the input - and rotate it by 180 degree, THEN RESCALE IT - resetting the rotation-tag. - typically iphone/ipad2 can create 180deg rotated material.
you just can leave '-metadata Rotation=x' out the line...
/usr/bin/ffmpeg -i input-movie.mov -timestamp 2012-06-23 08:58:10 -map_metadata 0:0 -metadata Rotation=270 -sws_flags lanczos -vcodec libx264 -x264opts me=umh -b 2600k -vf yadif=1,transpose=1,transpose=1,scale=1280:720 -f mp4 -y output-movie.MP4
I have multiple devices - like a settop box, ipad2, note2, and I convert ALL my input-material (regardless whether it's mp4,mov,MTS,AVI) to 720p mp4, and till now ALL the resulting videos play correct (orientation,sound) on every dev.
Hope it helps.
For including into web pages my portrait-format videos from iPhone, I just discovered the following recipe for getting .mp4 files in portrait display.
Step 1: In QuickTime Player, Export your file to 480p (I assume that 720p or 1080p would work as well). You get a .mov file again.
Step 2: Take the new file in QT Player, and export to “iPad, iPhone…”. You get a .m4v file.
Step 3: I’m using Miro Video Converter, but probably any readily-available converter at all will work, to get your .mp4 file.
Works like a (long-winded) charm.
I've filmed the video with Ipad3 and it was oriented upside down, which I suppose is the common situation of all Apple devices at some versions. Besides of it, the 3-minutes long MOV file (1920x1090) took about 500 Mb in size, which made it not available to share easily. I had to convert it to MP4, and analyzing all threads I've found on stackoverflow, here's the final code string for ffmpeg I've used (ffmpeg ver. 2.8.4):
ffmpeg -i IN.MOV -s 960x540 -metadata:s:v rotate="0" -acodec libmp3lame OUT.mp4
I suppose you may just leave '-metadata:s:v rotate="0"' if you don't need the resize and audio codec change. Note that if you resize the video, width and height should fully divide to 4.
Although the topic is old.
Hope this will help some one:
Get ffmpeg latest version : https://www.ffmpeg.org/download.html
The command that worked for me (to flip 180 degrees):
ffmpeg -noautorotate -i input.mp4 -filter:v "rotate=PI" output.mp4
When the degrees are determined by -filter:v "PI/180*degrees"
for example
-filter:v "45*PI/180" for 45 degrees
A nice explanation is here
https://superuser.com/questions/578321/how-to-rotate-a-video-180-with-ffmpeg
Or... to simply change the tag in an existing file:
Read the current rotation
exiftool -Rotation <file>
then, for example:
exiftool -Rotation=180 <file>
to set it to 180
I am using php ffmpeg in a laravel project, to do multiple things probe, extract frame and encode. I am having an issue when creating a frame from the uploaded video file.
This is how the frame is created:
$video = $ffmpeg->open($destinationPath.'/'.$filename);
$video
->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(10))
->save(public_path().$frame_path);
This is sometimes working and creates the frame but other times is not. I noticed that this bug comes up when I am trying to open a .mov file.
It's possible that your version of ffmpeg does not support the codec that is used in the source video file, and hence it is not able to decompress the video and extract an image.
You could try processing the file from the command line to see if you can extract an image that way, and ffmpeg may give you some more information on the problem.
An example command line to extract a png frame from a video file
ffmpeg -y -ss 30 -i [source_file] -vframes 1 [target_file]
Add -f image2 as an output option if your output name is a variable.
The PHP-FFMpeg library appends the -ss argument by default before the input file which requires the timestamp to be accurate in order to obtain the frame. I encountered this problem in case of mkv file. Files such as mkv and mov can not be accurately seeked.
https://github.com/PHP-FFMpeg/PHP-FFMpeg/blob/master/src/FFMpeg/Media/Frame.php#L79
You need to pass true as the second argument to the save function in order to give a Frame closest to the given point. It changes the position of -ss argument in ffmpeg command.
-ss position (input/output)
When used as an input option (before -i), seeks in this input file to position. Note that in most formats it is
not possible to seek exactly, so ffmpeg will seek to the closest seek
point before position. When transcoding and -accurate_seek is enabled
(the default), this extra segment between the seek point and position
will be decoded and discarded. When doing stream copy or when
-noaccurate_seek is used, it will be preserved.
When used as an output option (before an output filename), decodes but
discards input until the timestamps reach position.
position must be a time duration specification, see (ffmpeg-utils)the
Time duration section in the ffmpeg-utils(1) manual.
Here is the code I've been using with PHP:
https://totaldev.com/extract-image-frame-video-php-ffmpeg/
<?php
// Full path to ffmpeg (make sure this binary has execute permission for PHP)
$ffmpeg = "/full/path/to/ffmpeg";
// Full path to the video file
$videoFile = "/full/path/to/video.mp4";
// Full path to output image file (make sure the containing folder has write permissions!)
$imgOut = "/full/path/to/frame.jpg";
// Number of seconds into the video to extract the frame
$second = 0;
// Setup the command to get the frame image
$cmd = $ffmpeg." -i \"".$videoFile."\" -an -ss ".$second.".001 -y -f mjpeg \"".$imgOut."\" 2>&1";
// Get any feedback from the command
$feedback = `$cmd`;
// Use $imgOut (the extracted frame) however you need to
// ...
My environment is: MacOSX 10.8.3, PHP 5.3.17, ImageMagick 6.8.0, Apache 2.2.22
I have installed ImageMagick and PHP-Imagick module by using macports.
ImageMagick works as expected, for example I can convert a JPG to GIF by using the console command convert /my-path/file.jpg file.gif.
However when I create a new Imagick instance by using a sample code as follow:
<?php
$m = new Imagick('/my-path/file.jpg');
I get the exception:
NoDecodeDelegateForThisImageFormat `/my-path/file.jpg' #
error/constitute.c/ReadImage/550
The format of the file doesnt change the result; I tested different JPG, GIF and PNG images however same exception occurs.
So I suspect, the PHP/Apache - ImageMagick integration part is somewhat faulty.
I saw this post on SO and applied the given resolution (adding the environment variable "MAGICKCODERMODULE_PATH" with the value "/opt/local/lib/ImageMagick-6.8.0/modules-Q16/coders") however that didn't make sense for my case. (I confirmed the existence of this environment variable from my phpinfo)
Outputs of some commands on my system:
identify -list format: http://pastebin.com/tiE7Jr1m
identify -list configure: http://pastebin.com/Zt8yiRhj
I will appreciate any suggestion.
Solution
chmod 755 /opt
Insight and Thoughts
At last. I managed to solve the problem.
As there were no answers and suggestions on SO; I'm not suprised that something not expected was causing it!..
#sathia suggested to define an environment variable to call ImageMagick binaries. However in my case, I need to use phpImagick extension and access ImageMagick through its API, so this suggestion didn't make sense.
But I wanted to give it a try and call ImageMagick's convert binary by using PHP's system function. After calling it, I got a return value of "126"; and 126 means, binary is found however it's not executable!..
I checked the binary in /opt/local/bin/convert and it has appropriate execute permissions, then I checked /opt/local/bin and /opt/local directories as well and they were executable too. However the catch was /opt folder's permission was 700!
I managed to execute chmod 755 /opt and magically error has gone.
I've been there too, this is how I solved it:
<?php
define("IMAGE_MAGICK_PATH","/usr/local/bin/");
$in = '/my-path/file.jpg';
$out = '/my-path/file.gif';
$convertString = IMAGE_MAGICK_PATH." convert ".$yourfile." ".$out;
exec($convertString);
hope it helps
i am trying to use the code bellow to merge an audio file at specific time (6th second of my input video) and create a new video autput file but i cant make it work.
<?php
exec("/usr/local/bin/ffmpeg -sameq -i /home/xxx/public_html/xxx/video/full.mp4 -itsoffet 6 -i /home/xxx/public_html/xxx/sounds/names/george.mp3 /home/xxx/public_html/xxx/upload/sample.mpg");
?>
Thank you a lot!
Firstly, you have a typo in your command: -itsoffet should be -itsoffset.
Secondly, it seems there's a bug affecting -itsoffset.
Take a look at these identical/similar questions:
Add audio (with an offset) to video with FFMPEG
delay audio with ffmpeg
Add multiple audio files to video at specific points using FFMPEG