Whisper Text Renderer β‘π ‘π π £π
Burn animated, word-synced captions onto video
- images
- feature
- IMAGE
Those animated, word-highlighted captions you see on short-form video - the ones where text pops in synced to exactly when each word is spoken - are what this node builds directly inside ComfyUI. It's not just subtitles dumped on screen; it draws text onto your frames using per-word timing data, so the caption's appearance is locked to the actual speech, not an estimated block of time.
How it works
The timing data comes in through feature, a FEATURE object carrying Whisper alignment - the per-word start/end timestamps a Whisper transcription step upstream in this pack produces. This node then overlays styled text onto images frame by frame, using that alignment to know exactly which frames each word should be visible on. Everything else is presentation: font_name (a handful of built-in, system-independent fonts, so the look is consistent regardless of what's installed on the machine running it), font_size, position (top/middle/bottom) and horizontal_align (left/center/right) for placement, margin for spacing off the frame edges, and bg_color/text_color/opacity for the actual look of the text.
animation_type is where this stops being static subtitles: none is flat static text, fade smooth-fades each word or line in and out, pop does a scale/bounce-in, and slide animates text sliding into position - all timed to animation_duration (in frames). max_width handles wrapping - 0 uses the full frame width, anything above that constrains text to a narrower column and wraps it.
Inputs and outputs
images(required,IMAGE) - the video frames to render text onto.feature(required,FEATURE) - the Whisper alignment data; this has to come from an upstream Whisper transcription node in this pack, not a plain transcript string.font_size,position,animation_type- the three settings most beginners actually touch; everything else has sensible defaults.- Output - a single
IMAGE, the same frames with text composited on.
Note that the required feature input is typed FEATURE, not the pack's TRIGGER_SET type - this node consumes a different upstream product than Trigger Builder does, even though both live in the same Whisper-source category. Don't expect to wire a TRIGGER_SET directly into this node's feature slot; the types won't match.
Installing it
Install through ComfyUI Manager (search RyanOnTheInside) or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/ryanontheinside/ComfyUI_RyanOnTheInside
Then pip install -r requirements.txt and restart ComfyUI. Whisper itself downloads its model automatically from Hugging Face the first time any Whisper-based node in this pack runs - budget for that one-time delay, especially on a slower connection, before assuming the node is hung.
Common issues
The most common mistake is trying to feed this a plain string or a generic transcript rather than the proper Whisper FEATURE output - the alignment data (per-word timing) has to come from this pack's own Whisper transcription node, since that's what makes the captions sync to speech instead of just appearing all at once.
If text renders but looks cut off or oddly wrapped, check max_width before fiddling with font_size - leaving it at 0 uses the full frame, which can run text edge-to-edge on a narrow or vertical video; a modest max_width plus horizontal_align: center usually reads better for short-form formats. And if the animation looks too abrupt or too slow, animation_duration is a frame count, not a percentage or seconds value - tune it relative to your actual frame rate, not a fixed number that "felt right" on a different clip.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | Input video frames to overlay text on | |
| feature | FEATURE | Whisper feature containing alignment data | |
| font_size | INT | 328β256 | Size of the rendered text (8-256 pixels) |
| font_name | COMBO | arial | Font to use for rendering. Uses system-independent built-in fonts. |
| position | COMBO | bottom | Vertical position of text: - top: Align to top of frame - middle: Center vertically - bottom: Align to bottom of frame |
| horizontal_align | COMBO | center | Horizontal text alignment: - left: Align to left edge - center: Center horizontally - right: Align to right edge |
| margin | INT | 200β200 | Distance from frame edges in pixels |
| animation_type | COMBO | fade | Type of text animation: - none: Static text - fade: Smooth fade in/out - pop: Scale animation - slide: Sliding animation |
| animation_duration | INT | 151β60 | Length of animation in frames |
| max_widthopt | INT | 0 | Maximum width for text wrapping. 0 = use full frame width |
| bg_coloropt | STRING | #000000 | Background color in hex format (#RRGGBB) |
| text_coloropt | STRING | #FFFFFF | Text color in hex format (#RRGGBB) |
| opacityopt | FLOAT | 0.800β1 | Overall opacity of text overlay (0.0-1.0) |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | β |