Specification
Skill ID
starchild-ai-agent/official-skills/video
Publisher
starchild-ai-agent
Repository
official-skills
Installs
0
Files
6
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

starchild-ai-agent/official-skills/videoInstalls these files
  • SKILL.md
  • _cost_track.py
  • generate_video.py
  • logo.png
  • poll_status.py
  • publish_asset.py

What this skill tells the agent

video

Use this skill for all video-generation requests on Starchild.

Core principle: call the provided scripts. Do not re-implement proxy/billing/upload plumbing.


1. Text-to-video (most common)

⚠️ Execution context — read this first. The code blocks below are Python, not shell commands. Starchild's bash tool runs /bin/bash -c, which cannot parse exec(open(...)) — pasting them directly into a bash command will fail with syntax error near unexpected token 'open'. Also, exec(open(...)) inside python3 -c fails with NameError: __file__ because the script uses __file__ for path resolution. Use `python3 - <<'EOF'` with `from exports import` when calling via the bash tool: ``bash python3 - <<'EOF' import sys sys.path.insert(0, "skills/video") from generate_video import generate_video result = generate_video( prompt="A cinematic drone shot over snowy mountains at sunrise", model="balanced", duration=5, ) print(result) EOF ` The heredoc (<<'EOF') preserves all quotes and newlines — no escaping needed. Note: video skill has no exports.py — import directly from generate_video`.
exec(open('skills/video/generate_video.py').read())
result = generate_video(
    prompt="A cinematic drone shot over snowy mountains at sunrise",
    model="balanced",   # "budget" | "balanced" | "premium"
    duration=5,
)
# result -> {"success": True, "cost": 0.70, "video_url": "...", "local_path": "output/videos/..."}

generate_video automatically: submits → polls → fetches result → downloads mp4 to output/videos/.

Delivering the result to the user — IMPORTANT

*Never hand the user the raw `video_url` (e.g. `https://.fal.media/.../.mp4`).* fal serves these files with Content-Security-Policy: sandbox; default-src 'none', which means:

  • Opening the link in a browser shows a blank page (no inline player triggered).
  • Embedding via <video> / <iframe> is blocked by CSP.
  • There is no Content-Disposition: attachment header, so the browser does not auto-download either.
  • URL-side tweaks (query params, ?download=1, etc.) cannot fix this — only a server-side header change would, and we don't control fal's CDN.

The only reliable user-facing delivery path is the already-downloaded local file:

  1. Use result["local_path"] (e.g. output/videos/xxx.mp4) — generate_video always downloads on success.
  2. Tell the user the file is saved to output/videos/<filename> and is viewable in the workspace file panel / file browser.
  3. On Web channel, also embed it inline so the user can preview it in chat: ``markdown ![video](output/videos/<filename>.mp4) ` (or link as video` — the workspace serves these directly with the right headers).
  4. On Telegram / WeChat: send the file via send_to_telegram(file_path="output/videos/...", message_type="video") or send_to_wechat(file_path="output/videos/...", message_type="video").

If the download somehow failed (local_path missing) — re-fetch with:

curl -L -o output/videos/<filename>.mp4 "<video_url>"

Then deliver the local path. Still do not give the user the raw fal URL as the primary deliverable.


2. Image-to-video / video-to-video (reference assets)

fal.ai needs the reference asset as a public https URL. fal storage upload requires a Serverless permission your key currently does not have. The reliable path is to expose the asset via a published Starchild preview.

Standard procedure

  1. Drop or copy the asset into output/fal_assets/ using publish_asset.py.
  2. Make sure a preview named `fal-assets` is running and published (one-time setup, see §3).
  3. Build the public URL as <preview_base>/<filename>.
  4. Call `generate_video(... image_url=public_url)`.
# Step 1: publish a local image into the asset folder
exec(open('skills/video/publish_asset.py').read())
asset = publish_local('/path/to/your/photo.jpg')
# or: publish_from_url('https://example.com/photo.jpg')

