Burn-In
Because metadata does not survive a client review
- images
- stamped
ComfyUI has an unusually good story for metadata: the whole node graph lives inside the PNG, which is why dragging a render back onto the canvas rebuilds your pipeline. None of that survives a screenshot, a WhatsApp forward, a QuickTime export or a Vimeo upload. Burn-In bakes the important parts into the pixels instead, which is what a VFX house has done to dailies since before any of us were born.
What it stamps
Two things by default, both useful:
- Frame number as
# 001001- six digits, starting fromstart_frame(default 1001, the VFX convention). - SMPTE timecode, computed from the frame number at your
fpssetting, with frame 0 as00:00:00:00.
Then custom_text for whatever else - shot code, version, take, "DO NOT GRADE". And position (bottom_left default, plus bottom_right, top_left, top_right, center), font_scale (0.5–4, giving 14px × scale with a 12px floor), and opacity (0.85, with the dark backing box at 0.6 of that) so the text is legible without being louder than the picture.
drop_frame is the professional bit: SMPTE drop-frame timecode drops frame numbers 00 and 01 at the start of every minute except every tenth, keeping the TC clock aligned with wall-clock time. It's only meaningful at 29.97 or 59.94 fps, and the frame field uses ; instead of :. The node handles the rate mapping itself.
Output is stamped (IMAGE).
The behaviour that makes it trustworthy
The overlay is rasterised separately and composited onto the float pixels, so everything outside the text and its backing box keeps its original value - including negative values, HDR super-whites, and the source alpha. Text RGB is 230/255 in whatever encoding the input is, and no colour transform is applied.
That matters because burn-in nodes are usually where a float chain dies. You spend the whole graph preserving range, then the dailies node quietly runs your image through an 8-bit buffer to draw some text on it. This one doesn't, which is why you can stamp an intermediate review frame and still keep working with it.
Where it belongs
Dailies, and the full pattern is: Burn-In → Contact Sheet for a stills review, or Burn-In → Flipbook GIF for a motion one. The GIF and the contact sheet strip metadata by construction - a GIF has no place to put a node graph - so the stamped frame number is the only thing that survives to the person watching. That's not a limitation, it's the reason burn-in exists.
Second use, less glamorous: proofing your own graph. Stamp a frame, and when a render turns up in a folder four days later you know which frame number it is without opening it.
Install
Part of Radiance. ComfyUI Manager → search Radiance → install, then restart ComfyUI and hard-refresh the browser. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/fxtd-studios/radiance.git
cd radiance
python -m pip install -r requirements.txt
Windows portable users: run the pip step with python_embeded\python.exe. Text rendering goes through Pillow, which is in requirements.txt. No model downloads.
Where people get burned
The font. font_scale sizes text at 14px × scale using DejaVu Sans Mono. If that font isn't on your system, Pillow falls back to its own fixed default - which does not scale the same way, so only the margins appear to change when you drag font_scale. On a bare Linux container or a stripped Windows install, that's the first thing to check if 4× text is still tiny.
Stamping the wrong frame numbers. start_frame is the number of the first frame in the batch, and every subsequent frame counts up from it. If you feed a batch that's a slice of frames 200–260 and leave start_frame at 1001, every stamp is a cheerful lie. It's the most common way to get a dailies reel that nobody can navigate.
Forgetting the composition cost. The text sits over your image, permanently. On a client review it's fine - that's the point of burn-in. On something you want to deliver, don't, because there is no metadata layer to remove afterwards. Burn-in is one-way by definition.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | Float frames to stamp. Values outside the overlay and the source alpha are preserved, including negative and HDR values. Text RGB is 230/255 in the input encoding; no colour transform is applied. | |
| start_frame | INT | 10010–999999 | Frame number of the first frame in the batch. |
| fps | FLOAT | 24.0001–120 | Frames per second (used for timecode calculation). |
| drop_frameopt | BOOLEAN | false | Use SMPTE drop-frame timecode (DF). Only meaningful at 29.97 or 59.94 fps. Uses ';' separator instead of ':' for the frame field. |
| show_frame_numberopt | BOOLEAN | true | Burn the frame number as '# 001001' (6 digits). |
| show_timecodeopt | BOOLEAN | true | Burn the SMPTE timecode of the frame number at fps. Frame 0 is 00:00:00:00. |
| custom_textopt | STRING | Additional text burned into each frame (e.g. shot name, version). | |
| positionopt | COMBO | bottom_left | Where the text block sits in the frame. |
| font_scaleopt | FLOAT | 1.00.5–4 | Text size: 14 px x scale (minimum 12 px) with DejaVu Sans Mono. Without that font, Pillow's fixed default font is used and only the margins scale. |
| opacityopt | FLOAT | 0.850.1–1 | Text opacity; the dark backing box uses 0.6 x this. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| stamped | IMAGE | — |