Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding an Overlay Using FFMPEG With Minimal Re-Encoding

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

like image 762
spaceman Avatar asked Dec 09 '15 14:12

spaceman


People also ask

What is overlay FFmpeg?

FFmpeg offers the overlay filter as a way to overlay images (or even other videos) onto video streams. To centre overlay/watermark on a video, use this command: ffmpeg -i inputvideo.avi -i watermarklogo.png -filter_complex \ "overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" -codec:a copy output.flv.

Does FFmpeg support MP4?

FFmpeg can input most container formats natively, including MP4, . ts, MOV, AVI, Y4M, MKV, and many others.


2 Answers

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.

like image 95
Elder Geek Avatar answered Oct 14 '22 22:10

Elder Geek


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.

like image 25
llogan Avatar answered Oct 15 '22 00:10

llogan