Add Human demo videos (robot โ human, fal MiniMax-H3 480P) as a Video generation option
#1
by pepijn223 HF Staff - opened
Adds Human demo videos, a new Video generation category on the Annotations step next to the text annotations. For each subtask, the job generates a first-person video of human hands doing that subtask from the robot view. It mirrors LeRobot's --human_video annotation module (huggingface/lerobot#4809) and runs on the current pinned pipeline bundle, which stays unchanged.
Pipeline (per subtask, after the episode's annotations pass validation)
- The selected VLM reads 6 robot frames and writes the human task and an image-edit prompt.
Qwen/Qwen-Image-Edit-2509(fal,guidance_scale=1.5) edits the full-resolution first frame: it removes the robot and adds two resting human hands. The output is resized back to the camera size.- The VLM writes a step-by-step video prompt from the edited frame.
MiniMaxAI/MiniMax-H3at 480P, 5 s (fal, via HF Inference Providers) animates it. Theimage-text-to-videotask isn't inInferenceClientyet, so this reuses fal's image-to-video queue helper and adds a polling loop that respects the job's deadline.
Cost and safety
- Pricing is pinned in
model_catalog.HUMAN_VIDEO: $0.04 for the edit plus $0.30 for the video (480p is $0.05/s, reserved as 6 s). - The estimate prices every possible video (episodes ร videos per episode) plus 2 VLM calls per video.
- Each media request reserves its price from the spending target before it starts, and the reservation is never refunded.
- Reaching the target or the runtime limit stops further videos but keeps the episode's annotations. A failed video is recorded and the others continue.
- The launch checks that both fal mappings are
liveand that the video pricing has not changed since the estimate. - Selecting videos also selects Subtasks, and the backend enforces this.
- The token stays server-side and is sent only as the job secret. The fal CDN download goes out without auth headers.
Output
- Files are written to
annotation_studio/human_videos/episode_XXXXXX/segment_XXX{.mp4,_first_frame.png,_robot_frame.png}, named by source episode. index.jsonlists each segment's subtask, timestamps, prompts and status, plus theepisode_indexit was materialized as. It is uploaded in the per-episode commit.run.jsonrecords per-episode video counts, and its usage section includesmedia_usd.- The dataset card gets a "Human demonstration videos" section.
UI
- New annotation: a separate "Video generation" card with a videos-per-episode picker (1/2/3/5/8), models, price and pricing link. The cost breakdown gets a "Human demo videos" line.
- Jobs: a video count and cost line, plus a lazy preview grid (robot frame next to the human video). Media is proxied through
/api/jobs/{id}/media, so private outputs stay private. That endpoint only allows the generated file paths, checks the job's owner, and never exposes prompts.
Testing
test_human_video.py(12 tests) covers:- pricing and dependency validation;
- launch checks for fal liveness and stale prices;
- media budget accounting;
- a real-video episode with a fake media client, checking full-resolution edits, failed segments, budget stops and the segment cap;
- commit operations and index;
- fal router polling, including no token sent to the CDN and the deadline guard;
- the media endpoint's path allow-list and auth.
- The existing suite passes (86 passed).
bun run build(tsc and vite) is clean. - A real fal call through
FalMediareturned a 640ร480, 24 fps, 5.18 s video with a correct human hand. The edit took 14 s and the video 15 s, and the budget recorded $0.34. - UI checked at desktop and phone width.
Not yet run: a full paid job on the deployed Space. That needs this PR merged or deployed, because jobs download the Space revision.
๐ค Generated with Claude Code
Update:
- Price follows episode length and count. About one subtask per 5 s of each episode (at least one per episode), up to 2ร that in the upper bound, with the per-episode cap applied. The breakdown shows ~expected / up to N videos and a $ range.
- Every subtask is now the default for videos per episode; 1/2/3/5/8 still cap it.
- Parallel generations (1/4/8/16/32, default 8) sets the job-wide limit on simultaneous fal requests. The review warns if the expected videos at that parallelism would outlast the timeout (~3 min per video).
Tests: 89 passed. Checked in the browser: 5 ABC episodes (10.6 min) with every subtask give ~127 videos (up to 256), $43โ$87.
pepijn223 changed pull request status to open
pepijn223 changed pull request status to merged