时间轴视频
一个长视频模型可以持续拍摄30秒,只要提示词精确描述了每一秒发生的事情。这个技能就是脚本层:格式、让视频落地的手法,以及 scripts/timeline_video.py——它负责检查脚本、报价、通过OpenRouter的异步视频API渲染,并生成一个接触表供回顾。所需环境:Python 3.8+ 标准库;ffmpeg 仅用于接触表。
六个模块
脚本是一个Markdown文件:可选的前置元数据,然后按顺序包含以下六个模块。前置元数据之后的所有内容将作为提示词逐字发送。
---
duration: 30
aspect: 16:9
resolution: 720p
model: bytedance/seedance-2.5
---
[CHARACTER] 角色:确切描述——年龄、面容、头发、眼镜、每一件衣物、姿态、手中物品、车辆或道具及其颜色、所在位置。以锁定语句结尾:“在全部30秒内保持面部、头发、服装和<道具>一致。”
[STYLE] 是否真人实拍、“一个不间断的长镜头”、宽高比、基于景深的焦点、一天中的时间及其光线、以命名颜色呈现的调色板、纹理、一个持续的小动作(如风中头发)、喜剧基调,以及禁止剪辑、冻结帧和慢动作。
[AUDIO] 环境背景音作为一系列具体声音的列表。然后按时间点给出提示:“0.8秒:一声清脆的消息提示音。”“1.2–4.0秒:<谁>,画外音,<如何发声>:“<确切台词>”。”最后描述随着画面变化声音所起的作用。
[TIMELINE]
0.0–1.0秒 — <构图> <动作> <一个细节>。
1.0–4.0秒 — ...
... (时间段首尾相接,从0到总时长,无间隙)
[CAMERA RULES] 连续法则:每段一个不间断的移动,缓入缓出,地平线保持水平,主体靠近中心,每段比前一段更远,哪条引导线保持位置。
[NEGATIVE] 禁止剪辑或黑帧,禁止其他人,禁止文字、字幕、副标题或标志……
templates/script.md 是一个空白模板,可供复制;examples/the-sandbar.md 是一个完整的30秒脚本示例。
让视频成功的关键
- 一个前提,四个节拍。 平静 → 一个你听到的触发信号(提示音,接着是一个语音留言提出请求)→ 特写镜头下的面无表情反应 → 揭示。在拉远形态中,揭示就是笑点:每次拉远都显示出从当前位置看这个请求有多么不可能。
- 第一秒就要展示人物。 没有建立镜头;滚动停在脸上。
- 在文字中锁定身份。 一次性命名所有可见属性,然后加上“在全部N秒内保持一致”的语句。漂移是破坏长镜头的元凶。
- 一种饱和的强调色。 降低调色板的饱和度,只给主体的道具赋予唯一强烈的颜色,这样即使在最后一秒道具只有三像素宽时,眼睛也能找到它。
- 逐步升级揭示。 每段移动比前一段更远,每个时间段都要指明在该尺度下哪些东西变得可见——进入方式、离开方式、地平线。地理讲述故事。
- 音频与镜头同步。 开始时紧密而贴近,然后只有风声,随着镜头拉远而变得更广阔、更空旷。
- 把控语音的节奏。 大约每秒2.5个单词:一个2.8秒的时间窗口大约包含七个单词。
- 最后三分之一保持安静。 缓慢、广阔、空旷——这是后期添加画外音的地方。
- 永远不要让模型生成文字、标志或品牌标识。 它会扭曲这些内容,并且除非负面提示禁止,否则它还会在车辆上绘制徽标。之后用你自己的字体,在安静广阔的画面上添加文字。
除拉远之外的其他形态:推近(笑点是一个细节)、跟随(长距离行走压缩时间)、环绕(世界围绕静止的主体变化)。同样六个模块;运镜规则不同。
运行
S=<此技能目录>/scripts/timeline_video.py
python3 $S check film.md # 解析模块,检查时间,打印节拍
python3 $S models --model bytedance/seedance-2.5 # 时长、分辨率、宽高比、音频、价格
python3 $S render film.md -o out/ --key-file ~/keys/openrouter.key # 报价、提交、轮询、下载
python3 $S sheet out/film.mp4 film.md # 每拍一帧 → out/film_beats.jpg
| 标志(render) | 作用 |
|---|---|
-o DIR | MP4及其附属文件的输出目录。文件名取自脚本名。 |
--model, --duration, --resolution, --aspect | 覆盖前置元数据。每个选项在发送前都会对照模型已发布的能力进行检查。 |
--seed N | 传递一个种子(仅当模型支持时有效)。 |
--no-audio | 请求生成无声视频。默认对于支持音频的模型,音频是开启的。 |
--key-file F | 从文件中读取OpenRouter密钥。否则读取环境变量 OPENROUTER_API_KEY。密钥不会被打印或保存。 |
--dry-run | 仅检查和报价。 |
成本。 render 在提交前会打印价格。按秒计费的模型给出的是精确价格。Seedance按视频令牌计价,OpenRouter未公布换算方式,因此其数值标注为估算值(令牌数 ≈ 宽度 × 高度 × 24 fps × 秒数 ÷ 1024)。经过实际任务验证:30秒720p视频估算为6.93美元,实际收费6.94美元。实际费用始终记录在附属文件的 usage.cost 中。先渲染一个,查看费用,再决定是否重新生成。
产出物: <名称>.mp4 和 <名称>.json —— 模型、参数、提示词及其SHA-256哈希、任务ID和生成ID、时间信息以及 usage 块。请保持文件在一起;附属文件是复现某个片段的方式。
使用前的检查
- 使用
ffprobe检查文件:确保时长与你要求的一致,并且如果你要求了音频,要确认存在音频流。 - 使用
sheet生成接触表,然后检查每一拍:面部、头发和服装在整个过程中一致;强调色保持;揭示逐步升级;没有文字、标志或额外人物出现。 - 听:触发信号准时出现,且语音说出了确切的台词。
一个失败的节拍意味着需要重新生成(使用新种子)或修改脚本——通常是将一个模糊的时间窗口具体化。
错误排查
| 退出码 | 含义 |
|---|---|
0 | 完成 |
1 | OpenRouter拒绝请求,或任务结束状态为 failed、cancelled 或 expired;其错误信息会原样打印 |
2 | 脚本或参数错误(缺少模块、时间线有间隙、模型不支持该时长等) |
4 | 未找到密钥 |
视频任务不属于零数据保留:提供商会短暂保留输出以供下载。
致谢
本格式遵循 @iamneubert 分享的Seedance提示词及其对一则病毒式单镜广告的解析(https://x.com/iamneubert/status/2099199895039336459)。本技能不包含该提示词或视频的任何内容。