FFmpeg - How to scale a video then apply a watermark? - filter

Im trying to scale a video so that it is always 512 wide where the height changes in proportion to the original video.
Once scaled, I then want to apply a watermark/overlay to the video, therefore the video will scale but the watermark wont.
I am able to achieve each of these separately using the following filters:
Scale
-vf "scale=512:-1"
Watermark
-vf "movie=watermark.png [watermark]; [in][watermark] overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2 [out]"
They work successfully on their own.
However when trying to combine the two, Im having a bit of trouble.
Having both as parameters of course does not work as one will override the other.
Ive tried:
-vf "scale=512:-1,movie=watermark.png [watermark]; [in][watermark] overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2 [out]"
my thinking was that the scale would be applied first then the watermark but all I get is an error
Too many inputs specified for the "movie" filter.
Error opening filters!
Then changing the , to a ; resulted in:
Simple filtergraph 'scale=512:-1;
movie=watermark.png
[watermark]; [in][watermark]
overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2 [out]' does not have
exactly one input and output.
Error opening filters!
I presume I need to do something more with filterchains but Im struggling to figure it out.
Any ideas anyone?
Many thanks in advance.

You can use the -filter_complex option with the scale and overlay filters:
ffmpeg -i input.mp4 -i logo.png -filter_complex "[0:v]scale=512:-1[bg];[bg][1:v]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" output
See scale and overlay filter documentation for more info.
No need for the movie source filter as in the other examples.
You can add -c:a copy if you want to stream copy (re-mux) the original audio instead of re-encoding it. This is useful if your input and output container formats are the same.
The example will place the logo in the center. For other placement options:
Upper left with 10 px padding: overlay=10:10
Upper right with 10 px padding: overlay=W-w-10:10
Lower right with 10 px padding: overlay=W-w-10:H-h-10
Lower left with 10 px padding: overlay=H-h-10:10

Thank you to both #DiJuMx and #LordNeckbeard, you both got me closer to my solution. Ive not tried the filter_complex option yet but it certainly looks simpler.
The solution I found to work is:
-vf "movie=watermark.png [watermark]; [in]scale=512:trunc(ow/a/2)*2 [scale]; [scale][watermark] overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2 [out]"
Note that Ive replaced the -1 in the scale as that had the potential to cause an uneven number of pixels in the height of the video when scaling which would then cause encoding errors.

From what I understand, this might work:
-vf "movie=watermark.png [watermark]; [in] scale=512:-1,[watermark] overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2 [out]"
You apply the scale filter to the input "[in]".
Unfortunately I don't have much experience with the filters on ffmpeg so I can't help further. Sorry

Related

Adding an image in the padding area of the video instead of black color using FFMPEG

I have some videos of resolution 1280 X 720 with black padding area in both left and right side around the display area of all videos. I want to display a static image in padding area of video instead of solid black color. I am working with FFMPEG library but can't find any way to do so. Can you please help me regarding this?
Thank You!
Use the cropdetect filter to determine crop parameters to remove the black. See Remove black bars using ffmpeg for an example of how to get the crop parameters.
Crop the black area and overlay the video over the image:
ffmpeg -i video.mp4 -i background.jpg -filter_complex "[0]crop=404:720:438:0[vid];[1][vid]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" -c:a copy output.mp4
Well, after trying some commands I made a command to do so and its working for me.
ffmpeg -loop 1 -i image.jpg -i video.mp4 -filter_complex "[1:v]scale=1280:720:force_original_aspect_ratio=decrease:-1[fg];[0:v][fg]overlay=(W-w)/2:(H-h)/2:shortest=1" output.mp4

My filters seem to be applied in wrong order

