I'm trying to dynamically change the resolution of videos uploaded to a server via PHP, using FFmpeg. IE, I want to preserve portrait or landscape orientation - if Y is higher than X, I want to change Y to 320 and X to a corresponding value, and vice versa. I'm not having trouble with the resizing itself - it's quite straightforward, actually. What I'm having trouble with is detecting which dimension is larger.
I grabbed this solution off StackOverflow: how to check if video is landscape or portrait using ffmpeg php?
However, it doesn't appear to be working. While I track down what isn't working - I'm assuming the way the output is formatted has changed since that solution was posted, and it now needs to be parsed differently - I wanted to ask if there was a better way to do this. I'm open to using FFmpeg or a PHP-based solution.
ffmpeg -i input.jpg -vf 'scale=320:320:force_original_aspect_ratio=decrease' output.png
According to FFmpeg documentation, the force_original_aspect_ratio option is useful to keep the original aspect ratio when scaling:
force_original_aspect_ratio
Enable decreasing or increasing output video width or height if
necessary to keep the original aspect ratio. Possible values:
disable
Scale the video as specified and disable this feature.
decrease
The output video dimensions will automatically be decreased if
needed.
increase
The output video dimensions will automatically be increased if
needed.
Use decrease to make the largest dimension to 320, or use increase to make the smallest dimension to 320.
Have a look at the resizing page on the FFmpeg wiki. You basically want to look specifically at this section:
Sometimes there is a need to scale the input image in such way it fits
into a specified rectangle, i.e. if you have a placeholder (empty
rectangle) in which you want to scale any given image. This is a
little bit tricky, since you need to check the original aspect ratio,
in order to decide which component to specify and to set the other
component to -1 (to keep the aspect ratio). For example, if we would
like to scale our input image into a rectangle with dimensions of
320x240, we could use something like this:
ffmpeg -i input.jpg -vf scale="'if(gt(a,4/3),320,-1)':'if(gt(a,4/3),-1,240)'" output_320x240_boxed.png
You can obviously use this for videos as well as for images.
You can use a if statement to select the larger one
-vf scale='if(gt(iw,ih),320:-2)':'if(gt(iw,ih),-2:320)'
FYI, the correct way to do this is to use FFprobe, which comes with FFmpeg.
https://www.ffmpeg.org/ffprobe.html
Related
I am trying to upload a video that is 640 x 480. Using FFmpeg I am trying to resize to a square but I am having much difficulty.
if i use s=320x320 in my command or scale 320x320
->setVideoScale(320, 320)
the image is distored.
If i change the aspect ratio 1:1 i get black bars.
is there a way to actually just cut a RECT in the video. IE i want to be able to re save the video and it only capture
x 0 to 320
y 0 to 320
or whatever bounds I pick.
Basically I do not want to re-size I just want to be able to re record a certain portion of the video. is this possible?
Check out FFMPEG's video filters. There is a crop option that will do what you're asking for, specifically the first example.
Depending on the library you're using to interface with FFMPEG, something like the following might work per your example:
->addCommand('-vf', 'crop=320:320:0:0');
I have a tool which allows to justify contrast and brightness of image online using CSS3 filters. Thus I got two values of brightness and contrast from 0 to [inf] which means "1" is no change in brightness/contrast.
Next step, I need to apply these changes to image physically using Imagemagick. I've digged a ton of docs but not found how I can apply these 2 values to image.
It is relatively simple way to apply brightness and contrast corrections to image file using command-line Imagemagick?
convert -brightness-contrast 10X10 1.png 2.png
I use imagemagick to create thumbnails from images on my website using convert like so: convert -size 220x220 %s -resize 220 -profile '*' %s", $image, $thumb and this has worked great for a long time. Thousands of images have been processed and all the thumbnails look great ... except for one. For some reason this image produces a very ugly thumbnail and I can't figure out why.
Original image: http://i.imgur.com/fCbAN.jpg
Generated Thumbnail: http://i.imgur.com/MdLCs.jpg
Does anyone have any insight as to why this might happen with my convert code?
The thumbnail has been saved with very low quality (approximately 10-15, 99 being close to lossless). I think the question is, "why did that happen".
I can think of some reasons, but you will have to experiment. I assume the images you posted are the real images (not copies done converting e.g. PNG to JPG, I mean), and the command line is complete and describes the complete image workflow.
your ImageMagick setup attempts to keep estimated image quality. You do not set a quality explicitly (e.g. -quality 75), so the thumbnail gets the same quantizer setting as the source image. Suppose the source has a low quantizer, but you do not see it due to the high-frequency component (the image is "noisy" due to scanning). When resampling, the background loses its noise and becomes a smooth gradient, which was absent in the source. And a smooth gradient is hell on low quantizers. Try explicitly setting a quality factor (40 to 99, 40 is better compressed but chunkier, 99 is very high quality but bigger file).
there is some kind of interference between the resampler and the Moiré pattern that the scanner creates in the acquired image. This is less likely, because I see a "wavelength" of about 8 pixels which isn't at all uncommon, nor do I think that with so many images you acquired, none had approximately the same size and aspect ratio of this one; which in this scenario ought to have triggered the same behaviour. You say it didn't happen, so if this image isn't uncommon for size, aspect ratio, or source (e.g. one of the very few images scanned with a Scan-o-matic 600 scanner in the batch), this scenario becomes pretty unlikely. But if it is correct, then add a Gaussian blur before resizing and it ought to fix things: e.g. -blur 2x2.
there is bad juju in the file name, and for some reason this gets the ImageMagick wrapper to interpret a command of "set quantizer to its crappiest value". REALLY unlikely (if the interpret interprets a part of the filename as an option, it shouldn't interpret it as a filename, and the rest of the filename is no longer the true filename; resulting in a "File not found" error which we don't observe. All the same, if the original file name is something like "--progressive-swedish-music.jpg", try renaming it before thumbnailing.
I'm putting my money on option #1, anyway.
Another test which you could attempt is to run the same command from ImageMagick (command line) and not from PHP.
Ive got a strange task. Specifically i want to check for insane media file sizes for now. If possible, it would be nice if i could take image dimensions into consideration as well. For example, it's acceptable if a large image takes up 80kb, but not for a 20x20 px image.
Going off #BoltClock's comment, you would need to define what makes an image optimized vs non-optimized.
Something like a definition table to go off of in your validation:
Maximum image size = 1MB X 2000px x 2000px
Relative Ratio of size to dimensions of file
The above could be checked easily (without GD for instance) using something like the getimagesize() function.
I want to mimic the bing video preview functionality, with a thumbnail preview, then onMouseOver, load and play a video file. I plan to use VideoJS (html5 + flash) for the video playback. I need to use ffmpeg to produce these video files.
How can I create a mp4 preview with video only, which contains 1s of every other minute of the full clip, and shrink resolution to a fixed width (maintaining aspect ratio, preferably with zoom crop) using php + ffmpeg command line?
I'm assuming it can be done somehow along the lines of cutting 1s clips, then combine the smaller clips, and re-encode for a final rescaled output.
*Edit: Using ffmpeg is a design requirement. Pulling out 1s clips, should be fairly easy, but combining them seems to be somewhat complex with ffmpeg. I don't want cycling thumbnails, I want a video preview which contains a number of 1s clips. Eg. runtime in seconds: 100-101, and 200-201 combined in a heavily compressed clip. I am asking for a command line example of how to do this in an efficient manner.
One way to do this in Windows (or wine) would be to use an Avisynth script. This would allow you to do all your desired transformations in one step. It's been a little while since I've used Avisynth but a very simple script might look like:
DirectShowSource("C:\file\to\encode.avi", audio=false) # Or another source filter
SelectRangeEvery(1440, 24) # outputs 24 frames every 1440 frames
BilinearResize(320,240) # resize to your desired resolution
Crop(...) # crop to reach desired aspect ratio
This could be extended to support various framerates and aspect ratios instead of hardcoding everything. The resulting .avs file can then be used as an input file to ffmpeg, provided that it has been compiled with --enable-avisynth.
I've an approach and i think that will work...
Using ffmpeg you can get thumbnails of the video at specific intervals.
So i will take about 5 to 10 thumbnails in the interval of 2 seconds and store them on my server with a unique name that identifies the video.
So when I mouse over i call the function which will load these images sequentially(which makes the user feel the video is fast forwarding..)
But in this format, we can't play sound when we mouse over ..
I don't know whether this is good but i know this will work..
Update:
I think it will be better to create a video using ffmpeg using the extracted images and play them while we mouse over.. This will be quite faster than loading a sequence of images. ffmpeg can be used to create a new video from a list of images.
I managed to do this now, by pulling out 1s clips, and convert them to mpeg. Then combine these mpeg files, by appending them into a single file. Then convert til mpeg file to mp4