To add a green video overlay that appears every minute using FFmpeg, you must use the
overlay filter within a
filter_complex graph. This approach allows precise control over the timing and positioning of the overlay by calculating the start time for each interval based on the main video's duration.
Understanding the Overlay Filter
The core challenge in periodic overlays is telling FFmpeg exactly when to show and hide the second video stream. Unlike simple concatenation, where you join clips end-to-end, an overlay sits on top of another video layer. The
overlay filter takes two inputs: the main background video (input 0) and the overlay video (input 1). To make it appear periodically, you cannot simply loop the overlay indefinitely without masking it out during specific times. Instead, you define the active windows for the overlay using expressions or by splitting the timeline.
A common misconception is that setting
-stream_loop -1 on the overlay input will automatically handle the repetition correctly within the filter graph. As noted in previous troubleshooting guides,
-stream_loop affects the demuxer level, not the filter complex duration handling directly. If you loop the source file externally, you risk memory issues or sync errors if the main video length does not perfectly divide by the loop count. It is safer to generate the overlay pattern dynamically or use a single short clip and reference it with precise timing offsets.
Constructing the Filter Graph
You need to build a
filter_complex string that chains your filters. The basic structure involves loading both videos, processing them, and merging them. For a green screen effect, you might also want to apply chroma keying before overlaying, but for a solid green block, the raw overlay is sufficient.
The critical part is the
x and
y coordinates, and more importantly, the
enable option. The
enable option accepts an expression that evaluates to true or false at each frame. You can use the
t variable, which represents the current timestamp in seconds.
For example, to show the overlay from second 0 to 60, then hide it from 60 to 120, and repeat this cycle, you can use a modulo operation. The expression
mod(t, 60) < 5 would show the overlay for the first 5 seconds of every minute. Adjust the
5 to match the duration of your green overlay clip.
Here is the general syntax structure:
ffmpeg -i main.mp4 -i overlay.mp4 -filter_complex "[0:v][1:v]overlay=x=0:y=0:enable='mod(t\,60)<5'[vout]" -map "[vout]" output.mp4
Note the escaping of the comma in
mod(t\,60). In many shells, commas inside filter expressions must be escaped to prevent parsing errors. If you are using Windows CMD, you may need different quoting strategies. On Linux/Mac Bash, single quotes around the entire expression and backslash-escaping the comma is standard.
Handling Multiple Intervals
If you need multiple distinct intervals per minute, such as appearing at 0-5s and 30-35s, you combine conditions with logical OR (
or) or AND (
and).
enable='mod(t,60)<5 or mod(t,60)>=30 and mod(t,60)<35'
This logic ensures the overlay is visible only during those specific windows. The
t variable resets its context relative to the filter's start, but since we use
mod, it cycles through the minutes seamlessly regardless of the total video length.
Alternative: Using trim and concat
Another robust method avoids complex expressions by physically cutting the main video into segments, inserting the overlay, and then concatenating them. This is useful if you have many different overlay patterns or if the expression engine struggles with performance on very long videos.
1. Use
ffmpeg -ss 0 -t 60 -i main.mp4 segment1.mp4 to cut the first minute.
2. Overlay the green clip onto
segment1.mp4.
3. Cut the next minute
segment2.mp4.
4. Leave
segment2.mp4 without the overlay.
5. Repeat for all minutes.
6. Create a list file
list.txt with entries like
file 'segment1_overlay.mp4' and
file 'segment2.mp4'.
7. Run
ffmpeg -f concat -i list.txt -c copy final.mp4.
This method is less elegant but extremely reliable because it relies on standard muxing rather than real-time filter evaluation. It also helps avoid the excessive memory usage issues sometimes seen with large filter graphs, as discussed in related troubleshooting articles.
Performance Considerations
Real-time filtering with
overlay and expressions can be CPU-intensive, especially if you are using high-resolution overlays or additional filters like
chromakey. If you encounter dropped frames or slow encoding, consider pre-rendering the filtered segments using the
trim and
concat method mentioned above. This moves the heavy lifting to disk I/O rather than RAM and CPU during the final muxing phase.
Also, ensure your overlay video has the same resolution and frame rate as the main video to prevent rescaling overhead. If they differ, FFmpeg will automatically insert
scale and
fps filters, which adds latency. Explicitly scaling the overlay to match the main video in the
filter_complex gives you more control and often better performance.
Common Pitfalls
One frequent error is forgetting to map the output video stream. When you use
filter_complex, FFmpeg does not automatically map the result to the output file. You must explicitly include
-map "[vout]" (or whatever label you assigned) in your command line. Without this, the output file will either be empty or contain only audio if you mapped it separately.
Another issue is synchronization drift. If your main video has variable frame rates (VFR), the
t variable in the expression might not align perfectly with visual frames. Converting the main video to a constant frame rate (CFR) using
-r 30 before applying the filter ensures that the timing expressions behave predictably.
For more details on handling video streams and avoiding common pitfalls like early audio termination, you might find these resources helpful:
Weird FFmpeg Behavior: Shortest Flag Ends Audio Early
Troubleshooting Excessive Memory Usage with ffmpeg Overlay Filter
Frequently Asked Questions
Why does my overlay flicker or stutter?
Flickering usually occurs when the overlay's frame rate differs from the main video, causing resampling artifacts. Ensure both videos are converted to the same constant frame rate before filtering, or use the
fps filter in your complex graph to normalize the overlay stream.
Can I use this method for non-periodic overlays?
Yes, you can specify exact timestamps instead of using modulo arithmetic. For example,
enable='between(t,10,15)' shows the overlay only between 10 and 15 seconds. This provides granular control for one-off events within the video timeline.
What if my green overlay has transparency?
If your overlay is a PNG or WebM with alpha channels, the
overlay filter handles transparency automatically. You do not need to use chroma keying unless you are trying to remove a specific color from a video file. The filter blends the alpha channel directly onto the background.
How do I position the overlay in the center?
Use expressions for the x and y coordinates. For center alignment, set
x=(main_w-overlay_w)/2 and
y=(main_h-overlay_h)/2. These variables refer to the dimensions of the main video input, ensuring the overlay stays centered regardless of resolution changes.
Is there a limit to how many overlays I can stack?
FFmpeg supports multiple layers, but each additional
overlay filter increases computational load significantly. Stacking more than three or four overlays may lead to encoding slowdowns or memory exhaustion. For complex compositions, consider rendering intermediate layers to disk files before combining them.