Video Character Swap · Video Analysis
The analysis pass that doesn't touch your video
- video_url
- previews
- text
- task id
What it is, and why the job comes in two nodes
Swapping a person out of a video isn't one operation, it's two: first you have to know which people are in which frames, then you have to put someone else's likeness onto each tracked person consistently. SpicyAPI splits it exactly that way, and this is the first half - the analysis pass. $0.08 per run, and it produces no video at all. Change nothing, that's the design.
The payoff is control. Instead of "swap the person" and hoping, you get back one numbered preview still per detected person and a text readout, and then you decide who gets replaced. If your clip has a crowd, this is the difference between a useful tool and a coin flip.
How it works
You give it a video and it tracks every person through it, at the tracking resolution you pick. It uploads the MP4 (90 MiB ceiling), runs spicyapi/character-swap-v1/video-analyze, and returns numbered stills - one per detected person - plus a task id that the second node needs.
The task id is load-bearing: it's what carries the tracking result to the swap call, and it stays usable for 24 hours. The previews and the swap node's target indices are listed in the same order, which is the only reason the pairing works at all. Wire task id into the Video Edit node's analysis_task_id field, and keep the text output - it's the human-readable list of what was detected.
The inputs
video_url (VIDEO) - source clip, 5 to 30 seconds, MP4. Upload it with the core Load Video node, or pass a public MP4 URL. Keep the URL you used here, because the swap call has to run on the same video; if you re-load it differently the later request gets rejected.
resolution - 480p or 720p, default 720p. Two things to understand. First, it's tracking resolution, and it doesn't change what this call costs. Second, the swap call must use the same value - so pick the resolution you want the finished clip to have, not the cheapest one. Choosing 480p here to save money locks your output at 480p.
Outputs: previews (IMAGE, one per detected person, numbered in detection order), text (STRING), task id (STRING).
Install
Manager → search SpicyAPI, or:
cd ComfyUI/custom_nodes
git clone https://github.com/spicyapi-ai/comfyui-spicyapi
Restart. No dependencies, no model downloads - the pack runs entirely against SpicyAPI's servers and declares an empty dependency list. It needs Python 3.10+ and a ComfyUI with the V3 node API. Set your key in Settings > SpicyAPI (or SPICY_API_KEY), restart once so the catalogue loads, and set Max cost per run before you touch a video node.
Traps
- Orphaning the task id. Re-running the analysis node generates a new task id. If the edit node is still holding the old one from a previous queue, you're pairing two different runs. Reconnect it each time.
- Resolution drift. Analyze at 720p, edit at 480p, request rejected. Same for the video: pass a different URL in the
video_urlfield and the request is refused rather than silently ignored, which is the honest behaviour. - Length limits are hard. Three seconds or thirty-five, and the clip is rejected before any charge. Trim in ComfyUI first.
- 24 hours, not forever. The task id expires, and after that your edit node has nothing to point at.
- Cancelling the run doesn't cancel the job on SpicyAPI's side; if it completes, it's charged and the result sits in your console for up to 14 days.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| video_url | VIDEO | Source video, 5 to 30 seconds long. Upload an MP4 or pass a public MP4 URL. The swap call has to run on this same video, so keep the URL you used here. | |
| resolution | COMBO | 720p | Tracking resolution. The swap call must run at the same value, so pick the resolution you want the finished clip to have. It does not change what this call costs. |
| seed | INT | 00–2147483647 | This model takes no seed, so the number is never sent. Changing it makes ComfyUI run the node again: set 'control after generate' to randomize for a new result on every run; every run is billed. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| previews | IMAGE | — |
| text | STRING | — |
| task id | STRING | The SpicyAPI task id, for the console logs or support. |