Video Overlay with Subtitles (画中画+字幕)
Picture-in-picture with burned-in subtitles, straight from Whisper timestamps
- alignment
- video_path
This is the upgraded version of the pack's plain VideoOverlayNode, and the headline feature is the one that turns it from "handy compositing helper" into "auto-captioning machine": it can burn subtitles directly from Whisper-style alignment data. If your workflow already transcribes a video into timestamped segments, this node takes that data, overlays your picture-in-picture clip, renders the captions onto the frame, and hands back one finished MP4. No intermediate SRT file, no fiddling with an external subtitle tool.
What changed vs. the base node
Everything from VideoOverlayNode is here - same big_video_path / small_video_path / mask_video_path strings, same size_ratio, position, margins, opacity, and the same per-clip audio and speed controls, including the surprising defaults (base audio muted at 0.0, base speed at 1.8×). What's added is the alignment input plus the whole subtitle styling block, and one extra required field: video_fps (default 24), which the node uses when it builds the timeline.
How the subtitles work
The alignment input accepts a whisper_alignment custom type - a list of segments like {"value": "...", "start": 0.0, "end": 4.86} - either wired directly from a transcription node or pasted as a JSON string. The node parses it, word-wraps each segment against max_subtitle_width (0 = auto, about 80% of the video width), then renders each segment as an ffmpeg drawtext filter with escaping handled for you. Text is drawn between start and end, with a background box whose color and opacity you control. Output is the same libx264 + aac + +faststart MP4 written to ComfyUI/output/, and video_path is the only output.
The subtitle inputs worth touching
font_path- a dropdown that auto-detects the pack'sfonts/folder (it ships ~18 fonts, including a Chinese font) plus common system fonts. Default is "YRDZST Semibold.ttf".font_size(12–200, default 48) andfont_color(any ffmpeg color name or hex).subtitle_position-bottom_centerby default, with top/bottom-left/right, center, orcustom, which activatesx_position/y_position.subtitle_bg_opacity/subtitle_bg_color- the caption backdrop. Defaults of 0.7 opacity over black give you the standard legible caption look.
The subtle trap: if you want subtitles and your alignment input is empty or fails to parse, the node silently proceeds and just doesn't draw text - it logs a [VideoOverlay] 警告 in the console but the MP4 still comes out. If your captions are missing, check that first.
Installing and the usual suspects
Same install as the whole pack: ComfyUI Manager (search "ComfyUI-VideoOverlayFFmpeg"), or clone into custom_nodes and pip install -r requirement.txt (that file is just ffmpeg-python - the real dependency is a system ffmpeg on your PATH). Then restart. There are no model downloads; the fonts ship inside the repo.
The classic failures: captions show as boxes or garbage - your font doesn't support the script, so pick a CJK font for Chinese text. Text runs off the edge - lower font_size or set max_subtitle_width to ~70–80% of the video width. Text appears for the whole clip or not at all - your alignment segments are missing proper start/end fields. And as with the base node, use absolute paths without spaces, or the file-existence check trips first.
If you're doing talking-head-over-B-roll content, this is the rare node that finishes the whole captioning+compositing job inside the graph. It's worth the two minutes of install.
Inputs (23)
| Name | Type | Default | Description |
|---|---|---|---|
| big_video_path | STRING | — | |
| small_video_path | STRING | — | |
| mask_video_path | STRING | — | |
| opacity | FLOAT | 1.000–1 | — |
| position | COMBO | right_bottom | 5 options: right_bottom, right_top, left_bottom, left_top, center |
| margin_x | INT | 00–500 | — |
| margin_y | INT | 00–500 | — |
| size_ratio | FLOAT | 0.250.1–1 | — |
| big_video_audio_volume | FLOAT | 0.00–2 | — |
| small_video_audio_volume | FLOAT | 1.00–2 | — |
| video_fps | FLOAT | 241–120 | — |
| big_video_speed | FLOAT | 1.80.25–4 | — |
| small_video_speed | FLOAT | 1.00.25–4 | — |
| alignmentopt | whisper_alignment | — | |
| font_pathopt | COMBO | YRDZST Semibold.ttf | 18 options: YRDZST Semibold.ttf, YoungSerif-Regular.ttf, impact.ttf, Oswald-Bold.ttf, Roboto-Regular copy.ttf, PixelifySans-Bold.ttf, +12 |
| font_sizeopt | INT | 4812–200 | — |
| font_coloropt | STRING | white | — |
| x_positionopt | INT | 0-1000–3000 | — |
| y_positionopt | INT | 0-1000–3000 | — |
| subtitle_positionopt | COMBO | bottom_center | 6 options: bottom_center, top_center, bottom_left, bottom_right, center, custom |
| max_subtitle_widthopt | INT | 00–4000 | — |
| subtitle_bg_opacityopt | FLOAT | 0.70–1 | — |
| subtitle_bg_coloropt | STRING | black | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| video_path | STRING | — |