Adding an Overlay Using FFMPEG With Minimal Re-Encoding
Asked Answered
M

2

12

FFMPEG is really useful for cutting a part of a video, without re-encoding the video.

I know it is also possible to use FFMPEG for adding an Overlay Image to a video, in a certain part of the video (for example from 10secs till 20secs).

My question is: If I do this overlaying of an image, will the whole video get re-encoded because of that? Or just the relevant duration will be encoded?

Also are there any options that I can use to make the re-encoding minimal?
The purpose if of course to keep the quality of the video like the original one..
(I would ask for no re-encoding at all, but I don't see how that might be possible...)

Thank you

Merger answered 9/12, 2015 at 14:0 Comment(8)
Whole video will get re-encoded when filtering.Harbin
Oh.. and no parameter that I can set to improve it even abit? OK I understand.. thank you. BTW If you wrote this below in the answers, I could click Accept on it..Merger
You might be able to split without re-encoding, add an overlay just to the concerned segment and then concatenate everything back. Depeding where your keyframes are you might not be able to cut exactly between 10s and 20s marks. Try video.stackexchange.comHarbin
That's an interesting (and surely will work) idea. Regarding "Depeding where your keyframes are you might not be able to cut exactly between 10s and 20s marks." - Is there a way for me to give FFMPEG a video file, and have it list for me all the points in time that are a new "packet" (or however those several second segments called)? That way I can try to plan cutting exactly when one ends and another one starts..Merger
Yes, you can use ffprobe from the same package to show packets and search for keyframe timestamps ffprobe -show_packets -select_streams v <input>. See also the ffmpeg Seeking wiki, it will help.Harbin
Your knowledge in it is amazing. Really appreciate it (if you could copy+paste your comments here down below to an answer, I would be glad to click Accept)Merger
Possible duplicate of FFmpeg - Overlay one video onto another video?Procephalic
No. My question asks about adding an Overlay Image to a video, and the question you link to is adding a Video Overlay to a video.. Also my question is from 2015, and the different question there is from 2016.. Even if it was a duplicate, the direction is the other way around, no?Merger
P
3

The whole video will get re-encoded if you overlay an image on part of it. One way you could avoid re-encoding the entire thing would be to clip out the portion you wish to overlay and only re-encode that piece (see the -t duration switch and the -ss position switch in the documentation

You will want to maintain the current encoding parameters throughout the process. This is easy to do when splitting as you can use the copy parameter for the codec switch(es) such as -c:a copy -c:v copy

To conceptualize (note that these are not complete commands):

Part1: Beginning of Movie (first 10 seconds which you do not wish to overlay) (obtained with ffmpeg -i SourceFileName -t 10 -c:a copy -c:v copy SourceFileNameP1.mkv where SourceFileName is your video to process. Part2: Part of movie between 10 and 20 seconds that you want to overlay (obtained with ffmpeg -i SourceFileName -ss 10 -t 10 -c:a copy -c:v copy SourceFileNameP2) Part3: End of movie (obtained with `ffmpeg -ss 20 -c:a copy -c:v copy)

Bonus tip: you can get slower but more exact cutting by moving the `-ss parameter to before the output file. This will drop frames from the output rather than attempting to seek to the correct position on the input prior to creating output.

If you don't know the encoding details of the source file, you can obtain them with ffprobe SourceFileName or my favorite mediainfo SourceFileName

I'm recommending using a Matroska container for at least the intermediate output due to it's flexibility and low overhead.

Here's a script you can use (on Debian based systems) to obtain the necessary parameters to match.

#!/bin/bash
#mknfo.sh
#Written by Elder Geek for the Stack Exchange network
# 1/1/2018 
####################################################################################################
#bash script to create an nfo file which includes information to help joining video clips          #
####################################################################################################
# This function will create an nfo file including the tech specs for a specified media file        #
####################################################################################################
function shortinfo {
   echo $@
      mediainfo --Inform="General;Duration=%Duration/String2%\nFile size=%FileSize/String1%\nBit Rate=%OverallBitRate/String% " "$@"
   echo -n "Video: "
   mediainfo --Inform="Video;FrameRate=%FrameRate/String% BitRate=%BitRate/String% Resolution=%Width%x%Height% Codec=%CodecID%" "$@";
    echo -n "Audio: "
   mediainfo --Inform="Audio;Mode=%BitRate_Mode/String% BitRate=%BitRate/String% Format=%Format%" "$@";
   echo "-----------------------------------------------------------------------------"
}
####################################################################################################
# This function will check for the existence of mediainfo and attempt installation if not found     #
####################################################################################################
function getmi {
   echo "mediainfo is required and not found. Attempt install Y/N"
   read -n 1 solve
    if [ $solve=={Yy} ]
    then sudo apt-get -y install mediainfo
    else echo "Cannot continue"
    exit 1
    fi
}
####################################################################################################
# Main program                                             #
####################################################################################################
if [ $# -ne 1 ] 
    then    
    echo Error 
    echo "$0" requires a single filename argument. Example: "$0" Videofile
    exit 2
fi
exist=$(which mediainfo)
    if [ "$exist" == "" ];
    then getmi
    fi
target=$(pwd)"/"$1".nfo"
    if [ -e $target ] 
    then 
    echo Error: "$1.nfo" already exists
    exit 3
    fi
echo "Creating $target"
        shortinfo "$1" > "$target"
    exit 0


Now you'll want to re-encode the overlay section (Part2) of the video to exactly match the parameters (same audio and video codecs and same bitrate and sample rate as the original of Part1 and Part3 to allow for joining.

Once this is complete you can join all the pieces together.

mkvmerge -o joined.mkv Part1 + Part2Reencoded + Part3

Note that re-encoding always results in some quality loss so the joins between the pieces may show visible defects. This may or may not be noticeable with the distraction caused by the overlay appearing and disappearing at the same time codes.

This may reduce your re-encoding time significantly depending on the length of the material and has the added benefit of only re-encoding that which must be re-encoded.

How to overlay your re-encoded segment is covered here and you can adjust the accepted answer to match your material.

Procephalic answered 4/10, 2017 at 12:44 Comment(0)
R
2

Another way of doing this is with a player:

ffplay -f lavfi "movie=main.mkv[bg];movie=logo.png[fg];[bg][fg]overlay=W-w-10:H-h-10:enable=between'(t,10,20)'[out0];amovie=main.mkv[out1]"

No encoding needed. No quality loss. Instant gratification.

Reckoning answered 24/4, 2019 at 17:57 Comment(2)
If I understand correctly, since you are executing ffplay, this means that the overlay is only dislpayed on the screen, but not somehow embedded to the file.. I want the change in the file too.. (just wished it was possible with minimal re-encoding)Merger
@Merger Correct. It wasn't clear in the question that you needed it to be permanently part of the video, but perhaps this method could be useful for other users with some weird use case.Reckoning

© 2022 - 2024 — McMap. All rights reserved.