Add Subtitles To Frames
Burn word-timed captions straight into your video
- images
- alignment
- IMAGE
- MASK
- cropped_subtitles
- subtitle_coord
This is the node that actually puts captions on your video - permanently, baked into the pixels. Where Save SRT gives you a portable subtitle file a player toggles on and off, Add Subtitles To Frames draws the text directly onto every frame. That's the tradeoff up front: you lose the ability to turn captions off later, but you gain something SRT can't give you - captions that work anywhere, including platforms and players that don't read subtitle tracks at all (most short-form social video, for a start).
Where it sits in the pipeline
It's the second stop after Apply Whisper. Apply Whisper listens to your audio and hands back word-level timestamps; this node takes those timestamps plus your actual video frames and renders text onto them, one word (or the words active at that timestamp) at a time, synced to when they're spoken. The mechanism is straightforward once you see it: for every frame, the node checks which words' timestamps overlap that frame's position in the video (using video_fps to convert frame index to a time), and draws whichever word(s) are active at that instant, in your chosen font, size, color, and position.
The inputs and outputs that matter
Two required inputs carry the real content - everything else is styling:
images- your video frames as anIMAGEbatch (a video loader feeding into this, typically).alignment- plug inwords_alignmentfrom Apply Whisper here, notsegments_alignment. This node times individual words to individual frames, so it needs word-level granularity.
The rest is font and layout: font_color / font_border_color (default white-on-black outline, readable on almost any footage) and font_border_width for outline thickness. font_family picks from four bundled fonts - Roboto regular and bold for Latin text, plus YRDZST Semibold and Chanakya Regular for CJK and Devanagari scripts, so non-Latin transcripts aren't an afterthought. font_size, x_position/y_position, and the center_x/center_y booleans (default true) control placement - leave centering on for classic caption behavior, turn it off to hand-place coordinates. video_fps has to match your actual video's frame rate or word timing drifts out of sync with the frames as the clip plays.
Four outputs come out: the composited IMAGE (your frames with subtitles burned in - this is almost always what you want), a MASK isolating just the text region per frame, cropped_subtitles (the subtitle region cropped out as its own image), and subtitle_coord (where that crop came from). The mask and crop pair exist for one specific downstream use: if you want to further process, translate, or restyle just the subtitle text - through an img2img pass, for instance - without touching the rest of the frame, crop it out here, process it, and hand subtitle_coord to Resize Cropped Subtitles to paste the result back at the right size and position.
How to install it
ComfyUI Manager: search ComfyUI Whisper, install, restart. Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/yuvraj108c/ComfyUI-Whisper
then restart. This node itself doesn't pull extra weights - the model download happens back at Apply Whisper - but the pack's dependencies (openai-whisper, pillow, soundfile) install alongside it either way.
Common issues & troubleshooting
Captions are readable but drift out of sync as the video plays. Almost always a video_fps mismatch - the node is placing words by converting timestamps to frame numbers using this value, so if it doesn't match your actual export frame rate, the drift compounds over the length of the clip. Double-check your video loader's fps against what you typed here.
Text is unreadable against bright or busy footage. The default white-with-black-border is a reasonable general choice, but for consistently bright scenes bump font_border_width up, or flip to a darker font_color with a light border. There's no auto-contrast here - it's a static color choice per run.
Wrong alignment plugged in and words look chopped or wildly mistimed. This node wants words_alignment, not segments_alignment. They're both the pack's whisper_alignment type so ComfyUI won't stop you from wiring the wrong one - the mistake only shows up visually, as text that jumps oddly or doesn't match the granularity you expected.
Non-Latin script renders as boxes or blanks. Make sure you've picked a font_family that actually covers your script - YRDZST Semibold for CJK, Chanakya Regular for Devanagari. The two Roboto options only cover Latin characters.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| alignment | whisper_alignment | — | |
| font_color | STRING | white | — |
| font_border_color | STRING | black | — |
| font_border_width | INT | 4 | — |
| font_family | COMBO | 4 options: YRDZST Semibold.ttf, Roboto-Regular.ttf, Chanakya Regular.ttf, Roboto-Bold.ttf | |
| font_size | INT | 100 | — |
| x_position | INT | 100 | — |
| y_position | INT | 100 | — |
| center_x | BOOLEAN | true | — |
| center_y | BOOLEAN | true | — |
| video_fps | FLOAT | 24 | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| MASK | MASK | — |
| cropped_subtitles | IMAGE | — |
| subtitle_coord | subtitle_coord | — |