I'm using ffmpeg to join frames into a video with some parameters.
Here is a sample of the commands I run :
"ffmpeg -y -r 24 -f image2 -i "C:\Users\Pictures\me\frame%04d.bmp" -filter_complex "[0:v]select=between(n,0,76)[selected];[selected]crop=in_w:in_h-60-60:0:60[cropped];[cropped]scale=w=2ceil(2048.0/20.5):h=2ceil(858.0 /20.5) " -c:v libx264 -q:v 1 -b:v 2M "C:\Users\me\Video\output.mp4""
When I run this command I have calculated the size of my cropping on the frames to remove black rectangles at the top and bottom of the frame (I tried using cropdetect but it doesn't fit my usecase so I'm using another soft).So my first that was that ffmpeg would crop on the input stream so it would only crop my black rectangles. But when I change my scale it crops a part of the image.
So my understanding is that ffmpeg crops after scaling (maybe I'm wrong) and if I get the crop parameters on the input images it is sure the they will be wrong if I apply them on the scaled video.
I tried using ";" and "," to separate my filters. I tried naming and not naming my streams between filters. Nothing seems to solve my issue.
What could I do to fix that or am I understanding the issue incorrectely?
Thanks in advance
So actually I didn't understand the problem correctly. The filters are indeed applied in the correct order but it seems like "scale" crops my video again so I'm losing the bottom of my images.
I'm gonna investigate that.

ffmpeg scale down video dynamically (squeeze-back) or zoompan out to smaller than original

I have 2 videos, I'm trying to overlay one on top of the other, and have it shrink down in an animated fashion until it appears like a picture-in-picture setup. Then, after a few seconds it should scale back up.
This is what I am trying to achieve (these would be videos, not images):
This is the closest I've been able to get, but, crucially, zoompanning "out" (as opposed to "in") does not appear to work; so, of course, this does not work:
ffmpeg -i bg.mov -i top.mov -filter_complex "[0:v]zoompan=z='pzoom-0.1':d=1, setpts=PTS-STARTPTS[top]; [1:v]setpts=PTS-STARTPTS+2/TB, scale=1920x1080, format=yuva420p,colorchannelmixer=aa=1.0[bottom]; [top][bottom]overlay=shortest=0" -vcodec libx264 out.mp4
Is this achievable with ffmpeg?
Use the scale filter with animation, available since v4.3.
Here's something to get you started. This will expand the top layer from 480 px height to 1080 height in 2 seconds and then back to 480 px in 2 seconds.
ffmpeg -i bg.mov -i top.mov -filter_complex "[0:v]scale=1920x1080,setpts=PTS-STARTPTS[bg]; [1:v]setpts=PTS-STARTPTS+2/TB, scale=-1:'480+600*abs(sin((t-2)*2*PI/8))':eval=frame[top]; [bg][top]overlay" -vcodec libx264 out.mp4

ffmpeg how to crop and scale at the same time?

I'm trying to convert a video with black bars, to one without and if the source is 4k, I want the video to be converted to 1080p
Now to do this, I'm using the following command:*
ffmpeg -i input ... -filter:v "crop=..." -filter:V "scale=1920:-1" ouput
But running this, I found that the end product still has said black bars and is 1920x1080 as opposed to the 1920x800 I'd expect.
What gives, why does this not work?
*: Other settings have been left out for convenience.
I got it to work by putting both the crop and the scale in the same -vf tag. I was cropping and then increasing the size of an old video game, and I just did this:
-vf crop=256:192:2:16,scale=-2:1080:flags=neighbor
I knew it worked as soon as I saw it display the output file size as 1440x1080 (4:3 ratio at 1080p).

how to mirror + add logo to video?

how to mirror + add logo to video?
How to mirror video, then add logo to video using ffmpeg?
To flip a video horizontally, you can use -vf hflip (or vflip for vertical flipping).
To add a watermark of any image to a video is more complex, especially if you want to position it:
-i logo.png -filter_complex "overlay=x=(main_w-overlay_w)/2:y=(main_h-overlay_h)/2"
There are a lot of things you can do with the overlay filter, check the documentation. It gets extremely complex if you also want to scale the overlay, so make sure your logo file is the right size before that.
However, you cannot mix -vf and -filter_complex, so the flipping has to become part of the complex filter. So, for your desired result, you'd have to do this (assuming you want the logo to be at position 10/10):
ffmpeg -i input.mp4 -i logo.png -filter_complex "hflip[flipped];[flipped]overlay=x=10:y=10" out.mp4

Resources