video

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

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.

在Starchild上,所有视频生成请求均可使用此技能。
核心原则: 调用提供的脚本。请勿重新实现代理/计费/上传相关逻辑。

1. Text-to-video (most common)

1. 文本转视频(最常用)

python
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,
)
python
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/..."}

result -> {"success": True, "cost": 0.70, "video_url": "...", "local_path": "output/videos/..."}


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

`generate_video`会自动执行:提交任务 → 轮询状态 → 获取结果 → 将mp4文件下载至`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](output/videos/<filename>.mp4)
    — 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:
bash
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.

切勿直接将原始
video_url
(例如
https://*.fal.media/.../*.mp4
)提供给用户。
fal采用
Content-Security-Policy: sandbox; default-src 'none'
策略提供这些文件,这意味着:
  • 在浏览器中打开链接会显示空白页面(无法触发内嵌播放器)。
  • 通过
    <video>
    /
    <iframe>
    嵌入会被CSP阻止。
  • 不存在
    Content-Disposition: attachment
    头,因此浏览器不会自动下载文件。
  • URL侧的调整(查询参数、
    ?download=1
    等)无法解决此问题——只有修改服务器端头部才能解决,而我们无法控制fal的CDN。
唯一可靠的用户交付路径是已下载的本地文件
  1. 使用
    result["local_path"]
    (例如
    output/videos/xxx.mp4
    )——
    generate_video
    在成功时总会自动下载文件。
  2. 告知用户文件已保存至
    output/videos/<filename>
    ,可在工作区文件面板/文件浏览器中查看。
  3. 在Web渠道中,还可将文件内嵌到聊天中供用户预览:
    markdown
    ![video](output/videos/<filename>.mp4)
    (或链接为
    [video](output/videos/<filename>.mp4)
    ——工作区会使用正确的头部直接提供这些文件)。
  4. 在Telegram / 微信中:通过
    send_to_telegram(file_path="output/videos/...", message_type="video")
    send_to_wechat(file_path="output/videos/...", message_type="video")
    发送文件。
如果下载失败(
local_path
缺失)——可通过以下命令重新获取:
bash
curl -L -o output/videos/<filename>.mp4 "<video_url>"
然后交付本地路径。仍需注意切勿将原始fal URL作为主要交付内容提供给用户。

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

2. 图像转视频 / 视频转视频(参考资产)

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.
fal.ai需要参考资产为公开HTTPS URL。fal存储上传需要Serverless权限,而当前你的密钥不具备该权限。可靠的解决方案是通过已发布的Starchild预览暴露资产。

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)
    .
python
undefined
  1. 使用
    publish_asset.py
    将资产放入或复制到
    output/fal_assets/
    目录
  2. 确保名为
    fal-assets
    的预览已启动并发布
    (一次性设置,见第3节)。
  3. 构建公开URL,格式为
    <preview_base>/<filename>
  4. 调用
    generate_video(... image_url=public_url)
python
undefined

Step 1: publish a local image into the asset folder

步骤1:将本地图像发布到资产文件夹

exec(open('skills/video/publish_asset.py').read()) asset = publish_local('/path/to/your/photo.jpg')
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')

或:publish_from_url('https://example.com/photo.jpg')

filename = asset['filename']
filename = asset['filename']

Step 2: combine with the preview's public base URL (see §3)

步骤2:与预览的公开基础URL组合(见第3节)

public_url = f"https://community.iamstarchild.com/<user_slug>-fal-assets/{filename}"
public_url = f"https://community.iamstarchild.com/<user_slug>-fal-assets/{filename}"

Step 3: image-to-video

步骤3:图像转视频

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.
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, )

当提供`image_url`时,`generate_video`会自动将模型路径从`*/text-to-video`重写为`*/image-to-video`。相同方法适用于视频转视频模型——只需传入mp4 URL即可。

Asset constraints (enforced by
publish_asset.py
)

资产约束(由
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

  • 图像:
    .jpg .jpeg .png .webp .gif .bmp
    ,最大10 MB
  • 视频:
    .mp4 .mov .webm .mkv .m4v
    ,最大100 MB
  • 超出上述范围的内容会在发布前被拒绝

3. One-time
fal-assets
public preview setup

3.
fal-assets
公开预览的一次性设置

Run this once per workspace. The preview keeps running across sessions.
python
undefined
每个工作区只需运行一次。预览会在会话间持续运行。
python
undefined

3.1 ensure the asset folder exists with a placeholder index

3.1 确保资产文件夹存在并包含占位符索引文件

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>' )
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

3.2 启动预览

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

3.3 publish to a public URL

3.3 发布到公开URL

preview(action='publish', preview_id='<id from step 3.2>', slug='fal-assets', title='fal-assets')
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/

→ 公开基础URL: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:
```bash
curl -sI https://community.iamstarchild.com/<user_slug>-fal-assets/<filename>

