Create a polished social demo video (MP4, 4:3, ~10s) for any Hugging Face Space with the space-demo-kit renderer. Use whenever the user asks for a demo, promo, showcase, or social video of a HF Space or model. Covers template selection (i2v, t2v, edit, avatar, a2a, gallery, vqa), manifest schema, live asset capture, rendering, verification, and delivery.
npx skills add https://github.com/huggingface/space-demo-kit --skill space-demo-video
The kit renders a Gradio-style "app window" video: a hero intro where the input opens
near full-frame with the prompt typing in large text (readable at mobile feed size),
a morph into the app layout with the Space's real header (emoji, author/name, likes,
hardware), a Generate press, a progress sweep, and the real output filling the output
panel edge-to-edge. Text auto-fits its panels (short answers render huge, long ones stay
readable). Branding is extracted from the Space page automatically. Output: 1440x1080
(4:3), 30 fps, ~12–17 s, H.264, silent unless the task itself involves audio.
Kit location on this machine: /root/code/space-demo-kit
Render command (the ONLY way to produce the video):
cd /root/code/space-demo-kit && python3 render.py manifests/<name>.json
# -> out/<name>/<name>.mp4 + out/<name>/<name>-contact.jpg
no custom HTML. The kit owns 100% of the design; you only supply facts and assets via a
manifest JSON.
gradio_client) with areal input. Only mock when live inference is impossible (quota, broken Space), and then
label it honestly in the manifest meta field (e.g. "mock demo assets") and tell the user.
emoji, colorFrom, colorTo, likes, and hardware fromhttps://huggingface.co/api/spaces/<id> (cardData + runtime.hardware.current).
If the user gives a MODEL id, resolve its demo Space first (model page / spaces field of
https://huggingface.co/api/models/<id>).
pick or write inputs that fit.
ffprobe the MP4 (duration, 1440x1080) and look at thecontact sheet (no overflowing text, output visible). Then send the MP4 to the user as media.
"style" key in a manifest — the app-window template is theonly production design and the renderer ignores styles. Anything under experiments/ is a
rejected prototype: never use it as an example or reference.
the short side. NEVER an emoji, icon, favicon, logo, or clipart — tiny images upscale into
blurry blobs and ruin the video. Verify every asset with file + dimensions before using it.
examples in its Gradio config,or files in the Space repo via https://huggingface.co/api/spaces/<id>/tree/main). They are
known to work with the model.
edit, a2a): the output MUST actually be derived from theinput. Never pair two unrelated assets — an incoherent before/after is worse than no video.
If live inference fails: retry via gradio_client (not hand-built HTTP calls), try another
example input, and if it still fails, report the failure to the user and STOP. Do not
fabricate the pair.
| template | Space task | required manifest fields |
|---|---|---|
| i2v | image → video | input_image, prompt, video (generated clip) |
| t2v | text → video | prompt, video |
| edit | image + instruction → image | input_image, prompt, before_image, after_image |
| avatar | portrait + audio → talking video | input_image, audio, video (audio can be the generated mp4 itself) |
| a2a | audio → audio | audio_in, audio_out |
| gallery | one input → several images | input_image, prompt, outputs (list of {path, label}, 4 items) |
| vqa | video/image + question → text | video, prompt, answer |
Text-to-image Spaces use t2v: turn the generated image into a short static clip first
(ffmpeg -loop 1 -i out.webp -t 6 -r 30 -pix_fmt yuv420p static.mp4) and pass it as video
(see manifests/z-image-turbo-demo.json). There is no t2i template.
Common fields (all templates):
{
"name": "my-demo", // output folder + file name
"template": "edit",
"space": {
"id": "owner/space-name",
"emoji": "🧬", // from cardData
"colorFrom": "blue", // from cardData
"colorTo": "gray", // from cardData
"likes": 27, // from the API
"hardware": "zero-a10g" // runtime.hardware.current
},
"meta": "live output · zero-a10g", // small honest footer note; use "mock demo assets" for mocks
"button": "Generate", // optional; e.g. "Enhance", "Animate"
"input_label": "source image", // optional label overrides
"prompt_label": "edit instruction",
"output_label": "edited image",
"audio_gain": 2.0, // optional; default 2.0 (with limiter)
"hero": false // optional; set false to skip the full-frame intro
}
Plus the template-specific fields from the table. All asset paths are absolute paths on
this machine. Store working assets under /root/code/<project-dir>/ as usual.
curl -s https://huggingface.co/api/spaces/<id> → metadata for space{} fields.the closest; do NOT invent a new design.
live Space with gradio_client, download the real output. Verify the output file with
ffprobe/file before rendering.
manifests/<name>.json in the kit.inputs, extracts frames. A render takes roughly 3–5 minutes — do not assume it hung.
Demo-video requests are heavy (live inference + a ~2 min render). Do NOT run inference or
rendering inline in the main session — it blocks you for many minutes. ALWAYS dispatch a
codex session per the codex-monitor skill (setsid, </dev/null, CODEX_HOME pinned) and let
the CODEX_FINISHED wake drive verification + delivery. Include in the codex prompt:
"Read /root/code/space-demo-kit/skills/space-demo-video/SKILL.md and follow it exactly.
Use the kit's render.py for ALL visuals; do not design any frame yourself."
avatar, a2a) mux the real audio automatically, delayed to the momentplayback starts on screen, at 2x gain with a limiter.
gallery wants exactly 4 outputs for the 2x2 grid.vqa answers auto-fit the output panel: keep them 30–60 words so the type stays large.templates/app-window.html or render.py for a one-off video. If a Spacegenuinely needs a new mode, report that instead of hacking around the kit.
Take huggingface/space-demo-video from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.