Do you want to add a logo or and overlay to a video file? This article describes how you can do this using FFmpeg.
How it works
In this example we’re using a PNG file for the logo (can also be a video). You can also work here with transparency (in my case a transparent background). For the “merging” process we can use the FFmpeg filter called “overlay“.
Overlay one video on top of another.
It takes two inputs and has one output. The first input is the “main” video on which the second input is overlaid.
Sounds easy, right?
FFmpeg is easy to use: The first input is our video file, the second one the logo. At the end we declare a output file name.
./ffmpeg -i video.mp4 -i logo.png output-video.mp4
Adding the overlay filter
Now we need to add the overlay filter for the merging process:
./ffmpeg -i video.mp4 -i logo.png -filter_complex "overlay=x=10:y=10" output-video.mp4
The parameter “filter_complex” allows us to use filter with multiple input or outputs. As value we define the x and y position for the overlay (here an offset of 10 pixel from the top left corner).
Positioning the overlay
The logo in the example above has the position in the top left corner with an additional offset of 10 pixel from the x and y position. We can use here also a formula for calculating the position. The variables main_w, main_h, overlay_w and overlay_h helps us here.
If we want to position the logo on the top right position we need to calculate the new offset.
Here we use the width of the video (main_w; 1920 pixel on a full HD video) reducing by the logo size (overlay_w; 100 pixel of the logo width) and add an additional offset of 10 pixel.
Hi, thanks for this! works great. I also found you can specify the duration for the logo to appear using (set to 10s in this example):
ffmpeg -i input.mp4 -i logo.png -filter_complex “overlay=10:10:enable=’between(t,0,10)'” -c:a copy output.mp4
However I have a 10min video and I only want the first 10 sec of the logo to encode. Using the code above ffmpeg will encode the whole thing (600seconds re encode) which takes way too much time and is rather uneccessary as I just want to add the logo at the begining, nothing more. I want same video quality, container and same codecs.
Would appreciate if you have an answer for this!
The best way is still to re-encode the whole video.
The only alternative is to encode the first 10 seconds with the logo. Then create a second file with the rest of the video (using the codec copy option to not re-encode this part).
With the “concat” command you can combine now both videos (see https://trac.ffmpeg.org/wiki/Concatenate for more information).
But: My personal experience is not that great. Some players have then trouble during playback. Also (depending on keyframe settings of the video) it may cause some broken frames between both files.
Another idea: Some container formats (e.g. MP4) support multiple video streams. So maybe you can also have a try with this by adding the logo as a second video stream instead of encoding it directly into the video. But: Not sure what player supports that.
I’m creating long videos where I also wanted an intro in front. With 4K60 and often 1 hour length a 6 sec intro does not justify a whole recompilation. However, the bitstream has to be identical when you use concat. Audio is tricky as the frame-intervals are different. Here is the workflow I scripted in bash as I needed the same bitstream through QuickTime (OSX):
1. extract the audio of the combined video (for use in step 5)
2. split the video into 1st part (6 seconds) and rest – without audio
3. also take the audio separately – 6 sec + rest
4. overlay my intro over the first 6 seconds (I use even alpha thanks to ProRes) and
5. overlay the first 6 seconds intro jingle with the whole video-audio (ffmpeg audio filter)
6. merge the intro and rest of original video together through concat*
7. merge the complete audio (from 5) into video from #6
* note on 6: I found the reason why concat produces problems is the timescale of different encodings even using the same encoder. I used ffprobe to find out the timescale that Quicktime (my encoder on Mac) uses and only adding -video_track_timescale 60k solved it. Now audio is playing and there are no video gaps or hangs.
The whole scripting was time consuming as on my old MBP only QuickTime provides QuickSync speed while changing video properties and timing slightly. I had to make 363 frames and cut off 360 etc. etc… It was still worth it as I have used it on 50+ video by now.
What version of ffmpeg was this for? It doesn’t work on ffmpeg 4.4.x.
It’s working for me with the latest version of FFmpeg. What error do you get?