发布后,公开基础URL可重复用于未来所有图像转视频/视频转视频任务。放入`output/fal_assets/`的文件会立即变为`<base>/<filename>`可访问状态——无需重新发布。

验证方法:
```bash
curl -sI https://community.iamstarchild.com/<user_slug>-fal-assets/<filename>

expect: HTTP/2 200, content-type: image/* or video/*

预期结果:HTTP/2 200,content-type: image/* 或 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.

---

如果`preview(action='serve')`返回`No available ports in pool`,请询问用户可以停止哪个现有预览以释放端口——切勿静默终止任何预览。

---

4. Model selection

4. 模型选择

TierModelCost / 5sNotes
budget
fal-ai/wan/v2.5/text-to-video
$0.25Fastest, cheapest; good for prompt iteration
balanced
alibaba/happy-horse/text-to-video
$0.70Default; best lip-sync, most use cases
premium
bytedance/seedance-2.0/fast/text-to-video
$1.20Best motion + camera direction
Override by passing the full model id to
generate_video(model=...)
. Image-to-video variants are auto-derived by replacing
text-to-video
with
image-to-video
.
Pricing details and model registry live in
generate_video.py::estimate_cost
.

层级模型每5秒成本说明
budget
fal-ai/wan/v2.5/text-to-video
$0.25速度最快、成本最低;适合提示词迭代
balanced
alibaba/happy-horse/text-to-video
$0.70默认模型;唇形同步效果最佳,适用于大多数场景
premium
bytedance/seedance-2.0/fast/text-to-video
$1.20运动效果与镜头调度最佳
可通过向
generate_video(model=...)
传入完整模型ID来覆盖默认选择。图像转视频变体可通过将
text-to-video
替换为
image-to-video
自动派生。
定价详情和模型注册表位于
generate_video.py::estimate_cost
中。

5. Polling an existing request

5. 轮询现有请求

python
exec(open('skills/video/poll_status.py').read())
result = poll_video("019ded6c-d871-7290-bbf1-ddc6993f8958")
Use this when an earlier
generate_video
call timed out or you only have a
request_id
.

python
exec(open('skills/video/poll_status.py').read())
result = poll_video("019ded6c-d871-7290-bbf1-ddc6993f8958")
当之前的
generate_video
调用超时或仅拥有
request_id
时,可使用此方法。

6. Provided scripts

6. 提供的脚本

  • generate_video.py
    — submit → poll → download. Handles text-to-video and image-to-video.
  • publish_asset.py
    — copy local files (or download remote URLs) into
    output/fal_assets/
    so they can be served by the
    fal-assets
    preview.
  • poll_status.py
    — resume polling by
    request_id
    , downloads the result on completion.

  • generate_video.py
    — 提交任务 → 轮询状态 → 下载结果。支持文本转视频和图像转视频。
  • publish_asset.py
    — 将本地文件(或下载远程URL)复制到
    output/fal_assets/
    目录,以便通过
    fal-assets
    预览提供服务。
  • poll_status.py
    — 通过
    request_id
    恢复轮询,完成后下载结果。

7. Troubleshooting

7. 故障排查

ProblemFix
image_url must be a public HTTP(S) URL
Use
publish_asset.py
+
fal-assets
preview, then pass the public URL
No available ports in pool
(preview serve)
Ask the user which preview to stop; do not auto-kill
downstream_service_error
after
COMPLETED
Reference asset host failed mid-render — re-encode/resize to 16:9, re-publish, retry
HTTP 402 insufficient_credits
Top up balance; cost is pre-charged on submit
HTTP 403 endpoint_not_allowed
sc-proxy only allows approved fal video endpoints; pick one from the model table
Generation
FAILED
upstream
Shorten prompt, drop unusual tokens, retry once before changing model
Job stuck
IN_PROGRESS
>15 min
Save
request_id
, resume later with
poll_status.py
User reports the fal.media link "shows nothing" / "blank page"Expected — fal serves with
CSP: sandbox; default-src 'none'
. Deliver the local file at
result["local_path"]
instead of the raw URL (see §1).

问题解决方法
image_url must be a public HTTP(S) URL
使用
publish_asset.py
+
fal-assets
预览,然后传入公开URL
No available ports in pool
(预览启动)
询问用户停止哪个预览;请勿自动终止
downstream_service_error
COMPLETED
之后出现
参考资产主机在渲染中途故障——重新编码/调整为16:9比例,重新发布后重试
HTTP 402 insufficient_credits
充值余额;提交任务时会预先扣费
HTTP 403 endpoint_not_allowed
sc-proxy仅允许已批准的fal视频端点;从模型表中选择一个
上游生成
FAILED
缩短提示词,移除特殊令牌,更换模型前重试一次
任务卡在
IN_PROGRESS
状态超过15分钟
保存
request_id
,稍后使用
poll_status.py
恢复轮询
用户反馈fal.media链接“显示空白”/“空白页面”此为预期情况——fal采用
CSP: sandbox; default-src 'none'
策略。请交付
result["local_path"]
对应的本地文件,而非原始URL(见第1节)。

8. Infrastructure (reference)

8. 基础设施(参考)

  • Caller →
    sc-proxy
    queue.fal.run
    (and
    api.fal.ai
    ) → fal model providers
  • All requests must include
    Authorization: Key fake-falai-key-12345
    (proxy injects the real
    FAL_KEY
    )
  • Pre-charge happens at submit. Poll/result calls are free.
  • Allowed endpoints: video text-to-video / image-to-video / video-to-video / edit-video for the registered models. Anything else returns
    403 endpoint_not_allowed
    .
  • Final mp4 lives at
    https://*.fal.media/...
    — public CDN, no auth needed for download.

  • 调用方 →
    sc-proxy
    queue.fal.run
    (以及
    api.fal.ai
    )→ fal模型提供商
  • 所有请求必须包含
    Authorization: Key fake-falai-key-12345
    (代理会注入真实的
    FAL_KEY
  • 预先扣费在提交任务时发生。轮询/获取结果的调用免费。
  • 允许的端点:已注册模型的视频文本转视频/图像转视频/视频转视频/编辑视频接口。其他任何请求都会返回
    403 endpoint_not_allowed
  • 最终mp4文件存储在
    https://*.fal.media/...
    ——公开CDN,下载无需认证。

9. Maintenance

9. 维护

  • Adding a new model → register price in
    generate_video.py::estimate_cost
    and in
    transparent-proxy/apis/falai.py::_VIDEO_PRICING
    .
  • Asset hosting via fal storage upload is intentionally not used in this skill: the production
    FAL_KEY
    lacks Serverless permission. Keep using the preview-based approach until that changes.
  • 添加新模型 → 在
    generate_video.py::estimate_cost
    transparent-proxy/apis/falai.py::_VIDEO_PRICING
    中注册价格。
  • 本技能故意使用fal存储上传来托管资产:生产环境的
    FAL_KEY
    缺少Serverless权限。在权限变更前,请继续使用基于预览的方案。