filename = asset['filename']

# Step 2: combine with the preview's public base URL (see §3)
public_url = f"https://community.iamstarchild.com/<user_slug>-fal-assets/{filename}"

# Step 3: image-to-video
exec(open('skills/video/generate_video.py').read())
result = generate_video(
    prompt="gentle cinematic camera push-in",
    model="balanced",
    duration=5,
    image_url=public_url,
)

generate_video auto-rewrites the model path from */text-to-video to */image-to-video whenever image_url is provided. The same approach works for video-to-video models — pass an mp4 URL instead.

Asset constraints (enforced by publish_asset.py)

  • Image: .jpg .jpeg .png .webp .gif .bmp, max 10 MB
  • Video: .mp4 .mov .webm .mkv .m4v, max 100 MB
  • Anything outside these is rejected before publish

3. One-time fal-assets public preview setup

Run this once per workspace. The preview keeps running across sessions.

# 3.1 ensure the asset folder exists with a placeholder index
import os, pathlib
pathlib.Path('output/fal_assets').mkdir(parents=True, exist_ok=True)
if not os.path.exists('output/fal_assets/index.html'):
    open('output/fal_assets/index.html', 'w').write(
        '<!doctype html><html><body><h1>fal asset host</h1></body></html>'
    )

# 3.2 start the preview
preview(action='serve', dir='output/fal_assets', title='fal-assets')

# 3.3 publish to a public URL
preview(action='publish', preview_id='<id from step 3.2>', slug='fal-assets', title='fal-assets')
# → public base: https://community.iamstarchild.com/<user_slug>-fal-assets/

After publish, the public base URL is reusable for every future image-to-video / video-to-video task. Files dropped into output/fal_assets/ become reachable as <base>/<filename> immediately — no re-publish needed.

Verify with:

curl -sI https://community.iamstarchild.com/<user_slug>-fal-assets/<filename>
# expect: HTTP/2 200, content-type: image/* or video/*

If preview(action='serve') returns No available ports in pool, ask the user which existing preview can be stopped to free a port — never silently kill one.


4. Model selection

TierModelCost / 5sNotes
budgetfal-ai/wan/v2.5/text-to-video$0.25Fastest, cheapest; good for prompt iteration
balancedalibaba/happy-horse/text-to-video$0.70Default; best lip-sync, most use cases
premiumbytedance/seedance-2.0/fast/text-to-video$1.20Best motion + camera direction
minibytedance/seedance-2.0/mini/text-to-video$0.36 (480p) / $0.77 (720p)Cheapest Seedance; resolution-tiered, no 1080p. Duration must be a string ("5", not 5 or "5s") — see gotcha below
premium-25bytedance/seedance-2.5/text-to-videotoken-basedSupports text-to-video, image-to-video, and reference-to-video. Requires resolution (480p/720p), aspect_ratio (six supported ratios), and integer duration from 4–30 seconds. Estimate with estimate_cost(..., aspect_ratio=...).
—xai/grok-imagine-video/v1.5/image-to-video$0.41 (480p) / $0.71 (720p) per 5simage-to-video ONLY (single required image_url, no image_urls); +$0.01 input-image surcharge included in estimate. ⚠️ resolution="1080p" is schema-valid upstream but has NO published price — the proxy rejects it 400 fail-closed
—fal-ai/kling-video/v3/turbo/standard/text-to-video$0.56 per 5sKling v3 Turbo Standard, flat $0.112/s; .../turbo/pro/... = $0.14/s ($0.70/5s); .../v3/4k/... = $0.42/s ($2.10/5s). i2v variants exist for all
—alibaba/happy-horse/v1.1/text-to-video$0.70 (720p) / $0.90 (1080p) per 5sv1.1 has its own 1080p tier $0.18/s (NOT the v1.0 2× rule); also /image-to-video, /reference-to-video

Use this skill in a project

Open any RiverX project, search the Skills panel for starchild-ai-agent/official-skills/video, and install it in one click.

Use this skill