Magic Hour: Talking Photo
Magic Hour: Talking Photo
- image
- audio
- video
- video_path
- credits_charged
This is the example the pack's own README leads with, and it's the one people actually want: photo of a person, audio of them talking, video of them talking. It's the cheapest convincing "avatar" result in the whole node set, because you don't need footage - you need one decent portrait.
The two modes, and why the prompt field is a trap
generation_mode is realistic (default) or prompted, and they're not a quality setting. realistic drives the head from the audio alone: mouth shapes, small head motion, blinks. prompted additionally takes your prompt text to steer expression and performance.
Here's the part that wastes people's time: prompt is only used in prompted mode. Type a beautiful description of the performance you want, leave generation_mode on realistic, and it goes nowhere. The field is still sitting there looking active in the node UI - the tooltip is the only thing telling you it does nothing. The node won't warn you.
So: realistic for a straight read, prompted when the delivery matters ("she's laughing mid-sentence", "he's reading a serious announcement"). The prompt shapes performance, not appearance - the photo already decided what the person looks like.
The 60-second ceiling
The pack caps audio at 60 seconds and uses min(clip length, 60) as the available length. Leave end_seconds at 0 and you get the whole thing up to a minute; anything longer is truncated, not compressed. Long scripts are made in segments and stitched, or you move to a different tool.
The tooltip on end_seconds says this plainly - 0 = use the whole audio (max 60s window) - and it's the single most-missed constraint in the pack.
How it works
The image becomes a temp PNG, the AUDIO becomes a temp 16-bit WAV, both upload. The job runs remotely, watching only for the audio window you specified, and the resulting MP4 is downloaded into ComfyUI/output/magic_hour/ and wrapped as a VIDEO.
Frame-zero rule applies: only the first image of a batch is used. Two portraits into one node gives you one talking portrait.
Inputs and outputs
| field | what it is |
| --- | --- |
| image (required) | the portrait. Front-on, mouth fully visible, even lighting. Not a profile, not a hand-over-mouth selfie |
| audio (required) | the speech. Clean, no music bed |
| generation_mode | realistic or prompted |
| start_seconds / end_seconds | the audio window; end_seconds 0 means to the end of the clip, capped at 60s |
| prompt | performance direction - prompted mode only |
Outputs: video (a proper VIDEO, wire to Save Video), video_path (STRING), credits_charged (INT).
Install
cd ComfyUI/custom_nodes
git clone https://github.com/magichourhq/comfyui-magic-hour
pip install -r comfyui-magic-hour/requirements.txt
Restart ComfyUI, then look under Magic Hour. Dependency: magic-hour>=0.87.1, nothing else - no InfiniteTalk weights, no Wan, no MultiTalk LoRA to fetch. That's the actual argument for this node: the local equivalent is a multi-pack install with a transformers dependency fight at the end of it, and this is one pip line. ComfyUI Manager users can search "Magic Hour".
export MAGIC_HOUR_API_KEY=your_key_here
before launching, or the bare key in comfyui-magic-hour/api_key.txt. Not a widget, because widget values are stored inside the workflow JSON.
What goes wrong
The mouth moves, the face doesn't. Audio-only driving produces convincing lips and slightly uncanny stillness. That's realistic mode being realistic. If you want life in the eyes and shoulders, prompted mode and a prompt about expression helps, and the local InfiniteTalk/MultiTalk route helps more.
Teeth. Always teeth. Frame through the result before you publish; the two worst frames are usually a hard consonant.
Audio longer than 60s, half a video back. Covered above, and it's the number one report.
Prompt ignored. Check generation_mode. Again.
Queue blocked for minutes. Video job, synchronous wait.
A face going to a third party. For your own, fine. For a colleague or a client, get the yes in writing first.
The workflow pattern that works: generate the voice locally with a TTS model (free, fast, private), feed both into this node, and only pay for the pixels. That's also one of the few genuinely sensible hybrid pipelines in this pack - local for what's cheap, hosted for what isn't.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| audio | AUDIO | — | |
| generation_mode | COMBO | realistic | 2 options: realistic, prompted |
| start_seconds | FLOAT | 0.00–3600 | — |
| end_seconds | FLOAT | 0.00–3600 | 0 = use the whole audio (max 60s window) |
| prompt | STRING | Only used in 'prompted' mode |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| video | VIDEO | — |
| video_path | STRING | — |
| credits_charged | INT | — |