{"id":"6a6a2edc-32d9-4aa3-a21d-acc55ee3f7ad","entityType":"agent","slug":"clawhub-hitjcl-ai-short-film-producer","name":"AI短剧制作助手 | AI Short Film Producer","canonicalUrl":"https://www.xpersona.co/agent/clawhub-hitjcl-ai-short-film-producer","canonicalPath":"/agent/clawhub-hitjcl-ai-short-film-producer","generatedAt":"2026-10-10T08:31:03.033Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-09T07:37:12.770Z","emptyReason":null},"description":"AI短剧制作助手 | AI Short Film Producer — 低成本AI短剧/短片全流程制作技能。使用Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成。适用于从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动... Skill: AI短剧制作助手 | AI Short Film Producer Owner: hitjcl Summary: AI短剧制作助手 | AI Short Film Producer — 低成本AI短剧/短片全流程制作技能。使用Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成。适用于从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动... Tags: ai:1.0.3, film:1.0.3, latest:1.0.3, production:1.0.3, video:1.0.3 Version history: v1.0.3 | 2026-04-30T11:23:17.316Z | user 标题改为中英文；移除外部链接和具体定价避免安全误报 v1.0.2 | 2026-04-30T09:50:26.768Z | use","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 3.6K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s17fcraf4fka3zh3rs6gjkpky983gfj1:ai-short-film-producer","sourceUrl":"https://clawhub.ai/hitjcl/ai-short-film-producer","homepage":"https://clawhub.ai/hitjcl/skills/ai-short-film-producer","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/hitjcl/ai-short-film-producer","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/hitjcl/skills/ai-short-film-producer","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":71,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"AI短剧制作助手 | AI Short Film Producer — 低成本AI短剧/短片全流程制作技能。使用Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成。适用于从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动..."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T07:37:12.770Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T07:37:12.770Z","emptyReason":null},"stars":null,"forks":null,"downloads":3561,"packageName":null,"latestVersion":"1.0.3","tractionLabel":"3.6K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T07:37:12.742Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T07:37:12.770Z","lastCrawledAt":"2026-10-09T07:37:12.742Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T07:37:12.742Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.3","createdAt":"2026-04-30T11:23:17.316Z","changelog":"标题改为中英文；移除外部链接和具体定价避免安全误报","fileCount":5,"zipByteSize":17882},{"version":"1.0.2","createdAt":"2026-04-30T09:50:26.768Z","changelog":"安全扫描修复：移除所有凭证和推广链接","fileCount":4,"zipByteSize":16416},{"version":"1.0.1","createdAt":"2026-04-30T09:41:29.858Z","changelog":"移除敏感信息：API凭证和推广链接","fileCount":4,"zipByteSize":16416},{"version":"1.0.0","createdAt":"2026-04-30T09:36:45.422Z","changelog":"AI短剧/短片全流程低成本自动化制作技能首发版。 - 支持从分镜脚本到成片的全流程自动化：分镜、AI视频生成、TTS配音、音画同步剪辑、字幕、合成及成本核算。 - 视频镜头与配音批量生成，自动循环补帧，确保音画同步，显著提升叙事流畅度。 - 兼容FFmpeg+Python本地高效合成、字幕自动生成与叠加。 - 成本透明，每部短片可控制在¥30-50之间，适宜零起点用户。 - 提供详细SOP、踩坑经验、成本估算及实战案例（如三体EP1）。","fileCount":4,"zipByteSize":16697}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17fcraf4fka3zh3rs6gjkpky983gfj1:ai-short-film-producer","setupComplexity":"low","setupSteps":["Setup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hitjcl-ai-short-film-producer/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hitjcl-ai-short-film-producer/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hitjcl-ai-short-film-producer/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-hitjcl-ai-short-film-producer/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-hitjcl-ai-short-film-producer/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-hitjcl-ai-short-film-producer/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T08:31:03.030Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hitjcl-ai-short-film-producer/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hitjcl-ai-short-film-producer/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hitjcl-ai-short-film-producer/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hitjcl-ai-short-film-producer/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-09T07:37:12.770Z","emptyReason":null},"readme":"Skill: AI短剧制作助手 | AI Short Film Producer\n\nOwner: hitjcl\n\nSummary: AI短剧制作助手 | AI Short Film Producer — 低成本AI短剧/短片全流程制作技能。使用Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成。适用于从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动...\n\nTags: ai:1.0.3, film:1.0.3, latest:1.0.3, production:1.0.3, video:1.0.3\n\nVersion history:\n\nv1.0.3 | 2026-04-30T11:23:17.316Z | user\n\n标题改为中英文；移除外部链接和具体定价避免安全误报\n\nv1.0.2 | 2026-04-30T09:50:26.768Z | user\n\n安全扫描修复：移除所有凭证和推广链接\n\nv1.0.1 | 2026-04-30T09:41:29.858Z | user\n\n移除敏感信息：API凭证和推广链接\n\nv1.0.0 | 2026-04-30T09:36:45.422Z | auto\n\nAI短剧/短片全流程低成本自动化制作技能首发版。\n\n- 支持从分镜脚本到成片的全流程自动化：分镜、AI视频生成、TTS配音、音画同步剪辑、字幕、合成及成本核算。\n- 视频镜头与配音批量生成，自动循环补帧，确保音画同步，显著提升叙事流畅度。\n- 兼容FFmpeg+Python本地高效合成、字幕自动生成与叠加。\n- 成本透明，每部短片可控制在¥30-50之间，适宜零起点用户。\n- 提供详细SOP、踩坑经验、成本估算及实战案例（如三体EP1）。\n\nArchive index:\n\nArchive v1.0.3: 5 files, 17882 bytes\n\nFiles: references/production_workflow.md (15821b), references/sucuang_api.md (5235b), skill-card.md (2825b), SKILL.md (12728b), _meta.json (141b)\n\nFile v1.0.3:SKILL.md\n\n---\nname: ai-short-film-producer\ndescription: AI短剧制作助手 | AI Short Film Producer — 低成本AI短剧/短片全流程制作技能。使用Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成。适用于从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动剪辑、字幕叠加、最终合成、成本核算的全套SOP。\n---\n\n# AI短剧制作助手 | AI Short Film Producer\n\n## 概述\n\n本Skill提供一套完整的**低成本AI短剧制作流程**，从脚本创作到最终成片，总成本仅需**¥30-50/部**（128秒短片）。核心思路：用AI API生成素材 → 本地FFmpeg合成 → WorkBuddy编排调度。\n\n**适用场景：**\n- 用户说\"帮我做一个短片/短剧/预告片\"\n- 用户说\"把这段文案做成视频\"\n- 用户说\"生成一个XX题材的短视频\"\n- 用户需要从零到一完成AI视频制作\n\n**核心成本优势：**\n- 视频生成：Grok Imagine（速创API，按秒计费）\n- 配音生成：TTS（速创API，按字计费）\n- 合成剪辑：本地FFmpeg免费\n- AI编排：WorkBuddy Lite版\n\n---\n\n## 制作流程总览\n\n```\nStep 1: 脚本创作\n  ├── 确定主题/时长/风格\n  ├── 编写分镜脚本（镜头×台词×角色）\n  └── 输出：分镜表 + TTS文本清单\n\nStep 2: 视频镜头生成\n  ├── 调用速创API Grok Imagine\n  ├── 25个镜头批量异步生成\n  └── 输出：ep1_shots/*.mp4\n\nStep 3: TTS配音生成\n  ├── 调用速创API audio_tts\n  ├── 多角色多音色\n  └── 输出：ep1_tts/*.mp3\n\nStep 4: 音频驱动剪辑\n  ├── 逐段按TTS时长裁剪/循环镜头\n  ├── 短镜头自动stream_loop填充\n  └── 输出：分段seg_*.mp4\n\nStep 5: 字幕生成\n  ├── Python Pillow生成透明PNG字幕\n  ├── FFmpeg overlay叠加（因FFmpeg 8.x无drawtext）\n  └── 输出：带字幕的分段视频\n\nStep 6: 最终合成\n  ├── concat拼接25段视频\n  ├── concat拼接25段音频\n  ├── 音视频合并\n  └── 输出：最终成片.mp4\n\nStep 7: 素材导出\n  ├── 结构化桌面文件夹\n  ├── 矩阵表 + JSON\n  └── 成本核算\n```\n\n---\n\n## 详细步骤\n\n### Step 1: 脚本创作\n\n**输入：** 用户需求（主题、风格、时长、参考素材）\n**输出：** 分镜脚本文档 + TTS台词清单\n\n**工作流程：**\n1. 与用户确认主题方向（科幻/悬疑/科普/剧情等）\n2. 编写分镜脚本，包含：\n   - 镜头编号、画面描述、时长\n   - 配音台词、角色分配、音色选择\n   - 音效说明\n3. 输出TTS台词清单（25段以内，每段2-20字最佳）\n4. 角色音色分配表：\n\n| 角色类型 | 推荐音色ID | 说明 |\n|---------|-----------|------|\n| 旁白/叙述者 | male-qn-jingying | 精英青年男声，通用 |\n| 男主角 | male-qn-jingying | 精英青年男声 |\n| 霸道/硬汉 | male-qn-badao | 霸道男声 |\n| 反派/俊朗 | junlang_nanyou | 俊朗男声 |\n| 成熟女性 | female-chengshu | 成熟女声 |\n| 少女 | female-shaonv | 少女音 |\n| 研究员/学生 | male-qn-daxuesheng | 大学生男声 |\n| 醇厚长辈 | male-chunhou | 醇厚男声 |\n\n### Step 2: 视频镜头生成（速创API Grok Imagine）\n\n**API平台：** 速创API（详见 references/sucuang_api.md）\n**模型：** Grok Imagine（xAI Aurora引擎）\n**价格：** 按秒计费（具体见平台）\n\n**API调用方式：**\n- 鉴权：Authorization Header 传API Key（不带Bearer前缀）\n- 接口：POST /api/async/video/grok_imagine\n- 参数格式：扁平JSON\n- 结果查询：GET /api/async/detail?id=xxx（轮询直到status=2）\n\n**批量生成策略：**\n1. 25个镜头同时提交（用ThreadPoolExecutor）\n2. 每个镜头约10秒，生成耗时约30-60秒\n3. 失败自动重试（平均重试3次）\n4. 注意：Sora2接口已不可用（持续400错误），全部使用Grok Imagine\n\n**Prompt编写要点：**\n- 英文Prompt效果更稳定\n- 包含：场景描述、光线、构图、镜头运动\n- 示例：`\"Deep space, Milky Way galaxy slowly rotating, cinematic wide shot, photorealistic, 4K quality\"`\n\n### Step 3: TTS配音生成（速创API audio_tts）\n\n**API接口：** POST /api/async/audio_tts\n**价格：** 按字计费（具体见平台）\n**参数格式（重要）：** 扁平JSON，不要嵌套\n\n```json\n{\n  \"text\": \"台词内容\",\n  \"voice_id\": \"male-qn-jingying\",\n  \"speed\": 1.0\n}\n```\n\n**注意事项（踩坑经验）：**\n- ❌ 不要传 format 参数（会报500\"存在未绑定的参数\"）\n- ❌ 不要嵌套成 `{\"model\":\"audio_tts\",\"params\":{...}}`\n- ✅ 状态码判断：status=2 完成，status=0/1 处理中\n- ⚠️ 部分任务会卡住（status一直=0），重试可换IP节点\n- ✅ 返回tar包，需解压获取mp3\n\n### Step 4: 音频驱动剪辑（核心节奏控制）\n\n**核心理念：** 画面长度由语音旁白决定，而非固定时长。先录制/生成TTS配音，再让每段视频精确匹配对应配音的时长。这样保证音画天然同步，且节奏由配音自然驱动。\n\n#### 4.1 节奏控制逻辑\n\n```\n每段（镜头, TTS）的处理流程：\n\n1. 获取TTS音频实际时长 tts_dur（用ffprobe精确到毫秒）\n2. 获取源视频时长 src_dur\n3. 对比决策：\n   ├── src_dur >= tts_dur + 0.5s  → 直接裁剪到tts_dur（视频多出的部分舍弃）\n   ├── src_dur ≈ tts_dur（差<0.5s）→ 直接裁剪，不做额外处理\n   └── src_dur < tts_dur           → stream_loop循环播放填满tts_dur\n4. 输出：seg_NNN.mp4（时长=tts_dur，精确匹配配音）\n```\n\n**为什么用\"音频驱动\"而非\"视频驱动\"：**\n- 传统剪辑：先定视频长度，再往里塞配音 → 配音节奏被画面绑架\n- 音频驱动：先定配音节奏，再裁剪画面适配 → 叙事节奏由台词自然决定\n- 效果：观众听到的每句话都有对应的画面时长，不会出现\"话没说完画面就切了\"\n\n#### 4.2 短镜头循环填充（stream_loop）\n\n当源视频时长不够时，用FFmpeg的stream_loop让视频循环播放：\n\n```bash\n# 循环播放直到填满tts_dur\n/opt/homebrew/bin/ffmpeg -y -stream_loop -1 -i shot.mp4 -t {tts_dur} -c:v libx264 -preset fast seg.mp4\n```\n\n**实战经验（三体EP1）：**\n- 25个镜头中有3个需要循环填充\n- 最大修复：pan_han_02火鸡演讲（源视频10s → TTS需要19s，循环补9s）\n- 循环填充的视觉重复感在1-2次循环内不明显，超过3次建议换镜头\n\n#### 4.3 逐段精确裁剪避免累积漂移\n\n```python\n# 关键：每段独立裁剪，不整体缩放\ncumulative = 0.0\nfor i, (tts_file, shot_file) in enumerate(segments):\n    tts_dur = get_duration(tts_file)  # ffprobe获取\n    # 精确裁剪到tts_dur，不依赖前一段的结束时间\n    trim_video(shot_file, tts_dur, f\"seg_{i:03d}.mp4\")\n    cumulative += tts_dur\n\n# 最终验证：所有seg时长之和 ≈ audio_concat时长 ≈ 最终成片时长\n```\n\n**FFmpeg路径（Mac mini M4）：** `/opt/homebrew/bin/ffmpeg`\n\n**已知限制：**\n- FFmpeg 8.x 未编译drawtext/libass/freetype滤镜 → 不能直接加字幕\n- anullsrc语法用 `cl=stereo` 而非 `c=stereo`\n- shell转义用Python subprocess list模式避免zsh问题\n\n### Step 5: 字幕生成\n\n**方案：** Pillow生成透明PNG → FFmpeg overlay叠加\n\n```python\nfrom PIL import Image, ImageDraw, ImageFont\n\n# 创建透明PNG\nimg = Image.new('RGBA', (1920, 160), (0,0,0,0))\ndraw = ImageDraw.Draw(img)\nfont = ImageFont.truetype('/System/Library/Fonts/PingFang.ttc', 48)\n\n# 白色大字 + 黑色描边\ndraw.text((960, 80), \"台词文本\", fill='white', font=font, \n          anchor='mm', stroke_width=3, stroke_fill='black')\n\n# FFmpeg overlay叠加\nffmpeg -i seg.mp4 -i sub.png -filter_complex \"overlay=0:H-h\" output.mp4\n```\n\n**字幕设计规范：**\n- 底部居中，距底部约60px\n- 白色大字 + 3px黑色描边\n- 字号48-56px（PingFang SC字体）\n- 可加角色标签（如\"旁白：\"、\"汪淼：\"）\n\n### Step 6: 最终合成\n\n**拼接视频：**\n```bash\n# 生成file list\nfor f in seg_*.mp4; do echo \"file '$f'\" >> video_list.txt; done\nffmpeg -f concat -safe 0 -i video_list.txt -c copy video_concat.mp4\n```\n\n**拼接音频：**\n```bash\nfor f in audio_*.mp3; do echo \"file '$f'\" >> audio_list.txt; done\nffmpeg -f concat -safe 0 -i audio_list.txt -c copy audio_concat.aac\n```\n\n**音视频合并：**\n```bash\nffmpeg -i video_concat.mp4 -i audio_concat.aac -c:v copy -c:a aac final.mp4\n```\n\n### Step 7: 素材导出与成本核算\n\n**桌面文件夹结构：**\n```\n~/Desktop/项目名称/\n├── 01_字幕/     → 字幕PNG文件\n├── 02_配音/     → TTS音频MP3\n├── 03_主图/     → 镜头缩略图JPG\n├── 04_视频/     → 分段视频MP4\n├── 05_矩阵表/   → 矩阵表.html + 素材结构.json\n└── 最终成片.mp4\n```\n\n**成本核算模板：**\n\n| 项目 | 计算方式 | 说明 |\n|------|---------|------|\n| Grok Imagine视频 | 总秒数 × 重试次数 × 单价 | 按秒计费 |\n| TTS配音 | 总字数 × 单价 | 按字计费 |\n| WorkBuddy算力 | 对话轮次 × 单价 | 按轮计费 |\n| 硬件折旧 | Mac mini ¥3,999/3年寿命 | ¥3.65/天 |\n| 电费 | 16h × 65W × ¥0.6/度 | ¥0.62/天 |\n\n---\n\n## 速创API平台速查\n\n**平台地址：** 详见 references/sucuang_api.md\n**文档中心：** 详见 references/sucuang_api.md\n\n**常用模型及价格：**\n\n| 模型/接口 | 价格 | 说明 |\n|-----------|------|------|\n| Grok Imagine 视频生成 | 按秒计费 | 文生视频/图生视频，6-15秒 |\n| audio_tts 配音 | 按字计费 | 多音色TTS |\n| video_digital_humans 数字人 | 按次计费 | 需公网音频URL+视频URL |\n| Sora2（已弃用） | — | 持续400错误，不可用 |\n\n**API Key传递：**\n- ✅ Authorization Header（推荐，不带Bearer前缀）\n- ❌ URL参数 ?key=xxx（会返回403）\n\n---\n\n## 三体EP1实战参考\n\n**项目规模：** 25个镜头，127秒成片，8个角色\n**总成本：** ¥44.17（含重试+硬件折旧）\n**工具链：** Grok Imagine × 25 + TTS × 25 + FFmpeg + Python Pillow\n**迭代版本：** v5min → v6 → v7 → v7.1 → v8（5个版本迭代）\n\n**关键经验：**\n1. Sora2不可用，全部切Grok Imagine\n2. 源视频短于TTS时用stream_loop循环填充\n3. FFmpeg 8.x无drawtext，用Pillow生成PNG替代\n4. TTS部分任务卡住需重试\n5. 逐段精确裁剪避免累积漂移\n\n---\n\n## 专业审核与迭代流程\n\nAI生成的第一版通常不是最终版。必须经过\"制作→审核→修改\"的迭代循环才能达到交付标准。\n\n### 审核维度\n\n| 维度 | 检查内容 | 常见问题 |\n|------|---------|---------|\n| **音画同步** | 画面内容是否匹配配音台词 | 角色A说话但画面是角色B |\n| **时长匹配** | 每段视频是否完整覆盖TTS | 短镜头被截断，话没说完画面就切 |\n| **视觉重复** | 循环播放是否超过3次 | 火鸡演讲循环9s，观众能看出重复 |\n| **字幕准确** | 字幕文本是否与TTS一致 | 错别字、标点错误 |\n| **节奏感** | 整体叙事节奏是否流畅 | 某段太长拖沓，某段太短仓促 |\n| **画面质量** | 是否有明显AI生成瑕疵 | 人物变形、闪烁、分辨率低 |\n\n### 迭代流程\n\n```\nV1（初版合成）\n  ↓\n专业审核（逐段检查以上6个维度）\n  ↓\n问题清单 → 按严重程度排序\n  ├── P0（必须修）：音画不匹配、字幕错误、画面截断\n  ├── P1（建议修）：节奏拖沓、视觉重复感强\n  └── P2（可优化）：画面质量、色调统一\n  ↓\nV2（修复P0问题）\n  ↓\n再次审核\n  ↓\nV3...（逐轮修复，直到P0=0、P1≤2）\n  ↓\n最终交付\n```\n\n### 实战案例：三体EP1迭代记录\n\n| 版本 | 问题 | 修复方案 |\n|------|------|---------|\n| v5min | 252秒成片，但TTS只有127秒，大量空白 | 重新按TTS时长裁剪 |\n| v6 | 音频驱动剪辑，但3个短镜头被截断 | 修复中 |\n| v7 | 短镜头截断（火鸡演讲缺9s） | stream_loop循环填充 |\n| v7.1 | 循环修复完成，但无字幕 | 加字幕 |\n| v8 | 字幕+音画同步修复+矩阵表 | ✅ 最终交付 |\n\n**审核工具：**\n- 逐段对比：`ffprobe` 获取每段TTS和视频的精确时长\n- 偏差检查：每段TTS vs 视频时长差 > 0.5s 即标记为问题段\n- 画面检查：播放时逐段确认画面内容与台词匹配\n\n---\n\n## 资源文件\n\n### references/\n- `sucuang_api.md` — 速创API完整接口文档和踩坑经验\n- `production_workflow.md` — 制作流程详细参考\n\n### scripts/\n- （按需添加：批量提交脚本、合成脚本模板等）\n\n### assets/\n- （按需添加：字幕模板、片头片尾素材等）\n\nFile v1.0.3:_meta.json\n\n{\n  \"ownerId\": \"kn703gwc11aqnnaatk69f339d9822e08\",\n  \"slug\": \"ai-short-film-producer\",\n  \"version\": \"1.0.3\",\n  \"publishedAt\": 1777548197316\n}\n\nFile v1.0.3:references/production_workflow.md\n\n# AI短剧制作流程详细参考\n\n## 一、项目启动\n\n### 需求确认\n与用户确认以下信息：\n1. **主题**：科幻/悬疑/科普/剧情/搞笑/教育等\n2. **风格**：写实/动画/赛博朋克/古风等\n3. **时长**：30秒/60秒/2分钟/5分钟\n4. **角色**：需要几个角色？是否有特定音色要求？\n5. **参考素材**：用户是否提供文案/图片/参考视频？\n\n### 脚本模板\n\n```markdown\n# 项目名称 · 分镜脚本\n\n## 总览\n- 总时长：XX秒\n- 镜头数：XX个\n- 角色数：XX个\n\n## 分镜表\n| # | 镜头ID | 画面描述 | 配音台词 | 角色 | 音色 | 时长 |\n|---|--------|---------|---------|------|------|------|\n| 1 | shot01_xxx | 画面描述 | 台词内容 | 角色名 | 音色ID | 10s |\n| 2 | shot02_xxx | 画面描述 | 台词内容 | 角色名 | 音色ID | 10s |\n```\n\n---\n\n## 二、视频生成\n\n### Grok Imagine Prompt编写指南\n\n**结构模板：**\n```\n[场景描述], [主体描述], [光线/氛围], [构图/镜头运动], [风格关键词]\n```\n\n**示例：**\n```\n\"Deep space, Milky Way galaxy slowly rotating across a star-filled cosmos,\ncountless stars twinkling, nebulae in deep blue and purple hues,\ncinematic wide shot, photorealistic, 4K quality, slow gentle rotation\"\n```\n\n**各类型场景Prompt关键词：**\n\n| 场景类型 | 关键词 |\n|---------|--------|\n| 太空/宇宙 | deep space, stars, nebula, galaxy, cosmic, celestial |\n| 城市/街头 | city street, urban, bustling, modern, buildings |\n| 室内/会议室 | conference room, modern, screens, professional |\n| 人物特写 | close-up, portrait, expression, emotion, cinematic lighting |\n| 自然/风景 | landscape, mountains, ocean, sunset, cinematic |\n| 科技/实验室 | laboratory, technology, screens, equipment, futuristic |\n\n### 批量提交策略\n\n1. 25个镜头同时提交到API\n2. 使用ThreadPoolExecutor(max_workers=10)\n3. 每5秒轮询一次结果\n4. 失败自动重试（最多5次）\n5. 下载后检查文件完整性（ffprobe验证时长）\n\n---\n\n## 三、TTS配音生成\n\n### 多角色音色分配策略\n\n| 角色数量 | 分配策略 |\n|---------|---------|\n| 1-2个角色 | 旁白用jingying，对话角色用对应音色 |\n| 3-5个角色 | 主要角色各分配独立音色，次要角色复用 |\n| 6-10个角色 | 核心角色独立音色，路人/群演用通用音色 |\n\n### 台词字数控制\n- 每段TTS建议2-20字（太长影响听感）\n- 10秒镜头配2-4秒台词最合适\n- 留白时间给观众消化内容\n\n---\n\n## 四、音频驱动剪辑（核心节奏控制）\n\n### 核心理念\n\n**音频驱动剪辑 = 画面长度由语音旁白决定，而非固定时长。**\n\n传统剪辑思维是\"先定视频长度，再往里塞配音\"，结果配音节奏被画面绑架。音频驱动反过来——先录制TTS配音，再让每段视频精确匹配对应配音的时长。这样：\n- 观众听到的每句话都有完整的画面时长\n- 叙事节奏由台词自然驱动\n- 不会出现\"话没说完画面就切了\"\n\n### 核心算法\n\n```\n对于每一段（镜头, TTS）：\n  1. 获取TTS音频时长 tts_dur（ffprobe精确到毫秒）\n  2. 获取源视频时长 src_dur\n  3. 对比决策：\n     ├── src_dur >= tts_dur + 0.5s  → 直接裁剪到tts_dur\n     ├── src_dur ≈ tts_dur（差<0.5s）→ 直接裁剪\n     └── src_dur < tts_dur           → stream_loop循环填充\n  4. 输出：seg_NNN.mp4（时长精确=tts_dur）\n```\n\n### 逐段精确裁剪（避免累积漂移）\n\n```python\nimport subprocess\nfrom pathlib import Path\n\nFFPROBE = '/opt/homebrew/bin/ffprobe'\nFFMPEG = '/opt/homebrew/bin/ffmpeg'\n\ndef get_duration(filepath):\n    \"\"\"获取媒体文件精确时长\"\"\"\n    result = subprocess.run(\n        [FFPROBE, '-v', 'quiet', '-show_entries', 'format=duration',\n         '-of', 'csv=p=0', str(filepath)],\n        capture_output=True, text=True\n    )\n    return float(result.stdout.strip())\n\ndef process_segment(tts_file, shot_file, output_file):\n    \"\"\"处理单段：按TTS时长裁剪/循环视频\"\"\"\n    tts_dur = get_duration(tts_file)\n    src_dur = get_duration(shot_file)\n    \n    cmd = [FFMPEG, '-y']\n    \n    if src_dur >= tts_dur:\n        # 视频够长，直接裁剪\n        cmd.extend(['-t', str(tts_dur), '-i', str(shot_file)])\n    else:\n        # 视频不够长，循环填充\n        cmd.extend(['-stream_loop', '-1', '-i', str(shot_file),\n                     '-t', str(tts_dur)])\n    \n    cmd.extend(['-c:v', 'libx264', '-preset', 'fast', str(output_file)])\n    subprocess.run(cmd, check=True)\n    \n    # 验证输出时长\n    out_dur = get_duration(output_file)\n    diff = abs(out_dur - tts_dur)\n    if diff > 0.5:\n        print(f\"⚠️ 时长偏差 {diff:.2f}s: {output_file.name}\")\n    \n    return tts_dur\n\n# 批量处理所有段\ntotal = 0.0\nfor i, (tts_file, shot_file) in enumerate(segments):\n    dur = process_segment(tts_file, shot_file, f\"seg_{i:03d}.mp4\")\n    total += dur\n\nprint(f\"总时长: {total:.2f}s\")\n```\n\n### 短镜头循环填充策略\n\n当源视频短于TTS时，用stream_loop让视频循环播放：\n\n```bash\n/opt/homebrew/bin/ffmpeg -y -stream_loop -1 -i shot.mp4 -t {tts_dur} -c:v libx264 -preset fast seg.mp4\n```\n\n**循环填充的视觉容忍度：**\n| 循环次数 | 观众感知 | 建议 |\n|---------|---------|------|\n| 1次（补0-5s） | 几乎察觉不到 | ✅ 可用 |\n| 2次（补5-10s） | 部分观众能察觉 | ⚠️ 谨慎使用 |\n| 3次以上（补>10s） | 明显重复感 | ❌ 建议换镜头或补新素材 |\n\n### 音画同步验证\n\n合成后必须逐段验证：\n\n```python\ndef verify_sync(segments_dir, tts_dir):\n    \"\"\"验证所有段的音画同步\"\"\"\n    issues = []\n    for i in range(25):\n        seg = Path(segments_dir) / f\"seg_{i:03d}.mp4\"\n        tts = Path(tts_dir) / f\"tts_{i:03d}.mp3\"\n        \n        seg_dur = get_duration(seg)\n        tts_dur = get_duration(tts)\n        diff = seg_dur - tts_dur\n        \n        if abs(diff) > 0.5:\n            issues.append(f\"#{i}: 偏差{diff:+.2f}s\")\n    \n    if issues:\n        print(\"⚠️ 同步问题:\")\n        for issue in issues:\n            print(f\"  {issue}\")\n    else:\n        print(\"✅ 全部同步\")\n```\n\n---\n\n## 五、字幕生成\n\n### Pillow字幕生成模板\n\n```python\nfrom PIL import Image, ImageDraw, ImageFont\n\ndef create_subtitle(text, role=\"\", output_path=\"sub.png\"):\n    \"\"\"生成字幕PNG\"\"\"\n    WIDTH, HEIGHT = 1920, 160\n    img = Image.new('RGBA', (WIDTH, HEIGHT), (0, 0, 0, 0))\n    draw = ImageDraw.Draw(img)\n    \n    font = ImageFont.truetype('/System/Library/Fonts/PingFang.ttc', 48)\n    \n    full_text = f\"{role}：{text}\" if role else text\n    \n    # 黑色描边 + 白色填充\n    draw.text((WIDTH//2, HEIGHT//2), full_text, \n              fill='white', font=font, anchor='mm',\n              stroke_width=3, stroke_fill='black')\n    \n    img.save(output_path)\n```\n\n### FFmpeg叠加字幕\n\n```bash\n/opt/homebrew/bin/ffmpeg -y -i {video}.mp4 -i {subtitle}.png \\\n  -filter_complex \"overlay=0:H-h\" \\\n  -c:v libx264 -preset fast {output}.mp4\n```\n\n---\n\n## 六、最终合成\n\n### 视频拼接\n\n```python\nimport subprocess\nfrom pathlib import Path\n\ndef concat_videos(seg_dir, output_path):\n    \"\"\"拼接所有分段视频\"\"\"\n    segs = sorted(Path(seg_dir).glob(\"seg_*.mp4\"))\n    \n    # 生成file list\n    list_path = Path(seg_dir) / \"video_list.txt\"\n    with open(list_path, 'w') as f:\n        for seg in segs:\n            f.write(f\"file '{seg.absolute()}'\\n\")\n    \n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-f', 'concat', '-safe', '0',\n        '-i', str(list_path),\n        '-c', 'copy',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n### 音频拼接\n\n```python\ndef concat_audios(audio_dir, output_path):\n    \"\"\"拼接所有TTS音频\"\"\"\n    audios = sorted(Path(audio_dir).glob(\"*.mp3\"))\n    \n    list_path = Path(audio_dir) / \"audio_list.txt\"\n    with open(list_path, 'w') as f:\n        for audio in audios:\n            f.write(f\"file '{audio.absolute()}'\\n\")\n    \n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-f', 'concat', '-safe', '0',\n        '-i', str(list_path),\n        '-c', 'copy',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n### 音视频合并\n\n```python\ndef merge_av(video_path, audio_path, output_path):\n    \"\"\"合并视频和音频\"\"\"\n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-i', str(video_path),\n        '-i', str(audio_path),\n        '-c:v', 'copy',\n        '-c:a', 'aac',\n        '-shortest',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n---\n\n## 七、素材导出\n\n### 桌面文件夹结构\n\n```python\nimport os, shutil\n\ndef export_to_desktop(project_name, segments_data, desktop_path):\n    \"\"\"导出结构化素材到桌面\"\"\"\n    base = os.path.join(desktop_path, project_name)\n    \n    dirs = {\n        \"01_字幕\": \"subtitle_pngs\",\n        \"02_配音\": \"tts_mp3s\",\n        \"03_主图\": \"thumbnails\",\n        \"04_视频\": \"seg_videos\",\n        \"05_矩阵表\": \"matrix\"\n    }\n    \n    for name in dirs:\n        os.makedirs(os.path.join(base, name), exist_ok=True)\n    \n    # 生成矩阵表HTML\n    generate_matrix_html(segments_data, os.path.join(base, \"05_矩阵表\", \"矩阵表.html\"))\n    \n    # 生成JSON\n    generate_json(segments_data, os.path.join(base, \"05_矩阵表\", \"素材结构.json\"))\n```\n\n---\n\n## 八、成本核算\n\n### 完整成本模型\n\n```python\ndef calculate_cost(params):\n    \"\"\"\n    params = {\n        'shot_seconds': 234,      # 镜头总时长\n        'retry_times': 3,          # 平均重试次数\n        'tts_chars': 350,          # TTS总字数\n        'dialog_rounds': 250,      # WorkBuddy对话轮次\n        'project_days': 2,         # 项目天数\n    }\n    \"\"\"\n    grok = params['shot_seconds'] * 0.05 * params['retry_times']\n    tts = params['tts_chars'] * 0.0006 * 1.5  # 含重试\n    wb = params['dialog_rounds'] * 0.0022 * 1.5  # 含隐性消耗\n    hw = 3.65 * params['project_days']  # 硬件折旧\n    power = 0.62 * params['project_days']  # 电费\n    \n    return {\n        'Grok Imagine': grok,\n        'TTS配音': tts,\n        'WorkBuddy算力': wb,\n        '硬件折旧': hw,\n        '电费': power,\n        '总计': grok + tts + wb + hw + power\n    }\n```\n\n### 参考成本（基于三体EP1实战）\n\n| 项目规模 | 预估成本 | 制作周期 |\n|---------|---------|---------|\n| 30秒 / 6镜头 | ¥10-15 | 0.5天 |\n| 60秒 / 12镜头 | ¥20-30 | 1天 |\n| 128秒 / 25镜头 | ¥40-50 | 2天 |\n| 5分钟 / 50镜头 | ¥80-120 | 3-4天 |\n\n---\n\n## 九、常见问题排查\n\n### 视频生成失败\n- **症状**: API返回错误或超时\n- **排查**: 检查API Key是否有效、余额是否充足\n- **解决**: 重试（换IP节点）、切换模型\n\n### TTS卡住\n- **症状**: status一直=0\n- **排查**: 检查参数格式（扁平JSON）\n- **解决**: 重新提交任务\n\n### 音画不同步\n- **症状**: 画面和声音对不上\n- **排查**: 检查每段TTS时长和视频裁剪时长\n- **解决**: 逐段精确裁剪，不要整体缩放\n\n### 字幕不显示\n- **症状**: 视频没有字幕\n- **排查**: 检查FFmpeg版本是否支持drawtext\n- **解决**: 用Pillow生成PNG + overlay叠加\n\n### 视频拼接报错\n- **症状**: concat失败\n- **排查**: 检查所有分段视频编码是否一致\n- **解决**: 统一用libx264编码重新转码\n\n---\n\n## 十、专业审核与迭代流程\n\nAI生成的第一版几乎从来不是最终版。必须经过\"制作→审核→修改\"的迭代循环。\n\n### 10.1 六维审核检查表\n\n| 维度 | 检查方法 | 判定标准 |\n|------|---------|---------|\n| **① 音画同步** | 逐段播放，对比画面内容与配音台词 | 角色A说话时画面必须是角色A |\n| **② 时长匹配** | ffprobe对比每段视频和TTS时长 | 偏差 < 0.5s |\n| **③ 视觉重复** | 检查stream_loop循环次数 | 不超过2次循环 |\n| **④ 字幕准确** | 逐句对照字幕文本和TTS台词 | 无错别字、标点正确 |\n| **⑤ 节奏感** | 整体观看，标记拖沓或仓促段落 | 每段TTS时长占镜头60-80%最佳 |\n| **⑥ 画面质量** | 检查AI生成瑕疵 | 无变形、闪烁、分辨率异常 |\n\n### 10.2 问题分级与修复优先级\n\n```\nP0（必须修复）—— 影响观看体验的根本问题\n├── 音画不匹配：画面内容与台词无关\n├── 字幕错误：错别字、台词与字幕不一致\n├── 画面截断：话没说完画面就切了\n└── 时长严重偏差：偏差 > 1s\n→ 优先级：最高，不修不能交付\n\nP1（建议修复）—— 影响观看体验但可接受\n├── 节奏拖沓：某段画面太长，观众失去耐心\n├── 视觉重复感：循环超过2次\n├── 转场生硬：相邻镜头切换突兀\n└── 音色不匹配：角色音色与形象不符\n→ 优先级：中，尽量修\n\nP2（可优化）—— 锦上添花\n├── 画面色调不统一\n├── 字幕样式可美化\n├── 背景音效可丰富\n└── 片头片尾可添加\n→ 优先级：低，有时间再修\n```\n\n### 10.3 迭代工作流\n\n```python\ndef review_and_fix(version, issues):\n    \"\"\"\n    version: 当前版本号\n    issues: 审核发现的问题列表\n    \n    返回: 是否需要继续迭代\n    \"\"\"\n    p0_count = sum(1 for i in issues if i['level'] == 'P0')\n    p1_count = sum(1 for i in issues if i['level'] == 'P1')\n    \n    print(f\"版本 {version} 审核结果:\")\n    print(f\"  P0(必须修): {p0_count}\")\n    print(f\"  P1(建议修): {p1_count}\")\n    print(f\"  P2(可优化): {len(issues) - p0_count - p1_count}\")\n    \n    if p0_count > 0:\n        print(\"→ 进入下一轮迭代\")\n        return True\n    elif p1_count > 2:\n        print(\"→ 建议再修一轮\")\n        return True\n    else:\n        print(\"→ 达到交付标准 ✅\")\n        return False\n```\n\n### 10.4 实战案例：三体EP1迭代记录\n\n| 版本 | 时长 | 问题发现 | 修复内容 | 审核结论 |\n|------|------|---------|---------|---------|\n| v5min | 252s | 视频总长252s但TTS仅127s，大量空白段落 | 重新按TTS时长裁剪 | ❌ P0: 节奏断裂 |\n| v6 | — | 音频驱动剪辑，3个短镜头被截断 | 修复中 | ❌ 未完成 |\n| v7 | 127s | 3个短镜头截断：火鸡演讲缺9s | stream_loop循环填充 | ❌ P0: 画面截断 |\n| v7.1 | 127.9s | 循环修复完成，但无字幕 | 加字幕 | ⚠️ P1: 缺字幕 |\n| v8 | 127.9s | 字幕+音画同步修复+矩阵表 | 全部修复 | ✅ 交付 |\n\n### 10.5 审核工具脚本\n\n```python\n#!/usr/bin/env python3\n\"\"\"一键审核脚本：检查所有段的音画同步和时长匹配\"\"\"\n\nimport subprocess\nfrom pathlib import Path\n\nFFPROBE = '/opt/homebrew/bin/ffprobe'\n\ndef get_duration(p):\n    r = subprocess.run([FFPROBE,'-v','quiet','-show_entries','format=duration',\n                        '-of','csv=p=0',str(p)], capture_output=True, text=True)\n    return float(r.stdout.strip())\n\ndef audit(segments_dir, tts_dir, num_segments=25):\n    issues = []\n    print(f\"{'#':>3} {'角色':<20} {'TTS':>7} {'视频':>7} {'偏差':>7} {'状态'}\")\n    print(\"-\" * 55)\n    \n    for i in range(num_segments):\n        seg = Path(segments_dir) / f\"seg_{i:03d}.mp4\"\n        tts = sorted(Path(tts_dir).glob(\"*.mp3\"))[i]\n        \n        seg_dur = get_duration(seg) if seg.exists() else 0\n        tts_dur = get_duration(tts)\n        diff = seg_dur - tts_dur\n        \n        status = \"✅\" if abs(diff) < 0.5 else \"⚠️\"\n        if abs(diff) > 0.5:\n            issues.append(f\"#{i}: 偏差{diff:+.2f}s\")\n        \n        print(f\"{i:3d} {tts.stem:<20s} {tts_dur:>6.2f}s {seg_dur:>6.2f}s {diff:>+6.2f}s {status}\")\n    \n    print(f\"\\n问题段: {len(issues)}\")\n    for issue in issues:\n        print(f\"  {issue}\")\n    \n    return issues\n\nif __name__ == '__main__':\n    audit(Path('v7_assets'), Path('ep1_tts'))\n```\n\nFile v1.0.3:references/sucuang_api.md\n\n# 速创API 接口文档与踩坑经验\n\n## 平台信息\n\n- **平台地址**: （注册后获取）\n- **文档中心**: （注册后获取）\n- **API Key获取**: 注册登录后进入控制台获取\n\n## 通用鉴权方式\n\n**推荐方式 — Authorization Header（不带Bearer前缀）：**\n```python\nHEADERS = {\n    \"Authorization\": \"你的API_KEY\",\n    \"Content-Type\": \"application/json\"\n}\n```\n\n**❌ 不要用URL参数传key：**\n```python\n# 会返回403，不要这样用\nrequests.get(\"平台API地址/api/xxx?key=你的API_KEY\")\n```\n\n---\n\n## 1. Grok Imagine 视频生成\n\n### 接口信息\n- **接口**: POST `/api/async/video/grok_imagine`\n- **价格**: 按秒计费（具体见平台）\n- **点数**: 5点/秒\n- **免费额度**: 无\n- **QPS限制**: 100次/秒\n- **每日限制**: 付费用户不限制\n\n### 请求参数\n```json\n{\n  \"prompt\": \"英文描述效果更稳定，包含场景、光线、构图、镜头运动\",\n  \"duration\": 10,\n  \"style\": \"cinematic\"\n}\n```\n\n### 结果查询\n- **接口**: `GET /api/async/detail?id=xxx`\n- **轮询策略**: 每5秒查询一次\n- **状态码**: status=2 表示完成，status=0/1 表示处理中\n- **返回内容**: 包含视频下载URL\n\n### 批量生成策略\n```python\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\n\ndef submit_shot(shot):\n    # 提交生成任务\n    resp = requests.post(url, headers=HEADERS, json=params)\n    task_id = resp.json()[\"data\"][\"id\"]\n    # 轮询直到完成\n    while True:\n        result = requests.get(f\"{BASE}/detail?id={task_id}\", headers=HEADERS)\n        if result.json()[\"data\"][\"status\"] == 2:\n            return download_video(result.json()[\"data\"][\"video_url\"])\n        time.sleep(5)\n\n# 批量25个镜头同时提交\nwith ThreadPoolExecutor(max_workers=10) as executor:\n    futures = [executor.submit(submit_shot, shot) for shot in SHOTS]\n    for future in as_completed(futures):\n        results.append(future.result())\n```\n\n### 踩坑经验\n- Sora2接口（sora2/video）已不可用，持续返回400错误，全部使用Grok Imagine\n- 英文Prompt比中文Prompt效果更稳定\n- 平均重试3次才能获得满意结果\n- 生成耗时约30-60秒/个\n\n---\n\n## 2. TTS配音生成\n\n### 接口信息\n- **接口**: `POST /api/async/audio_tts`\n- **价格**: 按字计费（具体见平台）\n- **返回格式**: tar包（需解压获取mp3）\n\n### 请求参数（重要：扁平JSON）\n```json\n{\n  \"text\": \"台词内容\",\n  \"voice_id\": \"male-qn-jingying\",\n  \"speed\": 1.0\n}\n```\n\n### 可用音色列表\n| 音色ID | 描述 | 适用角色 |\n|--------|------|---------|\n| male-qn-jingying | 精英青年男声 | 旁白、汪淼、常伟思 |\n| male-qn-badao | 霸道男声 | 史强 |\n| male-qn-daxuesheng | 大学生男声 | 研究员 |\n| male-chunhou | 醇厚男声 | 长辈角色 |\n| junlang_nanyou | 俊朗男声 | 潘寒 |\n| female-chengshu | 成熟女声 | 申玉菲 |\n| female-shaonv | 少女音 | 杨冬 |\n\n### 踩坑经验（重要）\n1. **❌ 不要传 format 参数** — 会报500\"存在未绑定的参数\"\n2. **❌ 不要嵌套参数** — 不要写成 `{\"model\":\"audio_tts\",\"params\":{...}}`，直接扁平JSON\n3. **✅ 状态码判断** — 用 `status == 2` 判断完成，不要用字符串 `\"completed\"`\n4. **⚠️ 部分任务会卡住** — status一直=0，重试可换到不同IP节点\n5. **✅ 返回tar包** — 需要用 `tarfile` 解压获取mp3文件\n\n### TTS生成代码模板\n```python\nimport requests, time, tarfile, io\n\ndef generate_tts(text, voice_id, output_path):\n    payload = {\"text\": text, \"voice_id\": voice_id, \"speed\": 1.0}\n    resp = requests.post(f\"{BASE}/api/async/audio_tts\", headers=HEADERS, json=payload)\n    task_id = resp.json()[\"data\"][\"id\"]\n\n    while True:\n        result = requests.get(f\"{BASE}/api/async/detail?id={task_id}\", headers=HEADERS)\n        data = result.json()[\"data\"]\n        if data[\"status\"] == 2:  # 完成\n            audio_url = data[\"audio_url\"]\n            audio_resp = requests.get(audio_url)\n            tar = tarfile.open(fileobj=io.BytesIO(audio_resp.content))\n            for member in tar.getmembers():\n                if member.name.endswith('.mp3'):\n                    f = tar.extractfile(member)\n                    with open(output_path, 'wb') as out:\n                        out.write(f.read())\n            return\n        elif data[\"status\"] == -1:  # 失败\n            raise Exception(f\"TTS failed: {data}\")\n        time.sleep(3)\n```\n\n---\n\n## 3. 数字人视频生成\n\n### 接口信息\n- **接口**: `POST /api/async/video_digital_humans`\n- **价格**: 按次计费\n\n### 请求参数\n```json\n{\n  \"audio_url\": \"公网可访问的音频URL\",\n  \"video_url\": \"公网可访问的视频URL\"\n}\n```\n\n### 注意事项\n- 音频和视频URL必须公网可访问\n- 推荐搭配云存储服务存储素材\n\n---\n\n## 4. 云存储配置（素材存储）\n\n如需存储视频和音频文件，推荐使用云存储服务：\n- 腾讯云COS\n- 阿里云OSS\n- AWS S3\n\n请根据实际需求配置您自己的云存储凭证。\n\n---\n\n## 5. 其他可用模型\n\n速创API平台还提供以下模型（价格以平台实际为准）：\n- 文生图模型（多种）\n- 视频编辑模型\n- 语音识别\n- 大语言模型对话\n\n具体价格请查看平台定价页面。\n\nFile v1.0.3:skill-card.md\n\n## Description:\n\nAI短剧制作助手 | AI Short Film Producer helps agents plan and produce low-cost AI short films by creating shot scripts, generating video and TTS assets through third-party APIs, and assembling them locally with FFmpeg and Python.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[hitjcl](https://clawhub.ai/user/hitjcl)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users, developers, and creative operators use this skill to turn a topic, script, or concept into an AI short film workflow with shot planning, video generation, voiceover generation, subtitles, local composition, review, and cost tracking.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The workflow uses third-party video and TTS APIs that may receive user prompts, scripts, or generated content.\n\nMitigation: Do not submit secrets, regulated data, private scripts, or sensitive personal information to the referenced APIs; review provider terms before use.\n\nRisk: API keys may be exposed if copied into URLs, logs, scripts, or shared project files.\n\nMitigation: Pass API keys through headers or a local secret store, keep them out of URLs and logs, and avoid committing generated credentials or configuration files.\n\nRisk: Downloaded media archives and generated assets are processed locally with Python and FFmpeg.\n\nMitigation: Use request timeouts, retry limits, trusted download hosts, archive size checks, and safe FFmpeg concat manifests before processing untrusted media folders.\n\nRisk: Generated footage, TTS, or subtitles can be inaccurate, poorly synchronized, or visually defective.\n\nMitigation: Run the documented review workflow for audio-video sync, subtitle accuracy, duration drift, repeated loops, and visual quality before publishing.\n\n## Reference(s):\n\n- [AI Short Film Producer skill page](https://clawhub.ai/hitjcl/skills/ai-short-film-producer)\n- [AI短剧制作流程详细参考](artifact/references/production_workflow.md)\n- [速创API 接口文档与踩坑经验](artifact/references/sucuang_api.md)\n\n## Skill Output:\n\n**Output Type(s):** [Guidance, Markdown, Code, Shell commands, Configuration]\n\n**Output Format:** [Markdown with JSON, Python, and shell command examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Produces workflow guidance and implementation snippets for scripts, generated media assets, subtitles, FFmpeg composition, review checks, and cost calculations.]\n\n## Skill Version(s):\n\n1.0.3 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.2: 4 files, 16416 bytes\n\nFiles: references/production_workflow.md (15821b), references/sucuang_api.md (5282b), SKILL.md (12752b), _meta.json (141b)\n\nFile v1.0.2:SKILL.md\n\n---\nname: ai-short-film-producer\ndescription: 低成本AI短剧/短片全流程制作技能。使用速创API(wuyinkeji.com)的Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成，WorkBuddy编排全流程。适用于用户需要从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动剪辑、字幕叠加、最终合成、成本核算的全套SOP。\n---\n\n# AI Short Film Producer - 低成本AI短剧制作\n\n## 概述\n\n本Skill提供一套完整的**低成本AI短剧制作流程**，从脚本创作到最终成片，总成本仅需**¥30-50/部**（128秒短片）。核心思路：用AI API生成素材 → 本地FFmpeg合成 → WorkBuddy编排调度。\n\n**适用场景：**\n- 用户说\"帮我做一个短片/短剧/预告片\"\n- 用户说\"把这段文案做成视频\"\n- 用户说\"生成一个XX题材的短视频\"\n- 用户需要从零到一完成AI视频制作\n\n**核心成本优势：**\n- 视频生成：Grok Imagine ¥0.05/秒（速创API）\n- 配音生成：TTS ¥0.0006/字（速创API）\n- 合成剪辑：本地FFmpeg免费\n- AI编排：WorkBuddy Lite版约¥0.0022/轮\n\n---\n\n## 制作流程总览\n\n```\nStep 1: 脚本创作\n  ├── 确定主题/时长/风格\n  ├── 编写分镜脚本（镜头×台词×角色）\n  └── 输出：分镜表 + TTS文本清单\n\nStep 2: 视频镜头生成\n  ├── 调用速创API Grok Imagine\n  ├── 25个镜头批量异步生成\n  └── 输出：ep1_shots/*.mp4\n\nStep 3: TTS配音生成\n  ├── 调用速创API audio_tts\n  ├── 多角色多音色\n  └── 输出：ep1_tts/*.mp3\n\nStep 4: 音频驱动剪辑\n  ├── 逐段按TTS时长裁剪/循环镜头\n  ├── 短镜头自动stream_loop填充\n  └── 输出：分段seg_*.mp4\n\nStep 5: 字幕生成\n  ├── Python Pillow生成透明PNG字幕\n  ├── FFmpeg overlay叠加（因FFmpeg 8.x无drawtext）\n  └── 输出：带字幕的分段视频\n\nStep 6: 最终合成\n  ├── concat拼接25段视频\n  ├── concat拼接25段音频\n  ├── 音视频合并\n  └── 输出：最终成片.mp4\n\nStep 7: 素材导出\n  ├── 结构化桌面文件夹\n  ├── 矩阵表 + JSON\n  └── 成本核算\n```\n\n---\n\n## 详细步骤\n\n### Step 1: 脚本创作\n\n**输入：** 用户需求（主题、风格、时长、参考素材）\n**输出：** 分镜脚本文档 + TTS台词清单\n\n**工作流程：**\n1. 与用户确认主题方向（科幻/悬疑/科普/剧情等）\n2. 编写分镜脚本，包含：\n   - 镜头编号、画面描述、时长\n   - 配音台词、角色分配、音色选择\n   - 音效说明\n3. 输出TTS台词清单（25段以内，每段2-20字最佳）\n4. 角色音色分配表：\n\n| 角色类型 | 推荐音色ID | 说明 |\n|---------|-----------|------|\n| 旁白/叙述者 | male-qn-jingying | 精英青年男声，通用 |\n| 男主角 | male-qn-jingying | 精英青年男声 |\n| 霸道/硬汉 | male-qn-badao | 霸道男声 |\n| 反派/俊朗 | junlang_nanyou | 俊朗男声 |\n| 成熟女性 | female-chengshu | 成熟女声 |\n| 少女 | female-shaonv | 少女音 |\n| 研究员/学生 | male-qn-daxuesheng | 大学生男声 |\n| 醇厚长辈 | male-chunhou | 醇厚男声 |\n\n### Step 2: 视频镜头生成（速创API Grok Imagine）\n\n**API平台：** 速创API https://api.wuyinkeji.com\n**模型：** Grok Imagine（xAI Aurora引擎）\n**价格：** ¥0.05/秒（按生成视频时长计费，不足1秒按1秒）\n\n**API调用方式：**\n- 鉴权：Authorization Header 传API Key（不带Bearer前缀）\n- 接口：POST /api/async/video/grok_imagine\n- 参数格式：扁平JSON\n- 结果查询：GET /api/async/detail?id=xxx（轮询直到status=2）\n\n**批量生成策略：**\n1. 25个镜头同时提交（用ThreadPoolExecutor）\n2. 每个镜头约10秒，生成耗时约30-60秒\n3. 失败自动重试（平均重试3次）\n4. 注意：Sora2接口已不可用（持续400错误），全部使用Grok Imagine\n\n**Prompt编写要点：**\n- 英文Prompt效果更稳定\n- 包含：场景描述、光线、构图、镜头运动\n- 示例：`\"Deep space, Milky Way galaxy slowly rotating, cinematic wide shot, photorealistic, 4K quality\"`\n\n### Step 3: TTS配音生成（速创API audio_tts）\n\n**API接口：** POST /api/async/audio_tts\n**价格：** ¥0.0006/字\n**参数格式（重要）：** 扁平JSON，不要嵌套\n\n```json\n{\n  \"text\": \"台词内容\",\n  \"voice_id\": \"male-qn-jingying\",\n  \"speed\": 1.0\n}\n```\n\n**注意事项（踩坑经验）：**\n- ❌ 不要传 format 参数（会报500\"存在未绑定的参数\"）\n- ❌ 不要嵌套成 `{\"model\":\"audio_tts\",\"params\":{...}}`\n- ✅ 状态码判断：status=2 完成，status=0/1 处理中\n- ⚠️ 部分任务会卡住（status一直=0），重试可换IP节点\n- ✅ 返回tar包，需解压获取mp3\n\n### Step 4: 音频驱动剪辑（核心节奏控制）\n\n**核心理念：** 画面长度由语音旁白决定，而非固定时长。先录制/生成TTS配音，再让每段视频精确匹配对应配音的时长。这样保证音画天然同步，且节奏由配音自然驱动。\n\n#### 4.1 节奏控制逻辑\n\n```\n每段（镜头, TTS）的处理流程：\n\n1. 获取TTS音频实际时长 tts_dur（用ffprobe精确到毫秒）\n2. 获取源视频时长 src_dur\n3. 对比决策：\n   ├── src_dur >= tts_dur + 0.5s  → 直接裁剪到tts_dur（视频多出的部分舍弃）\n   ├── src_dur ≈ tts_dur（差<0.5s）→ 直接裁剪，不做额外处理\n   └── src_dur < tts_dur           → stream_loop循环播放填满tts_dur\n4. 输出：seg_NNN.mp4（时长=tts_dur，精确匹配配音）\n```\n\n**为什么用\"音频驱动\"而非\"视频驱动\"：**\n- 传统剪辑：先定视频长度，再往里塞配音 → 配音节奏被画面绑架\n- 音频驱动：先定配音节奏，再裁剪画面适配 → 叙事节奏由台词自然决定\n- 效果：观众听到的每句话都有对应的画面时长，不会出现\"话没说完画面就切了\"\n\n#### 4.2 短镜头循环填充（stream_loop）\n\n当源视频时长不够时，用FFmpeg的stream_loop让视频循环播放：\n\n```bash\n# 循环播放直到填满tts_dur\n/opt/homebrew/bin/ffmpeg -y -stream_loop -1 -i shot.mp4 -t {tts_dur} -c:v libx264 -preset fast seg.mp4\n```\n\n**实战经验（三体EP1）：**\n- 25个镜头中有3个需要循环填充\n- 最大修复：pan_han_02火鸡演讲（源视频10s → TTS需要19s，循环补9s）\n- 循环填充的视觉重复感在1-2次循环内不明显，超过3次建议换镜头\n\n#### 4.3 逐段精确裁剪避免累积漂移\n\n```python\n# 关键：每段独立裁剪，不整体缩放\ncumulative = 0.0\nfor i, (tts_file, shot_file) in enumerate(segments):\n    tts_dur = get_duration(tts_file)  # ffprobe获取\n    # 精确裁剪到tts_dur，不依赖前一段的结束时间\n    trim_video(shot_file, tts_dur, f\"seg_{i:03d}.mp4\")\n    cumulative += tts_dur\n\n# 最终验证：所有seg时长之和 ≈ audio_concat时长 ≈ 最终成片时长\n```\n\n**FFmpeg路径（Mac mini M4）：** `/opt/homebrew/bin/ffmpeg`\n\n**已知限制：**\n- FFmpeg 8.x 未编译drawtext/libass/freetype滤镜 → 不能直接加字幕\n- anullsrc语法用 `cl=stereo` 而非 `c=stereo`\n- shell转义用Python subprocess list模式避免zsh问题\n\n### Step 5: 字幕生成\n\n**方案：** Pillow生成透明PNG → FFmpeg overlay叠加\n\n```python\nfrom PIL import Image, ImageDraw, ImageFont\n\n# 创建透明PNG\nimg = Image.new('RGBA', (1920, 160), (0,0,0,0))\ndraw = ImageDraw.Draw(img)\nfont = ImageFont.truetype('/System/Library/Fonts/PingFang.ttc', 48)\n\n# 白色大字 + 黑色描边\ndraw.text((960, 80), \"台词文本\", fill='white', font=font, \n          anchor='mm', stroke_width=3, stroke_fill='black')\n\n# FFmpeg overlay叠加\nffmpeg -i seg.mp4 -i sub.png -filter_complex \"overlay=0:H-h\" output.mp4\n```\n\n**字幕设计规范：**\n- 底部居中，距底部约60px\n- 白色大字 + 3px黑色描边\n- 字号48-56px（PingFang SC字体）\n- 可加角色标签（如\"旁白：\"、\"汪淼：\"）\n\n### Step 6: 最终合成\n\n**拼接视频：**\n```bash\n# 生成file list\nfor f in seg_*.mp4; do echo \"file '$f'\" >> video_list.txt; done\nffmpeg -f concat -safe 0 -i video_list.txt -c copy video_concat.mp4\n```\n\n**拼接音频：**\n```bash\nfor f in audio_*.mp3; do echo \"file '$f'\" >> audio_list.txt; done\nffmpeg -f concat -safe 0 -i audio_list.txt -c copy audio_concat.aac\n```\n\n**音视频合并：**\n```bash\nffmpeg -i video_concat.mp4 -i audio_concat.aac -c:v copy -c:a aac final.mp4\n```\n\n### Step 7: 素材导出与成本核算\n\n**桌面文件夹结构：**\n```\n~/Desktop/项目名称/\n├── 01_字幕/     → 字幕PNG文件\n├── 02_配音/     → TTS音频MP3\n├── 03_主图/     → 镜头缩略图JPG\n├── 04_视频/     → 分段视频MP4\n├── 05_矩阵表/   → 矩阵表.html + 素材结构.json\n└── 最终成片.mp4\n```\n\n**成本核算模板：**\n\n| 项目 | 计算方式 | 参考单价 |\n|------|---------|---------|\n| Grok Imagine视频 | 总秒数 × 重试次数 × ¥0.05 | ¥0.05/秒 |\n| TTS配音 | 总字数 × ¥0.0006 | ¥0.0006/字 |\n| WorkBuddy算力 | 对话轮次 × ¥0.0022 | ¥0.0022/轮 |\n| 硬件折旧 | Mac mini ¥3,999/3年寿命 | ¥3.65/天 |\n| 电费 | 16h × 65W × ¥0.6/度 | ¥0.62/天 |\n\n---\n\n## 速创API平台速查\n\n**平台地址：** https://api.wuyinkeji.com\n**文档中心：** https://api.wuyinkeji.com/doc\n\n**常用模型及价格：**\n\n| 模型/接口 | 价格 | 说明 |\n|-----------|------|------|\n| Grok Imagine 视频生成 | ¥0.05/秒 | 文生视频/图生视频，6-15秒 |\n| audio_tts 配音 | ¥0.0006/字 | 多音色TTS |\n| video_digital_humans 数字人 | 按次计费 | 需公网音频URL+视频URL |\n| Sora2（已弃用） | — | 持续400错误，不可用 |\n\n**API Key传递：**\n- ✅ Authorization Header（推荐，不带Bearer前缀）\n- ❌ URL参数 ?key=xxx（会返回403）\n\n---\n\n## 三体EP1实战参考\n\n**项目规模：** 25个镜头，127秒成片，8个角色\n**总成本：** ¥44.17（含重试+硬件折旧）\n**工具链：** Grok Imagine × 25 + TTS × 25 + FFmpeg + Python Pillow\n**迭代版本：** v5min → v6 → v7 → v7.1 → v8（5个版本迭代）\n\n**关键经验：**\n1. Sora2不可用，全部切Grok Imagine\n2. 源视频短于TTS时用stream_loop循环填充\n3. FFmpeg 8.x无drawtext，用Pillow生成PNG替代\n4. TTS部分任务卡住需重试\n5. 逐段精确裁剪避免累积漂移\n\n---\n\n## 专业审核与迭代流程\n\nAI生成的第一版通常不是最终版。必须经过\"制作→审核→修改\"的迭代循环才能达到交付标准。\n\n### 审核维度\n\n| 维度 | 检查内容 | 常见问题 |\n|------|---------|---------|\n| **音画同步** | 画面内容是否匹配配音台词 | 角色A说话但画面是角色B |\n| **时长匹配** | 每段视频是否完整覆盖TTS | 短镜头被截断，话没说完画面就切 |\n| **视觉重复** | 循环播放是否超过3次 | 火鸡演讲循环9s，观众能看出重复 |\n| **字幕准确** | 字幕文本是否与TTS一致 | 错别字、标点错误 |\n| **节奏感** | 整体叙事节奏是否流畅 | 某段太长拖沓，某段太短仓促 |\n| **画面质量** | 是否有明显AI生成瑕疵 | 人物变形、闪烁、分辨率低 |\n\n### 迭代流程\n\n```\nV1（初版合成）\n  ↓\n专业审核（逐段检查以上6个维度）\n  ↓\n问题清单 → 按严重程度排序\n  ├── P0（必须修）：音画不匹配、字幕错误、画面截断\n  ├── P1（建议修）：节奏拖沓、视觉重复感强\n  └── P2（可优化）：画面质量、色调统一\n  ↓\nV2（修复P0问题）\n  ↓\n再次审核\n  ↓\nV3...（逐轮修复，直到P0=0、P1≤2）\n  ↓\n最终交付\n```\n\n### 实战案例：三体EP1迭代记录\n\n| 版本 | 问题 | 修复方案 |\n|------|------|---------|\n| v5min | 252秒成片，但TTS只有127秒，大量空白 | 重新按TTS时长裁剪 |\n| v6 | 音频驱动剪辑，但3个短镜头被截断 | 修复中 |\n| v7 | 短镜头截断（火鸡演讲缺9s） | stream_loop循环填充 |\n| v7.1 | 循环修复完成，但无字幕 | 加字幕 |\n| v8 | 字幕+音画同步修复+矩阵表 | ✅ 最终交付 |\n\n**审核工具：**\n- 逐段对比：`ffprobe` 获取每段TTS和视频的精确时长\n- 偏差检查：每段TTS vs 视频时长差 > 0.5s 即标记为问题段\n- 画面检查：播放时逐段确认画面内容与台词匹配\n\n---\n\n## 资源文件\n\n### references/\n- `sucuang_api.md` — 速创API完整接口文档和踩坑经验\n- `production_workflow.md` — 制作流程详细参考\n\n### scripts/\n- （按需添加：批量提交脚本、合成脚本模板等）\n\n### assets/\n- （按需添加：字幕模板、片头片尾素材等）\n\nFile v1.0.2:_meta.json\n\n{\n  \"ownerId\": \"kn703gwc11aqnnaatk69f339d9822e08\",\n  \"slug\": \"ai-short-film-producer\",\n  \"version\": \"1.0.2\",\n  \"publishedAt\": 1777542626768\n}\n\nFile v1.0.2:references/production_workflow.md\n\n# AI短剧制作流程详细参考\n\n## 一、项目启动\n\n### 需求确认\n与用户确认以下信息：\n1. **主题**：科幻/悬疑/科普/剧情/搞笑/教育等\n2. **风格**：写实/动画/赛博朋克/古风等\n3. **时长**：30秒/60秒/2分钟/5分钟\n4. **角色**：需要几个角色？是否有特定音色要求？\n5. **参考素材**：用户是否提供文案/图片/参考视频？\n\n### 脚本模板\n\n```markdown\n# 项目名称 · 分镜脚本\n\n## 总览\n- 总时长：XX秒\n- 镜头数：XX个\n- 角色数：XX个\n\n## 分镜表\n| # | 镜头ID | 画面描述 | 配音台词 | 角色 | 音色 | 时长 |\n|---|--------|---------|---------|------|------|------|\n| 1 | shot01_xxx | 画面描述 | 台词内容 | 角色名 | 音色ID | 10s |\n| 2 | shot02_xxx | 画面描述 | 台词内容 | 角色名 | 音色ID | 10s |\n```\n\n---\n\n## 二、视频生成\n\n### Grok Imagine Prompt编写指南\n\n**结构模板：**\n```\n[场景描述], [主体描述], [光线/氛围], [构图/镜头运动], [风格关键词]\n```\n\n**示例：**\n```\n\"Deep space, Milky Way galaxy slowly rotating across a star-filled cosmos,\ncountless stars twinkling, nebulae in deep blue and purple hues,\ncinematic wide shot, photorealistic, 4K quality, slow gentle rotation\"\n```\n\n**各类型场景Prompt关键词：**\n\n| 场景类型 | 关键词 |\n|---------|--------|\n| 太空/宇宙 | deep space, stars, nebula, galaxy, cosmic, celestial |\n| 城市/街头 | city street, urban, bustling, modern, buildings |\n| 室内/会议室 | conference room, modern, screens, professional |\n| 人物特写 | close-up, portrait, expression, emotion, cinematic lighting |\n| 自然/风景 | landscape, mountains, ocean, sunset, cinematic |\n| 科技/实验室 | laboratory, technology, screens, equipment, futuristic |\n\n### 批量提交策略\n\n1. 25个镜头同时提交到API\n2. 使用ThreadPoolExecutor(max_workers=10)\n3. 每5秒轮询一次结果\n4. 失败自动重试（最多5次）\n5. 下载后检查文件完整性（ffprobe验证时长）\n\n---\n\n## 三、TTS配音生成\n\n### 多角色音色分配策略\n\n| 角色数量 | 分配策略 |\n|---------|---------|\n| 1-2个角色 | 旁白用jingying，对话角色用对应音色 |\n| 3-5个角色 | 主要角色各分配独立音色，次要角色复用 |\n| 6-10个角色 | 核心角色独立音色，路人/群演用通用音色 |\n\n### 台词字数控制\n- 每段TTS建议2-20字（太长影响听感）\n- 10秒镜头配2-4秒台词最合适\n- 留白时间给观众消化内容\n\n---\n\n## 四、音频驱动剪辑（核心节奏控制）\n\n### 核心理念\n\n**音频驱动剪辑 = 画面长度由语音旁白决定，而非固定时长。**\n\n传统剪辑思维是\"先定视频长度，再往里塞配音\"，结果配音节奏被画面绑架。音频驱动反过来——先录制TTS配音，再让每段视频精确匹配对应配音的时长。这样：\n- 观众听到的每句话都有完整的画面时长\n- 叙事节奏由台词自然驱动\n- 不会出现\"话没说完画面就切了\"\n\n### 核心算法\n\n```\n对于每一段（镜头, TTS）：\n  1. 获取TTS音频时长 tts_dur（ffprobe精确到毫秒）\n  2. 获取源视频时长 src_dur\n  3. 对比决策：\n     ├── src_dur >= tts_dur + 0.5s  → 直接裁剪到tts_dur\n     ├── src_dur ≈ tts_dur（差<0.5s）→ 直接裁剪\n     └── src_dur < tts_dur           → stream_loop循环填充\n  4. 输出：seg_NNN.mp4（时长精确=tts_dur）\n```\n\n### 逐段精确裁剪（避免累积漂移）\n\n```python\nimport subprocess\nfrom pathlib import Path\n\nFFPROBE = '/opt/homebrew/bin/ffprobe'\nFFMPEG = '/opt/homebrew/bin/ffmpeg'\n\ndef get_duration(filepath):\n    \"\"\"获取媒体文件精确时长\"\"\"\n    result = subprocess.run(\n        [FFPROBE, '-v', 'quiet', '-show_entries', 'format=duration',\n         '-of', 'csv=p=0', str(filepath)],\n        capture_output=True, text=True\n    )\n    return float(result.stdout.strip())\n\ndef process_segment(tts_file, shot_file, output_file):\n    \"\"\"处理单段：按TTS时长裁剪/循环视频\"\"\"\n    tts_dur = get_duration(tts_file)\n    src_dur = get_duration(shot_file)\n    \n    cmd = [FFMPEG, '-y']\n    \n    if src_dur >= tts_dur:\n        # 视频够长，直接裁剪\n        cmd.extend(['-t', str(tts_dur), '-i', str(shot_file)])\n    else:\n        # 视频不够长，循环填充\n        cmd.extend(['-stream_loop', '-1', '-i', str(shot_file),\n                     '-t', str(tts_dur)])\n    \n    cmd.extend(['-c:v', 'libx264', '-preset', 'fast', str(output_file)])\n    subprocess.run(cmd, check=True)\n    \n    # 验证输出时长\n    out_dur = get_duration(output_file)\n    diff = abs(out_dur - tts_dur)\n    if diff > 0.5:\n        print(f\"⚠️ 时长偏差 {diff:.2f}s: {output_file.name}\")\n    \n    return tts_dur\n\n# 批量处理所有段\ntotal = 0.0\nfor i, (tts_file, shot_file) in enumerate(segments):\n    dur = process_segment(tts_file, shot_file, f\"seg_{i:03d}.mp4\")\n    total += dur\n\nprint(f\"总时长: {total:.2f}s\")\n```\n\n### 短镜头循环填充策略\n\n当源视频短于TTS时，用stream_loop让视频循环播放：\n\n```bash\n/opt/homebrew/bin/ffmpeg -y -stream_loop -1 -i shot.mp4 -t {tts_dur} -c:v libx264 -preset fast seg.mp4\n```\n\n**循环填充的视觉容忍度：**\n| 循环次数 | 观众感知 | 建议 |\n|---------|---------|------|\n| 1次（补0-5s） | 几乎察觉不到 | ✅ 可用 |\n| 2次（补5-10s） | 部分观众能察觉 | ⚠️ 谨慎使用 |\n| 3次以上（补>10s） | 明显重复感 | ❌ 建议换镜头或补新素材 |\n\n### 音画同步验证\n\n合成后必须逐段验证：\n\n```python\ndef verify_sync(segments_dir, tts_dir):\n    \"\"\"验证所有段的音画同步\"\"\"\n    issues = []\n    for i in range(25):\n        seg = Path(segments_dir) / f\"seg_{i:03d}.mp4\"\n        tts = Path(tts_dir) / f\"tts_{i:03d}.mp3\"\n        \n        seg_dur = get_duration(seg)\n        tts_dur = get_duration(tts)\n        diff = seg_dur - tts_dur\n        \n        if abs(diff) > 0.5:\n            issues.append(f\"#{i}: 偏差{diff:+.2f}s\")\n    \n    if issues:\n        print(\"⚠️ 同步问题:\")\n        for issue in issues:\n            print(f\"  {issue}\")\n    else:\n        print(\"✅ 全部同步\")\n```\n\n---\n\n## 五、字幕生成\n\n### Pillow字幕生成模板\n\n```python\nfrom PIL import Image, ImageDraw, ImageFont\n\ndef create_subtitle(text, role=\"\", output_path=\"sub.png\"):\n    \"\"\"生成字幕PNG\"\"\"\n    WIDTH, HEIGHT = 1920, 160\n    img = Image.new('RGBA', (WIDTH, HEIGHT), (0, 0, 0, 0))\n    draw = ImageDraw.Draw(img)\n    \n    font = ImageFont.truetype('/System/Library/Fonts/PingFang.ttc', 48)\n    \n    full_text = f\"{role}：{text}\" if role else text\n    \n    # 黑色描边 + 白色填充\n    draw.text((WIDTH//2, HEIGHT//2), full_text, \n              fill='white', font=font, anchor='mm',\n              stroke_width=3, stroke_fill='black')\n    \n    img.save(output_path)\n```\n\n### FFmpeg叠加字幕\n\n```bash\n/opt/homebrew/bin/ffmpeg -y -i {video}.mp4 -i {subtitle}.png \\\n  -filter_complex \"overlay=0:H-h\" \\\n  -c:v libx264 -preset fast {output}.mp4\n```\n\n---\n\n## 六、最终合成\n\n### 视频拼接\n\n```python\nimport subprocess\nfrom pathlib import Path\n\ndef concat_videos(seg_dir, output_path):\n    \"\"\"拼接所有分段视频\"\"\"\n    segs = sorted(Path(seg_dir).glob(\"seg_*.mp4\"))\n    \n    # 生成file list\n    list_path = Path(seg_dir) / \"video_list.txt\"\n    with open(list_path, 'w') as f:\n        for seg in segs:\n            f.write(f\"file '{seg.absolute()}'\\n\")\n    \n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-f', 'concat', '-safe', '0',\n        '-i', str(list_path),\n        '-c', 'copy',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n### 音频拼接\n\n```python\ndef concat_audios(audio_dir, output_path):\n    \"\"\"拼接所有TTS音频\"\"\"\n    audios = sorted(Path(audio_dir).glob(\"*.mp3\"))\n    \n    list_path = Path(audio_dir) / \"audio_list.txt\"\n    with open(list_path, 'w') as f:\n        for audio in audios:\n            f.write(f\"file '{audio.absolute()}'\\n\")\n    \n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-f', 'concat', '-safe', '0',\n        '-i', str(list_path),\n        '-c', 'copy',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n### 音视频合并\n\n```python\ndef merge_av(video_path, audio_path, output_path):\n    \"\"\"合并视频和音频\"\"\"\n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-i', str(video_path),\n        '-i', str(audio_path),\n        '-c:v', 'copy',\n        '-c:a', 'aac',\n        '-shortest',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n---\n\n## 七、素材导出\n\n### 桌面文件夹结构\n\n```python\nimport os, shutil\n\ndef export_to_desktop(project_name, segments_data, desktop_path):\n    \"\"\"导出结构化素材到桌面\"\"\"\n    base = os.path.join(desktop_path, project_name)\n    \n    dirs = {\n        \"01_字幕\": \"subtitle_pngs\",\n        \"02_配音\": \"tts_mp3s\",\n        \"03_主图\": \"thumbnails\",\n        \"04_视频\": \"seg_videos\",\n        \"05_矩阵表\": \"matrix\"\n    }\n    \n    for name in dirs:\n        os.makedirs(os.path.join(base, name), exist_ok=True)\n    \n    # 生成矩阵表HTML\n    generate_matrix_html(segments_data, os.path.join(base, \"05_矩阵表\", \"矩阵表.html\"))\n    \n    # 生成JSON\n    generate_json(segments_data, os.path.join(base, \"05_矩阵表\", \"素材结构.json\"))\n```\n\n---\n\n## 八、成本核算\n\n### 完整成本模型\n\n```python\ndef calculate_cost(params):\n    \"\"\"\n    params = {\n        'shot_seconds': 234,      # 镜头总时长\n        'retry_times': 3,          # 平均重试次数\n        'tts_chars': 350,          # TTS总字数\n        'dialog_rounds': 250,      # WorkBuddy对话轮次\n        'project_days': 2,         # 项目天数\n    }\n    \"\"\"\n    grok = params['shot_seconds'] * 0.05 * params['retry_times']\n    tts = params['tts_chars'] * 0.0006 * 1.5  # 含重试\n    wb = params['dialog_rounds'] * 0.0022 * 1.5  # 含隐性消耗\n    hw = 3.65 * params['project_days']  # 硬件折旧\n    power = 0.62 * params['project_days']  # 电费\n    \n    return {\n        'Grok Imagine': grok,\n        'TTS配音': tts,\n        'WorkBuddy算力': wb,\n        '硬件折旧': hw,\n        '电费': power,\n        '总计': grok + tts + wb + hw + power\n    }\n```\n\n### 参考成本（基于三体EP1实战）\n\n| 项目规模 | 预估成本 | 制作周期 |\n|---------|---------|---------|\n| 30秒 / 6镜头 | ¥10-15 | 0.5天 |\n| 60秒 / 12镜头 | ¥20-30 | 1天 |\n| 128秒 / 25镜头 | ¥40-50 | 2天 |\n| 5分钟 / 50镜头 | ¥80-120 | 3-4天 |\n\n---\n\n## 九、常见问题排查\n\n### 视频生成失败\n- **症状**: API返回错误或超时\n- **排查**: 检查API Key是否有效、余额是否充足\n- **解决**: 重试（换IP节点）、切换模型\n\n### TTS卡住\n- **症状**: status一直=0\n- **排查**: 检查参数格式（扁平JSON）\n- **解决**: 重新提交任务\n\n### 音画不同步\n- **症状**: 画面和声音对不上\n- **排查**: 检查每段TTS时长和视频裁剪时长\n- **解决**: 逐段精确裁剪，不要整体缩放\n\n### 字幕不显示\n- **症状**: 视频没有字幕\n- **排查**: 检查FFmpeg版本是否支持drawtext\n- **解决**: 用Pillow生成PNG + overlay叠加\n\n### 视频拼接报错\n- **症状**: concat失败\n- **排查**: 检查所有分段视频编码是否一致\n- **解决**: 统一用libx264编码重新转码\n\n---\n\n## 十、专业审核与迭代流程\n\nAI生成的第一版几乎从来不是最终版。必须经过\"制作→审核→修改\"的迭代循环。\n\n### 10.1 六维审核检查表\n\n| 维度 | 检查方法 | 判定标准 |\n|------|---------|---------|\n| **① 音画同步** | 逐段播放，对比画面内容与配音台词 | 角色A说话时画面必须是角色A |\n| **② 时长匹配** | ffprobe对比每段视频和TTS时长 | 偏差 < 0.5s |\n| **③ 视觉重复** | 检查stream_loop循环次数 | 不超过2次循环 |\n| **④ 字幕准确** | 逐句对照字幕文本和TTS台词 | 无错别字、标点正确 |\n| **⑤ 节奏感** | 整体观看，标记拖沓或仓促段落 | 每段TTS时长占镜头60-80%最佳 |\n| **⑥ 画面质量** | 检查AI生成瑕疵 | 无变形、闪烁、分辨率异常 |\n\n### 10.2 问题分级与修复优先级\n\n```\nP0（必须修复）—— 影响观看体验的根本问题\n├── 音画不匹配：画面内容与台词无关\n├── 字幕错误：错别字、台词与字幕不一致\n├── 画面截断：话没说完画面就切了\n└── 时长严重偏差：偏差 > 1s\n→ 优先级：最高，不修不能交付\n\nP1（建议修复）—— 影响观看体验但可接受\n├── 节奏拖沓：某段画面太长，观众失去耐心\n├── 视觉重复感：循环超过2次\n├── 转场生硬：相邻镜头切换突兀\n└── 音色不匹配：角色音色与形象不符\n→ 优先级：中，尽量修\n\nP2（可优化）—— 锦上添花\n├── 画面色调不统一\n├── 字幕样式可美化\n├── 背景音效可丰富\n└── 片头片尾可添加\n→ 优先级：低，有时间再修\n```\n\n### 10.3 迭代工作流\n\n```python\ndef review_and_fix(version, issues):\n    \"\"\"\n    version: 当前版本号\n    issues: 审核发现的问题列表\n    \n    返回: 是否需要继续迭代\n    \"\"\"\n    p0_count = sum(1 for i in issues if i['level'] == 'P0')\n    p1_count = sum(1 for i in issues if i['level'] == 'P1')\n    \n    print(f\"版本 {version} 审核结果:\")\n    print(f\"  P0(必须修): {p0_count}\")\n    print(f\"  P1(建议修): {p1_count}\")\n    print(f\"  P2(可优化): {len(issues) - p0_count - p1_count}\")\n    \n    if p0_count > 0:\n        print(\"→ 进入下一轮迭代\")\n        return True\n    elif p1_count > 2:\n        print(\"→ 建议再修一轮\")\n        return True\n    else:\n        print(\"→ 达到交付标准 ✅\")\n        return False\n```\n\n### 10.4 实战案例：三体EP1迭代记录\n\n| 版本 | 时长 | 问题发现 | 修复内容 | 审核结论 |\n|------|------|---------|---------|---------|\n| v5min | 252s | 视频总长252s但TTS仅127s，大量空白段落 | 重新按TTS时长裁剪 | ❌ P0: 节奏断裂 |\n| v6 | — | 音频驱动剪辑，3个短镜头被截断 | 修复中 | ❌ 未完成 |\n| v7 | 127s | 3个短镜头截断：火鸡演讲缺9s | stream_loop循环填充 | ❌ P0: 画面截断 |\n| v7.1 | 127.9s | 循环修复完成，但无字幕 | 加字幕 | ⚠️ P1: 缺字幕 |\n| v8 | 127.9s | 字幕+音画同步修复+矩阵表 | 全部修复 | ✅ 交付 |\n\n### 10.5 审核工具脚本\n\n```python\n#!/usr/bin/env python3\n\"\"\"一键审核脚本：检查所有段的音画同步和时长匹配\"\"\"\n\nimport subprocess\nfrom pathlib import Path\n\nFFPROBE = '/opt/homebrew/bin/ffprobe'\n\ndef get_duration(p):\n    r = subprocess.run([FFPROBE,'-v','quiet','-show_entries','format=duration',\n                        '-of','csv=p=0',str(p)], capture_output=True, text=True)\n    return float(r.stdout.strip())\n\ndef audit(segments_dir, tts_dir, num_segments=25):\n    issues = []\n    print(f\"{'#':>3} {'角色':<20} {'TTS':>7} {'视频':>7} {'偏差':>7} {'状态'}\")\n    print(\"-\" * 55)\n    \n    for i in range(num_segments):\n        seg = Path(segments_dir) / f\"seg_{i:03d}.mp4\"\n        tts = sorted(Path(tts_dir).glob(\"*.mp3\"))[i]\n        \n        seg_dur = get_duration(seg) if seg.exists() else 0\n        tts_dur = get_duration(tts)\n        diff = seg_dur - tts_dur\n        \n        status = \"✅\" if abs(diff) < 0.5 else \"⚠️\"\n        if abs(diff) > 0.5:\n            issues.append(f\"#{i}: 偏差{diff:+.2f}s\")\n        \n        print(f\"{i:3d} {tts.stem:<20s} {tts_dur:>6.2f}s {seg_dur:>6.2f}s {diff:>+6.2f}s {status}\")\n    \n    print(f\"\\n问题段: {len(issues)}\")\n    for issue in issues:\n        print(f\"  {issue}\")\n    \n    return issues\n\nif __name__ == '__main__':\n    audit(Path('v7_assets'), Path('ep1_tts'))\n```\n\nFile v1.0.2:references/sucuang_api.md\n\n# 速创API 接口文档与踩坑经验\n\n## 平台信息\n\n- **平台地址**: https://api.wuyinkeji.com\n- **文档中心**: https://api.wuyinkeji.com/doc\n- **API Key获取**: 注册登录后进入控制台获取\n\n## 通用鉴权方式\n\n**推荐方式 — Authorization Header（不带Bearer前缀）：**\n```python\nHEADERS = {\n    \"Authorization\": \"你的API_KEY\",\n    \"Content-Type\": \"application/json\"\n}\n```\n\n**❌ 不要用URL参数传key：**\n```python\n# 会返回403，不要这样用\nrequests.get(\"https://api.wuyinkeji.com/api/xxx?key=你的API_KEY\")\n```\n\n---\n\n## 1. Grok Imagine 视频生成\n\n### 接口信息\n- **接口**: POST `/api/async/video/grok_imagine`\n- **价格**: ¥0.05/秒（按生成视频时长计费，不足1秒按1秒）\n- **点数**: 5点/秒\n- **免费额度**: 无\n- **QPS限制**: 100次/秒\n- **每日限制**: 付费用户不限制\n\n### 请求参数\n```json\n{\n  \"prompt\": \"英文描述效果更稳定，包含场景、光线、构图、镜头运动\",\n  \"duration\": 10,\n  \"style\": \"cinematic\"\n}\n```\n\n### 结果查询\n- **接口**: `GET /api/async/detail?id=xxx`\n- **轮询策略**: 每5秒查询一次\n- **状态码**: status=2 表示完成，status=0/1 表示处理中\n- **返回内容**: 包含视频下载URL\n\n### 批量生成策略\n```python\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\n\ndef submit_shot(shot):\n    # 提交生成任务\n    resp = requests.post(url, headers=HEADERS, json=params)\n    task_id = resp.json()[\"data\"][\"id\"]\n    # 轮询直到完成\n    while True:\n        result = requests.get(f\"{BASE}/detail?id={task_id}\", headers=HEADERS)\n        if result.json()[\"data\"][\"status\"] == 2:\n            return download_video(result.json()[\"data\"][\"video_url\"])\n        time.sleep(5)\n\n# 批量25个镜头同时提交\nwith ThreadPoolExecutor(max_workers=10) as executor:\n    futures = [executor.submit(submit_shot, shot) for shot in SHOTS]\n    for future in as_completed(futures):\n        results.append(future.result())\n```\n\n### 踩坑经验\n- Sora2接口（sora2/video）已不可用，持续返回400错误，全部使用Grok Imagine\n- 英文Prompt比中文Prompt效果更稳定\n- 平均重试3次才能获得满意结果\n- 生成耗时约30-60秒/个\n\n---\n\n## 2. TTS配音生成\n\n### 接口信息\n- **接口**: `POST /api/async/audio_tts`\n- **价格**: ¥0.0006/字\n- **返回格式**: tar包（需解压获取mp3）\n\n### 请求参数（重要：扁平JSON）\n```json\n{\n  \"text\": \"台词内容\",\n  \"voice_id\": \"male-qn-jingying\",\n  \"speed\": 1.0\n}\n```\n\n### 可用音色列表\n| 音色ID | 描述 | 适用角色 |\n|--------|------|---------|\n| male-qn-jingying | 精英青年男声 | 旁白、汪淼、常伟思 |\n| male-qn-badao | 霸道男声 | 史强 |\n| male-qn-daxuesheng | 大学生男声 | 研究员 |\n| male-chunhou | 醇厚男声 | 长辈角色 |\n| junlang_nanyou | 俊朗男声 | 潘寒 |\n| female-chengshu | 成熟女声 | 申玉菲 |\n| female-shaonv | 少女音 | 杨冬 |\n\n### 踩坑经验（重要）\n1. **❌ 不要传 format 参数** — 会报500\"存在未绑定的参数\"\n2. **❌ 不要嵌套参数** — 不要写成 `{\"model\":\"audio_tts\",\"params\":{...}}`，直接扁平JSON\n3. **✅ 状态码判断** — 用 `status == 2` 判断完成，不要用字符串 `\"completed\"`\n4. **⚠️ 部分任务会卡住** — status一直=0，重试可换到不同IP节点\n5. **✅ 返回tar包** — 需要用 `tarfile` 解压获取mp3文件\n\n### TTS生成代码模板\n```python\nimport requests, time, tarfile, io\n\ndef generate_tts(text, voice_id, output_path):\n    payload = {\"text\": text, \"voice_id\": voice_id, \"speed\": 1.0}\n    resp = requests.post(f\"{BASE}/api/async/audio_tts\", headers=HEADERS, json=payload)\n    task_id = resp.json()[\"data\"][\"id\"]\n\n    while True:\n        result = requests.get(f\"{BASE}/api/async/detail?id={task_id}\", headers=HEADERS)\n        data = result.json()[\"data\"]\n        if data[\"status\"] == 2:  # 完成\n            audio_url = data[\"audio_url\"]\n            audio_resp = requests.get(audio_url)\n            tar = tarfile.open(fileobj=io.BytesIO(audio_resp.content))\n            for member in tar.getmembers():\n                if member.name.endswith('.mp3'):\n                    f = tar.extractfile(member)\n                    with open(output_path, 'wb') as out:\n                        out.write(f.read())\n            return\n        elif data[\"status\"] == -1:  # 失败\n            raise Exception(f\"TTS failed: {data}\")\n        time.sleep(3)\n```\n\n---\n\n## 3. 数字人视频生成\n\n### 接口信息\n- **接口**: `POST /api/async/video_digital_humans`\n- **价格**: 按次计费\n\n### 请求参数\n```json\n{\n  \"audio_url\": \"公网可访问的音频URL\",\n  \"video_url\": \"公网可访问的视频URL\"\n}\n```\n\n### 注意事项\n- 音频和视频URL必须公网可访问\n- 推荐搭配云存储服务存储素材\n\n---\n\n## 4. 云存储配置（素材存储）\n\n如需存储视频和音频文件，推荐使用云存储服务：\n- 腾讯云COS\n- 阿里云OSS\n- AWS S3\n\n请根据实际需求配置您自己的云存储凭证。\n\n---\n\n## 5. 其他可用模型\n\n速创API平台还提供以下模型（价格以平台实际为准）：\n- 文生图模型（多种）\n- 视频编辑模型\n- 语音识别\n- 大语言模型对话\n\n具体价格请查看：https://api.wuyinkeji.com/type/all\n\nArchive v1.0.1: 4 files, 16416 bytes\n\nFiles: references/production_workflow.md (15821b), references/sucuang_api.md (5282b), SKILL.md (12752b), _meta.json (141b)\n\nFile v1.0.1:SKILL.md\n\n---\nname: ai-short-film-producer\ndescription: 低成本AI短剧/短片全流程制作技能。使用速创API(wuyinkeji.com)的Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成，WorkBuddy编排全流程。适用于用户需要从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动剪辑、字幕叠加、最终合成、成本核算的全套SOP。\n---\n\n# AI Short Film Producer - 低成本AI短剧制作\n\n## 概述\n\n本Skill提供一套完整的**低成本AI短剧制作流程**，从脚本创作到最终成片，总成本仅需**¥30-50/部**（128秒短片）。核心思路：用AI API生成素材 → 本地FFmpeg合成 → WorkBuddy编排调度。\n\n**适用场景：**\n- 用户说\"帮我做一个短片/短剧/预告片\"\n- 用户说\"把这段文案做成视频\"\n- 用户说\"生成一个XX题材的短视频\"\n- 用户需要从零到一完成AI视频制作\n\n**核心成本优势：**\n- 视频生成：Grok Imagine ¥0.05/秒（速创API）\n- 配音生成：TTS ¥0.0006/字（速创API）\n- 合成剪辑：本地FFmpeg免费\n- AI编排：WorkBuddy Lite版约¥0.0022/轮\n\n---\n\n## 制作流程总览\n\n```\nStep 1: 脚本创作\n  ├── 确定主题/时长/风格\n  ├── 编写分镜脚本（镜头×台词×角色）\n  └── 输出：分镜表 + TTS文本清单\n\nStep 2: 视频镜头生成\n  ├── 调用速创API Grok Imagine\n  ├── 25个镜头批量异步生成\n  └── 输出：ep1_shots/*.mp4\n\nStep 3: TTS配音生成\n  ├── 调用速创API audio_tts\n  ├── 多角色多音色\n  └── 输出：ep1_tts/*.mp3\n\nStep 4: 音频驱动剪辑\n  ├── 逐段按TTS时长裁剪/循环镜头\n  ├── 短镜头自动stream_loop填充\n  └── 输出：分段seg_*.mp4\n\nStep 5: 字幕生成\n  ├── Python Pillow生成透明PNG字幕\n  ├── FFmpeg overlay叠加（因FFmpeg 8.x无drawtext）\n  └── 输出：带字幕的分段视频\n\nStep 6: 最终合成\n  ├── concat拼接25段视频\n  ├── concat拼接25段音频\n  ├── 音视频合并\n  └── 输出：最终成片.mp4\n\nStep 7: 素材导出\n  ├── 结构化桌面文件夹\n  ├── 矩阵表 + JSON\n  └── 成本核算\n```\n\n---\n\n## 详细步骤\n\n### Step 1: 脚本创作\n\n**输入：** 用户需求（主题、风格、时长、参考素材）\n**输出：** 分镜脚本文档 + TTS台词清单\n\n**工作流程：**\n1. 与用户确认主题方向（科幻/悬疑/科普/剧情等）\n2. 编写分镜脚本，包含：\n   - 镜头编号、画面描述、时长\n   - 配音台词、角色分配、音色选择\n   - 音效说明\n3. 输出TTS台词清单（25段以内，每段2-20字最佳）\n4. 角色音色分配表：\n\n| 角色类型 | 推荐音色ID | 说明 |\n|---------|-----------|------|\n| 旁白/叙述者 | male-qn-jingying | 精英青年男声，通用 |\n| 男主角 | male-qn-jingying | 精英青年男声 |\n| 霸道/硬汉 | male-qn-badao | 霸道男声 |\n| 反派/俊朗 | junlang_nanyou | 俊朗男声 |\n| 成熟女性 | female-chengshu | 成熟女声 |\n| 少女 | female-shaonv | 少女音 |\n| 研究员/学生 | male-qn-daxuesheng | 大学生男声 |\n| 醇厚长辈 | male-chunhou | 醇厚男声 |\n\n### Step 2: 视频镜头生成（速创API Grok Imagine）\n\n**API平台：** 速创API https://api.wuyinkeji.com\n**模型：** Grok Imagine（xAI Aurora引擎）\n**价格：** ¥0.05/秒（按生成视频时长计费，不足1秒按1秒）\n\n**API调用方式：**\n- 鉴权：Authorization Header 传API Key（不带Bearer前缀）\n- 接口：POST /api/async/video/grok_imagine\n- 参数格式：扁平JSON\n- 结果查询：GET /api/async/detail?id=xxx（轮询直到status=2）\n\n**批量生成策略：**\n1. 25个镜头同时提交（用ThreadPoolExecutor）\n2. 每个镜头约10秒，生成耗时约30-60秒\n3. 失败自动重试（平均重试3次）\n4. 注意：Sora2接口已不可用（持续400错误），全部使用Grok Imagine\n\n**Prompt编写要点：**\n- 英文Prompt效果更稳定\n- 包含：场景描述、光线、构图、镜头运动\n- 示例：`\"Deep space, Milky Way galaxy slowly rotating, cinematic wide shot, photorealistic, 4K quality\"`\n\n### Step 3: TTS配音生成（速创API audio_tts）\n\n**API接口：** POST /api/async/audio_tts\n**价格：** ¥0.0006/字\n**参数格式（重要）：** 扁平JSON，不要嵌套\n\n```json\n{\n  \"text\": \"台词内容\",\n  \"voice_id\": \"male-qn-jingying\",\n  \"speed\": 1.0\n}\n```\n\n**注意事项（踩坑经验）：**\n- ❌ 不要传 format 参数（会报500\"存在未绑定的参数\"）\n- ❌ 不要嵌套成 `{\"model\":\"audio_tts\",\"params\":{...}}`\n- ✅ 状态码判断：status=2 完成，status=0/1 处理中\n- ⚠️ 部分任务会卡住（status一直=0），重试可换IP节点\n- ✅ 返回tar包，需解压获取mp3\n\n### Step 4: 音频驱动剪辑（核心节奏控制）\n\n**核心理念：** 画面长度由语音旁白决定，而非固定时长。先录制/生成TTS配音，再让每段视频精确匹配对应配音的时长。这样保证音画天然同步，且节奏由配音自然驱动。\n\n#### 4.1 节奏控制逻辑\n\n```\n每段（镜头, TTS）的处理流程：\n\n1. 获取TTS音频实际时长 tts_dur（用ffprobe精确到毫秒）\n2. 获取源视频时长 src_dur\n3. 对比决策：\n   ├── src_dur >= tts_dur + 0.5s  → 直接裁剪到tts_dur（视频多出的部分舍弃）\n   ├── src_dur ≈ tts_dur（差<0.5s）→ 直接裁剪，不做额外处理\n   └── src_dur < tts_dur           → stream_loop循环播放填满tts_dur\n4. 输出：seg_NNN.mp4（时长=tts_dur，精确匹配配音）\n```\n\n**为什么用\"音频驱动\"而非\"视频驱动\"：**\n- 传统剪辑：先定视频长度，再往里塞配音 → 配音节奏被画面绑架\n- 音频驱动：先定配音节奏，再裁剪画面适配 → 叙事节奏由台词自然决定\n- 效果：观众听到的每句话都有对应的画面时长，不会出现\"话没说完画面就切了\"\n\n#### 4.2 短镜头循环填充（stream_loop）\n\n当源视频时长不够时，用FFmpeg的stream_loop让视频循环播放：\n\n```bash\n# 循环播放直到填满tts_dur\n/opt/homebrew/bin/ffmpeg -y -stream_loop -1 -i shot.mp4 -t {tts_dur} -c:v libx264 -preset fast seg.mp4\n```\n\n**实战经验（三体EP1）：**\n- 25个镜头中有3个需要循环填充\n- 最大修复：pan_han_02火鸡演讲（源视频10s → TTS需要19s，循环补9s）\n- 循环填充的视觉重复感在1-2次循环内不明显，超过3次建议换镜头\n\n#### 4.3 逐段精确裁剪避免累积漂移\n\n```python\n# 关键：每段独立裁剪，不整体缩放\ncumulative = 0.0\nfor i, (tts_file, shot_file) in enumerate(segments):\n    tts_dur = get_duration(tts_file)  # ffprobe获取\n    # 精确裁剪到tts_dur，不依赖前一段的结束时间\n    trim_video(shot_file, tts_dur, f\"seg_{i:03d}.mp4\")\n    cumulative += tts_dur\n\n# 最终验证：所有seg时长之和 ≈ audio_concat时长 ≈ 最终成片时长\n```\n\n**FFmpeg路径（Mac mini M4）：** `/opt/homebrew/bin/ffmpeg`\n\n**已知限制：**\n- FFmpeg 8.x 未编译drawtext/libass/freetype滤镜 → 不能直接加字幕\n- anullsrc语法用 `cl=stereo` 而非 `c=stereo`\n- shell转义用Python subprocess list模式避免zsh问题\n\n### Step 5: 字幕生成\n\n**方案：** Pillow生成透明PNG → FFmpeg overlay叠加\n\n```python\nfrom PIL import Image, ImageDraw, ImageFont\n\n# 创建透明PNG\nimg = Image.new('RGBA', (1920, 160), (0,0,0,0))\ndraw = ImageDraw.Draw(img)\nfont = ImageFont.truetype('/System/Library/Fonts/PingFang.ttc', 48)\n\n# 白色大字 + 黑色描边\ndraw.text((960, 80), \"台词文本\", fill='white', font=font, \n          anchor='mm', stroke_width=3, stroke_fill='black')\n\n# FFmpeg overlay叠加\nffmpeg -i seg.mp4 -i sub.png -filter_complex \"overlay=0:H-h\" output.mp4\n```\n\n**字幕设计规范：**\n- 底部居中，距底部约60px\n- 白色大字 + 3px黑色描边\n- 字号48-56px（PingFang SC字体）\n- 可加角色标签（如\"旁白：\"、\"汪淼：\"）\n\n### Step 6: 最终合成\n\n**拼接视频：**\n```bash\n# 生成file list\nfor f in seg_*.mp4; do echo \"file '$f'\" >> video_list.txt; done\nffmpeg -f concat -safe 0 -i video_list.txt -c copy video_concat.mp4\n```\n\n**拼接音频：**\n```bash\nfor f in audio_*.mp3; do echo \"file '$f'\" >> audio_list.txt; done\nffmpeg -f concat -safe 0 -i audio_list.txt -c copy audio_concat.aac\n```\n\n**音视频合并：**\n```bash\nffmpeg -i video_concat.mp4 -i audio_concat.aac -c:v copy -c:a aac final.mp4\n```\n\n### Step 7: 素材导出与成本核算\n\n**桌面文件夹结构：**\n```\n~/Desktop/项目名称/\n├── 01_字幕/     → 字幕PNG文件\n├── 02_配音/     → TTS音频MP3\n├── 03_主图/     → 镜头缩略图JPG\n├── 04_视频/     → 分段视频MP4\n├── 05_矩阵表/   → 矩阵表.html + 素材结构.json\n└── 最终成片.mp4\n```\n\n**成本核算模板：**\n\n| 项目 | 计算方式 | 参考单价 |\n|------|---------|---------|\n| Grok Imagine视频 | 总秒数 × 重试次数 × ¥0.05 | ¥0.05/秒 |\n| TTS配音 | 总字数 × ¥0.0006 | ¥0.0006/字 |\n| WorkBuddy算力 | 对话轮次 × ¥0.0022 | ¥0.0022/轮 |\n| 硬件折旧 | Mac mini ¥3,999/3年寿命 | ¥3.65/天 |\n| 电费 | 16h × 65W × ¥0.6/度 | ¥0.62/天 |\n\n---\n\n## 速创API平台速查\n\n**平台地址：** https://api.wuyinkeji.com\n**文档中心：** https://api.wuyinkeji.com/doc\n\n**常用模型及价格：**\n\n| 模型/接口 | 价格 | 说明 |\n|-----------|------|------|\n| Grok Imagine 视频生成 | ¥0.05/秒 | 文生视频/图生视频，6-15秒 |\n| audio_tts 配音 | ¥0.0006/字 | 多音色TTS |\n| video_digital_humans 数字人 | 按次计费 | 需公网音频URL+视频URL |\n| Sora2（已弃用） | — | 持续400错误，不可用 |\n\n**API Key传递：**\n- ✅ Authorization Header（推荐，不带Bearer前缀）\n- ❌ URL参数 ?key=xxx（会返回403）\n\n---\n\n## 三体EP1实战参考\n\n**项目规模：** 25个镜头，127秒成片，8个角色\n**总成本：** ¥44.17（含重试+硬件折旧）\n**工具链：** Grok Imagine × 25 + TTS × 25 + FFmpeg + Python Pillow\n**迭代版本：** v5min → v6 → v7 → v7.1 → v8（5个版本迭代）\n\n**关键经验：**\n1. Sora2不可用，全部切Grok Imagine\n2. 源视频短于TTS时用stream_loop循环填充\n3. FFmpeg 8.x无drawtext，用Pillow生成PNG替代\n4. TTS部分任务卡住需重试\n5. 逐段精确裁剪避免累积漂移\n\n---\n\n## 专业审核与迭代流程\n\nAI生成的第一版通常不是最终版。必须经过\"制作→审核→修改\"的迭代循环才能达到交付标准。\n\n### 审核维度\n\n| 维度 | 检查内容 | 常见问题 |\n|------|---------|---------|\n| **音画同步** | 画面内容是否匹配配音台词 | 角色A说话但画面是角色B |\n| **时长匹配** | 每段视频是否完整覆盖TTS | 短镜头被截断，话没说完画面就切 |\n| **视觉重复** | 循环播放是否超过3次 | 火鸡演讲循环9s，观众能看出重复 |\n| **字幕准确** | 字幕文本是否与TTS一致 | 错别字、标点错误 |\n| **节奏感** | 整体叙事节奏是否流畅 | 某段太长拖沓，某段太短仓促 |\n| **画面质量** | 是否有明显AI生成瑕疵 | 人物变形、闪烁、分辨率低 |\n\n### 迭代流程\n\n```\nV1（初版合成）\n  ↓\n专业审核（逐段检查以上6个维度）\n  ↓\n问题清单 → 按严重程度排序\n  ├── P0（必须修）：音画不匹配、字幕错误、画面截断\n  ├── P1（建议修）：节奏拖沓、视觉重复感强\n  └── P2（可优化）：画面质量、色调统一\n  ↓\nV2（修复P0问题）\n  ↓\n再次审核\n  ↓\nV3...（逐轮修复，直到P0=0、P1≤2）\n  ↓\n最终交付\n```\n\n### 实战案例：三体EP1迭代记录\n\n| 版本 | 问题 | 修复方案 |\n|------|------|---------|\n| v5min | 252秒成片，但TTS只有127秒，大量空白 | 重新按TTS时长裁剪 |\n| v6 | 音频驱动剪辑，但3个短镜头被截断 | 修复中 |\n| v7 | 短镜头截断（火鸡演讲缺9s） | stream_loop循环填充 |\n| v7.1 | 循环修复完成，但无字幕 | 加字幕 |\n| v8 | 字幕+音画同步修复+矩阵表 | ✅ 最终交付 |\n\n**审核工具：**\n- 逐段对比：`ffprobe` 获取每段TTS和视频的精确时长\n- 偏差检查：每段TTS vs 视频时长差 > 0.5s 即标记为问题段\n- 画面检查：播放时逐段确认画面内容与台词匹配\n\n---\n\n## 资源文件\n\n### references/\n- `sucuang_api.md` — 速创API完整接口文档和踩坑经验\n- `production_workflow.md` — 制作流程详细参考\n\n### scripts/\n- （按需添加：批量提交脚本、合成脚本模板等）\n\n### assets/\n- （按需添加：字幕模板、片头片尾素材等）\n\nFile v1.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn703gwc11aqnnaatk69f339d9822e08\",\n  \"slug\": \"ai-short-film-producer\",\n  \"version\": \"1.0.1\",\n  \"publishedAt\": 1777542089858\n}\n\nFile v1.0.1:references/production_workflow.md\n\n# AI短剧制作流程详细参考\n\n## 一、项目启动\n\n### 需求确认\n与用户确认以下信息：\n1. **主题**：科幻/悬疑/科普/剧情/搞笑/教育等\n2. **风格**：写实/动画/赛博朋克/古风等\n3. **时长**：30秒/60秒/2分钟/5分钟\n4. **角色**：需要几个角色？是否有特定音色要求？\n5. **参考素材**：用户是否提供文案/图片/参考视频？\n\n### 脚本模板\n\n```markdown\n# 项目名称 · 分镜脚本\n\n## 总览\n- 总时长：XX秒\n- 镜头数：XX个\n- 角色数：XX个\n\n## 分镜表\n| # | 镜头ID | 画面描述 | 配音台词 | 角色 | 音色 | 时长 |\n|---|--------|---------|---------|------|------|------|\n| 1 | shot01_xxx | 画面描述 | 台词内容 | 角色名 | 音色ID | 10s |\n| 2 | shot02_xxx | 画面描述 | 台词内容 | 角色名 | 音色ID | 10s |\n```\n\n---\n\n## 二、视频生成\n\n### Grok Imagine Prompt编写指南\n\n**结构模板：**\n```\n[场景描述], [主体描述], [光线/氛围], [构图/镜头运动], [风格关键词]\n```\n\n**示例：**\n```\n\"Deep space, Milky Way galaxy slowly rotating across a star-filled cosmos,\ncountless stars twinkling, nebulae in deep blue and purple hues,\ncinematic wide shot, photorealistic, 4K quality, slow gentle rotation\"\n```\n\n**各类型场景Prompt关键词：**\n\n| 场景类型 | 关键词 |\n|---------|--------|\n| 太空/宇宙 | deep space, stars, nebula, galaxy, cosmic, celestial |\n| 城市/街头 | city street, urban, bustling, modern, buildings |\n| 室内/会议室 | conference room, modern, screens, professional |\n| 人物特写 | close-up, portrait, expression, emotion, cinematic lighting |\n| 自然/风景 | landscape, mountains, ocean, sunset, cinematic |\n| 科技/实验室 | laboratory, technology, screens, equipment, futuristic |\n\n### 批量提交策略\n\n1. 25个镜头同时提交到API\n2. 使用ThreadPoolExecutor(max_workers=10)\n3. 每5秒轮询一次结果\n4. 失败自动重试（最多5次）\n5. 下载后检查文件完整性（ffprobe验证时长）\n\n---\n\n## 三、TTS配音生成\n\n### 多角色音色分配策略\n\n| 角色数量 | 分配策略 |\n|---------|---------|\n| 1-2个角色 | 旁白用jingying，对话角色用对应音色 |\n| 3-5个角色 | 主要角色各分配独立音色，次要角色复用 |\n| 6-10个角色 | 核心角色独立音色，路人/群演用通用音色 |\n\n### 台词字数控制\n- 每段TTS建议2-20字（太长影响听感）\n- 10秒镜头配2-4秒台词最合适\n- 留白时间给观众消化内容\n\n---\n\n## 四、音频驱动剪辑（核心节奏控制）\n\n### 核心理念\n\n**音频驱动剪辑 = 画面长度由语音旁白决定，而非固定时长。**\n\n传统剪辑思维是\"先定视频长度，再往里塞配音\"，结果配音节奏被画面绑架。音频驱动反过来——先录制TTS配音，再让每段视频精确匹配对应配音的时长。这样：\n- 观众听到的每句话都有完整的画面时长\n- 叙事节奏由台词自然驱动\n- 不会出现\"话没说完画面就切了\"\n\n### 核心算法\n\n```\n对于每一段（镜头, TTS）：\n  1. 获取TTS音频时长 tts_dur（ffprobe精确到毫秒）\n  2. 获取源视频时长 src_dur\n  3. 对比决策：\n     ├── src_dur >= tts_dur + 0.5s  → 直接裁剪到tts_dur\n     ├── src_dur ≈ tts_dur（差<0.5s）→ 直接裁剪\n     └── src_dur < tts_dur           → stream_loop循环填充\n  4. 输出：seg_NNN.mp4（时长精确=tts_dur）\n```\n\n### 逐段精确裁剪（避免累积漂移）\n\n```python\nimport subprocess\nfrom pathlib import Path\n\nFFPROBE = '/opt/homebrew/bin/ffprobe'\nFFMPEG = '/opt/homebrew/bin/ffmpeg'\n\ndef get_duration(filepath):\n    \"\"\"获取媒体文件精确时长\"\"\"\n    result = subprocess.run(\n        [FFPROBE, '-v', 'quiet', '-show_entries', 'format=duration',\n         '-of', 'csv=p=0', str(filepath)],\n        capture_output=True, text=True\n    )\n    return float(result.stdout.strip())\n\ndef process_segment(tts_file, shot_file, output_file):\n    \"\"\"处理单段：按TTS时长裁剪/循环视频\"\"\"\n    tts_dur = get_duration(tts_file)\n    src_dur = get_duration(shot_file)\n    \n    cmd = [FFMPEG, '-y']\n    \n    if src_dur >= tts_dur:\n        # 视频够长，直接裁剪\n        cmd.extend(['-t', str(tts_dur), '-i', str(shot_file)])\n    else:\n        # 视频不够长，循环填充\n        cmd.extend(['-stream_loop', '-1', '-i', str(shot_file),\n                     '-t', str(tts_dur)])\n    \n    cmd.extend(['-c:v', 'libx264', '-preset', 'fast', str(output_file)])\n    subprocess.run(cmd, check=True)\n    \n    # 验证输出时长\n    out_dur = get_duration(output_file)\n    diff = abs(out_dur - tts_dur)\n    if diff > 0.5:\n        print(f\"⚠️ 时长偏差 {diff:.2f}s: {output_file.name}\")\n    \n    return tts_dur\n\n# 批量处理所有段\ntotal = 0.0\nfor i, (tts_file, shot_file) in enumerate(segments):\n    dur = process_segment(tts_file, shot_file, f\"seg_{i:03d}.mp4\")\n    total += dur\n\nprint(f\"总时长: {total:.2f}s\")\n```\n\n### 短镜头循环填充策略\n\n当源视频短于TTS时，用stream_loop让视频循环播放：\n\n```bash\n/opt/homebrew/bin/ffmpeg -y -stream_loop -1 -i shot.mp4 -t {tts_dur} -c:v libx264 -preset fast seg.mp4\n```\n\n**循环填充的视觉容忍度：**\n| 循环次数 | 观众感知 | 建议 |\n|---------|---------|------|\n| 1次（补0-5s） | 几乎察觉不到 | ✅ 可用 |\n| 2次（补5-10s） | 部分观众能察觉 | ⚠️ 谨慎使用 |\n| 3次以上（补>10s） | 明显重复感 | ❌ 建议换镜头或补新素材 |\n\n### 音画同步验证\n\n合成后必须逐段验证：\n\n```python\ndef verify_sync(segments_dir, tts_dir):\n    \"\"\"验证所有段的音画同步\"\"\"\n    issues = []\n    for i in range(25):\n        seg = Path(segments_dir) / f\"seg_{i:03d}.mp4\"\n        tts = Path(tts_dir) / f\"tts_{i:03d}.mp3\"\n        \n        seg_dur = get_duration(seg)\n        tts_dur = get_duration(tts)\n        diff = seg_dur - tts_dur\n        \n        if abs(diff) > 0.5:\n            issues.append(f\"#{i}: 偏差{diff:+.2f}s\")\n    \n    if issues:\n        print(\"⚠️ 同步问题:\")\n        for issue in issues:\n            print(f\"  {issue}\")\n    else:\n        print(\"✅ 全部同步\")\n```\n\n---\n\n## 五、字幕生成\n\n### Pillow字幕生成模板\n\n```python\nfrom PIL import Image, ImageDraw, ImageFont\n\ndef create_subtitle(text, role=\"\", output_path=\"sub.png\"):\n    \"\"\"生成字幕PNG\"\"\"\n    WIDTH, HEIGHT = 1920, 160\n    img = Image.new('RGBA', (WIDTH, HEIGHT), (0, 0, 0, 0))\n    draw = ImageDraw.Draw(img)\n    \n    font = ImageFont.truetype('/System/Library/Fonts/PingFang.ttc', 48)\n    \n    full_text = f\"{role}：{text}\" if role else text\n    \n    # 黑色描边 + 白色填充\n    draw.text((WIDTH//2, HEIGHT//2), full_text, \n              fill='white', font=font, anchor='mm',\n              stroke_width=3, stroke_fill='black')\n    \n    img.save(output_path)\n```\n\n### FFmpeg叠加字幕\n\n```bash\n/opt/homebrew/bin/ffmpeg -y -i {video}.mp4 -i {subtitle}.png \\\n  -filter_complex \"overlay=0:H-h\" \\\n  -c:v libx264 -preset fast {output}.mp4\n```\n\n---\n\n## 六、最终合成\n\n### 视频拼接\n\n```python\nimport subprocess\nfrom pathlib import Path\n\ndef concat_videos(seg_dir, output_path):\n    \"\"\"拼接所有分段视频\"\"\"\n    segs = sorted(Path(seg_dir).glob(\"seg_*.mp4\"))\n    \n    # 生成file list\n    list_path = Path(seg_dir) / \"video_list.txt\"\n    with open(list_path, 'w') as f:\n        for seg in segs:\n            f.write(f\"file '{seg.absolute()}'\\n\")\n    \n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-f', 'concat', '-safe', '0',\n        '-i', str(list_path),\n        '-c', 'copy',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n### 音频拼接\n\n```python\ndef concat_audios(audio_dir, output_path):\n    \"\"\"拼接所有TTS音频\"\"\"\n    audios = sorted(Path(audio_dir).glob(\"*.mp3\"))\n    \n    list_path = Path(audio_dir) / \"audio_list.txt\"\n    with open(list_path, 'w') as f:\n        for audio in audios:\n            f.write(f\"file '{audio.absolute()}'\\n\")\n    \n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-f', 'concat', '-safe', '0',\n        '-i', str(list_path),\n        '-c', 'copy',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n### 音视频合并\n\n```python\ndef merge_av(video_path, audio_path, output_path):\n    \"\"\"合并视频和音频\"\"\"\n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-i', str(video_path),\n        '-i', str(audio_path),\n        '-c:v', 'copy',\n        '-c:a', 'aac',\n        '-shortest',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n---\n\n## 七、素材导出\n\n### 桌面文件夹结构\n\n```python\nimport os, shutil\n\ndef export_to_desktop(project_name, segments_data, desktop_path):\n    \"\"\"导出结构化素材到桌面\"\"\"\n    base = os.path.join(desktop_path, project_name)\n    \n    dirs = {\n        \"01_字幕\": \"subtitle_pngs\",\n        \"02_配音\": \"tts_mp3s\",\n        \"03_主图\": \"thumbnails\",\n        \"04_视频\": \"seg_videos\",\n        \"05_矩阵表\": \"matrix\"\n    }\n    \n    for name in dirs:\n        os.makedirs(os.path.join(base, name), exist_ok=True)\n    \n    # 生成矩阵表HTML\n    generate_matrix_html(segments_data, os.path.join(base, \"05_矩阵表\", \"矩阵表.html\"))\n    \n    # 生成JSON\n    generate_json(segments_data, os.path.join(base, \"05_矩阵表\", \"素材结构.json\"))\n```\n\n---\n\n## 八、成本核算\n\n### 完整成本模型\n\n```python\ndef calculate_cost(params):\n    \"\"\"\n    params = {\n        'shot_seconds': 234,      # 镜头总时长\n        'retry_times': 3,          # 平均重试次数\n        'tts_chars': 350,          # TTS总字数\n        'dialog_rounds': 250,      # WorkBuddy对话轮次\n        'project_days': 2,         # 项目天数\n    }\n    \"\"\"\n    grok = params['shot_seconds'] * 0.05 * params['retry_times']\n    tts = params['tts_chars'] * 0.0006 * 1.5  # 含重试\n    wb = params['dialog_rounds'] * 0.0022 * 1.5  # 含隐性消耗\n    hw = 3.65 * params['project_days']  # 硬件折旧\n    power = 0.62 * params['project_days']  # 电费\n    \n    return {\n        'Grok Imagine': grok,\n        'TTS配音': tts,\n        'WorkBuddy算力': wb,\n        '硬件折旧': hw,\n        '电费': power,\n        '总计': grok + tts + wb + hw + power\n    }\n```\n\n### 参考成本（基于三体EP1实战）\n\n| 项目规模 | 预估成本 | 制作周期 |\n|---------|---------|---------|\n| 30秒 / 6镜头 | ¥10-15 | 0.5天 |\n| 60秒 / 12镜头 | ¥20-30 | 1天 |\n| 128秒 / 25镜头 | ¥40-50 | 2天 |\n| 5分钟 / 50镜头 | ¥80-120 | 3-4天 |\n\n---\n\n## 九、常见问题排查\n\n### 视频生成失败\n- **症状**: API返回错误或超时\n- **排查**: 检查API Key是否有效、余额是否充足\n- **解决**: 重试（换IP节点）、切换模型\n\n### TTS卡住\n- **症状**: status一直=0\n- **排查**: 检查参数格式（扁平JSON）\n- **解决**: 重新提交任务\n\n### 音画不同步\n- **症状**: 画面和声音对不上\n- **排查**: 检查每段TTS时长和视频裁剪时长\n- **解决**: 逐段精确裁剪，不要整体缩放\n\n### 字幕不显示\n- **症状**: 视频没有字幕\n- **排查**: 检查FFmpeg版本是否支持drawtext\n- **解决**: 用Pillow生成PNG + overlay叠加\n\n### 视频拼接报错\n- **症状**: concat失败\n- **排查**: 检查所有分段视频编码是否一致\n- **解决**: 统一用libx264编码重新转码\n\n---\n\n## 十、专业审核与迭代流程\n\nAI生成的第一版几乎从来不是最终版。必须经过\"制作→审核→修改\"的迭代循环。\n\n### 10.1 六维审核检查表\n\n| 维度 | 检查方法 | 判定标准 |\n|------|---------|---------|\n| **① 音画同步** | 逐段播放，对比画面内容与配音台词 | 角色A说话时画面必须是角色A |\n| **② 时长匹配** | ffprobe对比每段视频和TTS时长 | 偏差 < 0.5s |\n| **③ 视觉重复** | 检查stream_loop循环次数 | 不超过2次循环 |\n| **④ 字幕准确** | 逐句对照字幕文本和TTS台词 | 无错别字、标点正确 |\n| **⑤ 节奏感** | 整体观看，标记拖沓或仓促段落 | 每段TTS时长占镜头60-80%最佳 |\n| **⑥ 画面质量** | 检查AI生成瑕疵 | 无变形、闪烁、分辨率异常 |\n\n### 10.2 问题分级与修复优先级\n\n```\nP0（必须修复）—— 影响观看体验的根本问题\n├── 音画不匹配：画面内容与台词无关\n├── 字幕错误：错别字、台词与字幕不一致\n├── 画面截断：话没说完画面就切了\n└── 时长严重偏差：偏差 > 1s\n→ 优先级：最高，不修不能交付\n\nP1（建议修复）—— 影响观看体验但可接受\n├── 节奏拖沓：某段画面太长，观众失去耐心\n├── 视觉重复感：循环超过2次\n├── 转场生硬：相邻镜头切换突兀\n└── 音色不匹配：角色音色与形象不符\n→ 优先级：中，尽量修\n\nP2（可优化）—— 锦上添花\n├── 画面色调不统一\n├── 字幕样式可美化\n├── 背景音效可丰富\n└── 片头片尾可添加\n→ 优先级：低，有时间再修\n```\n\n### 10.3 迭代工作流\n\n```python\ndef review_and_fix(version, issues):\n    \"\"\"\n    version: 当前版本号\n    issues: 审核发现的问题列表\n    \n    返回: 是否需要继续迭代\n    \"\"\"\n    p0_count = sum(1 for i in issues if i['level'] == 'P0')\n    p1_count = sum(1 for i in issues if i['level'] == 'P1')\n    \n    print(f\"版本 {version} 审核结果:\")\n    print(f\"  P0(必须修): {p0_count}\")\n    print(f\"  P1(建议修): {p1_count}\")\n    print(f\"  P2(可优化): {len(issues) - p0_count - p1_count}\")\n    \n    if p0_count > 0:\n        print(\"→ 进入下一轮迭代\")\n        return True\n    elif p1_count > 2:\n        print(\"→ 建议再修一轮\")\n        return True\n    else:\n        print(\"→ 达到交付标准 ✅\")\n        return False\n```\n\n### 10.4 实战案例：三体EP1迭代记录\n\n| 版本 | 时长 | 问题发现 | 修复内容 | 审核结论 |\n|------|------|---------|---------|---------|\n| v5min | 252s | 视频总长252s但TTS仅127s，大量空白段落 | 重新按TTS时长裁剪 | ❌ P0: 节奏断裂 |\n| v6 | — | 音频驱动剪辑，3个短镜头被截断 | 修复中 | ❌ 未完成 |\n| v7 | 127s | 3个短镜头截断：火鸡演讲缺9s | stream_loop循环填充 | ❌ P0: 画面截断 |\n| v7.1 | 127.9s | 循环修复完成，但无字幕 | 加字幕 | ⚠️ P1: 缺字幕 |\n| v8 | 127.9s | 字幕+音画同步修复+矩阵表 | 全部修复 | ✅ 交付 |\n\n### 10.5 审核工具脚本\n\n```python\n#!/usr/bin/env python3\n\"\"\"一键审核脚本：检查所有段的音画同步和时长匹配\"\"\"\n\nimport subprocess\nfrom pathlib import Path\n\nFFPROBE = '/opt/homebrew/bin/ffprobe'\n\ndef get_duration(p):\n    r = subprocess.run([FFPROBE,'-v','quiet','-show_entries','format=duration',\n                        '-of','csv=p=0',str(p)], capture_output=True, text=True)\n    return float(r.stdout.strip())\n\ndef audit(segments_dir, tts_dir, num_segments=25):\n    issues = []\n    print(f\"{'#':>3} {'角色':<20} {'TTS':>7} {'视频':>7} {'偏差':>7} {'状态'}\")\n    print(\"-\" * 55)\n    \n    for i in range(num_segments):\n        seg = Path(segments_dir) / f\"seg_{i:03d}.mp4\"\n        tts = sorted(Path(tts_dir).glob(\"*.mp3\"))[i]\n        \n        seg_dur = get_duration(seg) if seg.exists() else 0\n        tts_dur = get_duration(tts)\n        diff = seg_dur - tts_dur\n        \n        status = \"✅\" if abs(diff) < 0.5 else \"⚠️\"\n        if abs(diff) > 0.5:\n            issues.append(f\"#{i}: 偏差{diff:+.2f}s\")\n        \n        print(f\"{i:3d} {tts.stem:<20s} {tts_dur:>6.2f}s {seg_dur:>6.2f}s {diff:>+6.2f}s {status}\")\n    \n    print(f\"\\n问题段: {len(issues)}\")\n    for issue in issues:\n        print(f\"  {issue}\")\n    \n    return issues\n\nif __name__ == '__main__':\n    audit(Path('v7_assets'), Path('ep1_tts'))\n```\n\nFile v1.0.1:references/sucuang_api.md\n\n# 速创API 接口文档与踩坑经验\n\n## 平台信息\n\n- **平台地址**: https://api.wuyinkeji.com\n- **文档中心**: https://api.wuyinkeji.com/doc\n- **API Key获取**: 注册登录后进入控制台获取\n\n## 通用鉴权方式\n\n**推荐方式 — Authorization Header（不带Bearer前缀）：**\n```python\nHEADERS = {\n    \"Authorization\": \"你的API_KEY\",\n    \"Content-Type\": \"application/json\"\n}\n```\n\n**❌ 不要用URL参数传key：**\n```python\n# 会返回403，不要这样用\nrequests.get(\"https://api.wuyinkeji.com/api/xxx?key=你的API_KEY\")\n```\n\n---\n\n## 1. Grok Imagine 视频生成\n\n### 接口信息\n- **接口**: POST `/api/async/video/grok_imagine`\n- **价格**: ¥0.05/秒（按生成视频时长计费，不足1秒按1秒）\n- **点数**: 5点/秒\n- **免费额度**: 无\n- **QPS限制**: 100次/秒\n- **每日限制**: 付费用户不限制\n\n### 请求参数\n```json\n{\n  \"prompt\": \"英文描述效果更稳定，包含场景、光线、构图、镜头运动\",\n  \"duration\": 10,\n  \"style\": \"cinematic\"\n}\n```\n\n### 结果查询\n- **接口**: `GET /api/async/detail?id=xxx`\n- **轮询策略**: 每5秒查询一次\n- **状态码**: status=2 表示完成，status=0/1 表示处理中\n- **返回内容**: 包含视频下载URL\n\n### 批量生成策略\n```python\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\n\ndef submit_shot(shot):\n    # 提交生成任务\n    resp = requests.post(url, headers=HEADERS, json=params)\n    task_id = resp.json()[\"data\"][\"id\"]\n    # 轮询直到完成\n    while True:\n        result = requests.get(f\"{BASE}/detail?id={task_id}\", headers=HEADERS)\n        if result.json()[\"data\"][\"status\"] == 2:\n            return download_video(result.json()[\"data\"][\"video_url\"])\n        time.sleep(5)\n\n# 批量25个镜头同时提交\nwith ThreadPoolExecutor(max_workers=10) as executor:\n    futures = [executor.submit(submit_shot, shot) for shot in SHOTS]\n    for future in as_completed(futures):\n        results.append(future.result())\n```\n\n### 踩坑经验\n- Sora2接口（sora2/video）已不可用，持续返回400错误，全部使用Grok Imagine\n- 英文Prompt比中文Prompt效果更稳定\n- 平均重试3次才能获得满意结果\n- 生成耗时约30-60秒/个\n\n---\n\n## 2. TTS配音生成\n\n### 接口信息\n- **接口**: `POST /api/async/audio_tts`\n- **价格**: ¥0.0006/字\n- **返回格式**: tar包（需解压获取mp3）\n\n### 请求参数（重要：扁平JSON）\n```json\n{\n  \"text\": \"台词内容\",\n  \"voice_id\": \"male-qn-jingying\",\n  \"speed\": 1.0\n}\n```\n\n### 可用音色列表\n| 音色ID | 描述 | 适用角色 |\n|--------|------|---------|\n| male-qn-jingying | 精英青年男声 | 旁白、汪淼、常伟思 |\n| male-qn-badao | 霸道男声 | 史强 |\n| male-qn-daxuesheng | 大学生男声 | 研究员 |\n| male-chunhou | 醇厚男声 | 长辈角色 |\n| junlang_nanyou | 俊朗男声 | 潘寒 |\n| female-chengshu | 成熟女声 | 申玉菲 |\n| female-shaonv | 少女音 | 杨冬 |\n\n### 踩坑经验（重要）\n1. **❌ 不要传 format 参数** — 会报500\"存在未绑定的参数\"\n2. **❌ 不要嵌套参数** — 不要写成 `{\"model\":\"audio_tts\",\"params\":{...}}`，直接扁平JSON\n3. **✅ 状态码判断** — 用 `status == 2` 判断完成，不要用字符串 `\"completed\"`\n4. **⚠️ 部分任务会卡住** — status一直=0，重试可换到不同IP节点\n5. **✅ 返回tar包** — 需要用 `tarfile` 解压获取mp3文件\n\n### TTS生成代码模板\n```python\nimport requests, time, tarfile, io\n\ndef generate_tts(text, voice_id, output_path):\n    payload = {\"text\": text, \"voice_id\": voice_id, \"speed\": 1.0}\n    resp = requests.post(f\"{BASE}/api/async/audio_tts\", headers=HEADERS, json=payload)\n    task_id = resp.json()[\"data\"][\"id\"]\n\n    while True:\n        result = requests.get(f\"{BASE}/api/async/detail?id={task_id}\", headers=HEADERS)\n        data = result.json()[\"data\"]\n        if data[\"status\"] == 2:  # 完成\n            audio_url = data[\"audio_url\"]\n            audio_resp = requests.get(audio_url)\n            tar = tarfile.open(fileobj=io.BytesIO(audio_resp.content))\n            for member in tar.getmembers():\n                if member.name.endswith('.mp3'):\n                    f = tar.extractfile(member)\n                    with open(output_path, 'wb') as out:\n                        out.write(f.read())\n            return\n        elif data[\"status\"] == -1:  # 失败\n            raise Exception(f\"TTS failed: {data}\")\n        time.sleep(3)\n```\n\n---\n\n## 3. 数字人视频生成\n\n### 接口信息\n- **接口**: `POST /api/async/video_digital_humans`\n- **价格**: 按次计费\n\n### 请求参数\n```json\n{\n  \"audio_url\": \"公网可访问的音频URL\",\n  \"video_url\": \"公网可访问的视频URL\"\n}\n```\n\n### 注意事项\n- 音频和视频URL必须公网可访问\n- 推荐搭配云存储服务存储素材\n\n---\n\n## 4. 云存储配置（素材存储）\n\n如需存储视频和音频文件，推荐使用云存储服务：\n- 腾讯云COS\n- 阿里云OSS\n- AWS S3\n\n请根据实际需求配置您自己的云存储凭证。\n\n---\n\n## 5. 其他可用模型\n\n速创API平台还提供以下模型（价格以平台实际为准）：\n- 文生图模型（多种）\n- 视频编辑模型\n- 语音识别\n- 大语言模型对话\n\n具体价格请查看：https://api.wuyinkeji.com/type/all\n\nArchive v1.0.0: 4 files, 16697 bytes\n\nFiles: references/production_workflow.md (15821b), references/sucuang_api.md (5702b), SKILL.md (12898b), _meta.json (141b)\n\nFile v1.0.0:SKILL.md\n\n---\nname: ai-short-film-producer\ndescription: 低成本AI短剧/短片全流程制作技能。使用速创API(wuyinkeji.com)的Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成，WorkBuddy编排全流程。适用于用户需要从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动剪辑、字幕叠加、最终合成、成本核算的全套SOP。\n---\n\n# AI Short Film Producer - 低成本AI短剧制作\n\n## 概述\n\n本Skill提供一套完整的**低成本AI短剧制作流程**，从脚本创作到最终成片，总成本仅需**¥30-50/部**（128秒短片）。核心思路：用AI API生成素材 → 本地FFmpeg合成 → WorkBuddy编排调度。\n\n**适用场景：**\n- 用户说\"帮我做一个短片/短剧/预告片\"\n- 用户说\"把这段文案做成视频\"\n- 用户说\"生成一个XX题材的短视频\"\n- 用户需要从零到一完成AI视频制作\n\n**核心成本优势：**\n- 视频生成：Grok Imagine ¥0.05/秒（速创API）\n- 配音生成：TTS ¥0.0006/字（速创API）\n- 合成剪辑：本地FFmpeg免费\n- AI编排：WorkBuddy Lite版约¥0.0022/轮\n\n---\n\n## 制作流程总览\n\n```\nStep 1: 脚本创作\n  ├── 确定主题/时长/风格\n  ├── 编写分镜脚本（镜头×台词×角色）\n  └── 输出：分镜表 + TTS文本清单\n\nStep 2: 视频镜头生成\n  ├── 调用速创API Grok Imagine\n  ├── 25个镜头批量异步生成\n  └── 输出：ep1_shots/*.mp4\n\nStep 3: TTS配音生成\n  ├── 调用速创API audio_tts\n  ├── 多角色多音色\n  └── 输出：ep1_tts/*.mp3\n\nStep 4: 音频驱动剪辑\n  ├── 逐段按TTS时长裁剪/循环镜头\n  ├── 短镜头自动stream_loop填充\n  └── 输出：分段seg_*.mp4\n\nStep 5: 字幕生成\n  ├── Python Pillow生成透明PNG字幕\n  ├── FFmpeg overlay叠加（因FFmpeg 8.x无drawtext）\n  └── 输出：带字幕的分段视频\n\nStep 6: 最终合成\n  ├── concat拼接25段视频\n  ├── concat拼接25段音频\n  ├── 音视频合并\n  └── 输出：最终成片.mp4\n\nStep 7: 素材导出\n  ├── 结构化桌面文件夹\n  ├── 矩阵表 + JSON\n  └── 成本核算\n```\n\n---\n\n## 详细步骤\n\n### Step 1: 脚本创作\n\n**输入：** 用户需求（主题、风格、时长、参考素材）\n**输出：** 分镜脚本文档 + TTS台词清单\n\n**工作流程：**\n1. 与用户确认主题方向（科幻/悬疑/科普/剧情等）\n2. 编写分镜脚本，包含：\n   - 镜头编号、画面描述、时长\n   - 配音台词、角色分配、音色选择\n   - 音效说明\n3. 输出TTS台词清单（25段以内，每段2-20字最佳）\n4. 角色音色分配表：\n\n| 角色类型 | 推荐音色ID | 说明 |\n|---------|-----------|------|\n| 旁白/叙述者 | male-qn-jingying | 精英青年男声，通用 |\n| 男主角 | male-qn-jingying | 精英青年男声 |\n| 霸道/硬汉 | male-qn-badao | 霸道男声 |\n| 反派/俊朗 | junlang_nanyou | 俊朗男声 |\n| 成熟女性 | female-chengshu | 成熟女声 |\n| 少女 | female-shaonv | 少女音 |\n| 研究员/学生 | male-qn-daxuesheng | 大学生男声 |\n| 醇厚长辈 | male-chunhou | 醇厚男声 |\n\n### Step 2: 视频镜头生成（速创API Grok Imagine）\n\n**API平台：** 速创API https://api.wuyinkeji.com\n**模型：** Grok Imagine（xAI Aurora引擎）\n**价格：** ¥0.05/秒（按生成视频时长计费，不足1秒按1秒）\n**注册链接：** https://api.wuyinkeji.com/user/register?cps=UXPjoCgN\n\n**API调用方式：**\n- 鉴权：Authorization Header 传API Key（不带Bearer前缀）\n- 接口：POST /api/async/video/grok_imagine\n- 参数格式：扁平JSON\n- 结果查询：GET /api/async/detail?id=xxx（轮询直到status=2）\n\n**批量生成策略：**\n1. 25个镜头同时提交（用ThreadPoolExecutor）\n2. 每个镜头约10秒，生成耗时约30-60秒\n3. 失败自动重试（平均重试3次）\n4. 注意：Sora2接口已不可用（持续400错误），全部使用Grok Imagine\n\n**Prompt编写要点：**\n- 英文Prompt效果更稳定\n- 包含：场景描述、光线、构图、镜头运动\n- 示例：`\"Deep space, Milky Way galaxy slowly rotating, cinematic wide shot, photorealistic, 4K quality\"`\n\n### Step 3: TTS配音生成（速创API audio_tts）\n\n**API接口：** POST /api/async/audio_tts\n**价格：** ¥0.0006/字\n**参数格式（重要）：** 扁平JSON，不要嵌套\n\n```json\n{\n  \"text\": \"台词内容\",\n  \"voice_id\": \"male-qn-jingying\",\n  \"speed\": 1.0\n}\n```\n\n**注意事项（踩坑经验）：**\n- ❌ 不要传 format 参数（会报500\"存在未绑定的参数\"）\n- ❌ 不要嵌套成 `{\"model\":\"audio_tts\",\"params\":{...}}`\n- ✅ 状态码判断：status=2 完成，status=0/1 处理中\n- ⚠️ 部分任务会卡住（status一直=0），重试可换IP节点\n- ✅ 返回tar包，需解压获取mp3\n\n### Step 4: 音频驱动剪辑（核心节奏控制）\n\n**核心理念：** 画面长度由语音旁白决定，而非固定时长。先录制/生成TTS配音，再让每段视频精确匹配对应配音的时长。这样保证音画天然同步，且节奏由配音自然驱动。\n\n#### 4.1 节奏控制逻辑\n\n```\n每段（镜头, TTS）的处理流程：\n\n1. 获取TTS音频实际时长 tts_dur（用ffprobe精确到毫秒）\n2. 获取源视频时长 src_dur\n3. 对比决策：\n   ├── src_dur >= tts_dur + 0.5s  → 直接裁剪到tts_dur（视频多出的部分舍弃）\n   ├── src_dur ≈ tts_dur（差<0.5s）→ 直接裁剪，不做额外处理\n   └── src_dur < tts_dur           → stream_loop循环播放填满tts_dur\n4. 输出：seg_NNN.mp4（时长=tts_dur，精确匹配配音）\n```\n\n**为什么用\"音频驱动\"而非\"视频驱动\"：**\n- 传统剪辑：先定视频长度，再往里塞配音 → 配音节奏被画面绑架\n- 音频驱动：先定配音节奏，再裁剪画面适配 → 叙事节奏由台词自然决定\n- 效果：观众听到的每句话都有对应的画面时长，不会出现\"话没说完画面就切了\"\n\n#### 4.2 短镜头循环填充（stream_loop）\n\n当源视频时长不够时，用FFmpeg的stream_loop让视频循环播放：\n\n```bash\n# 循环播放直到填满tts_dur\n/opt/homebrew/bin/ffmpeg -y -stream_loop -1 -i shot.mp4 -t {tts_dur} -c:v libx264 -preset fast seg.mp4\n```\n\n**实战经验（三体EP1）：**\n- 25个镜头中有3个需要循环填充\n- 最大修复：pan_han_02火鸡演讲（源视频10s → TTS需要19s，循环补9s）\n- 循环填充的视觉重复感在1-2次循环内不明显，超过3次建议换镜头\n\n#### 4.3 逐段精确裁剪避免累积漂移\n\n```python\n# 关键：每段独立裁剪，不整体缩放\ncumulative = 0.0\nfor i, (tts_file, shot_file) in enumerate(segments):\n    tts_dur = get_duration(tts_file)  # ffprobe获取\n    # 精确裁剪到tts_dur，不依赖前一段的结束时间\n    trim_video(shot_file, tts_dur, f\"seg_{i:03d}.mp4\")\n    cumulative += tts_dur\n\n# 最终验证：所有seg时长之和 ≈ audio_concat时长 ≈ 最终成片时长\n```\n\n**FFmpeg路径（Mac mini M4）：** `/opt/homebrew/bin/ffmpeg`\n\n**已知限制：**\n- FFmpeg 8.x 未编译drawtext/libass/freetype滤镜 → 不能直接加字幕\n- anullsrc语法用 `cl=stereo` 而非 `c=stereo`\n- shell转义用Python subprocess list模式避免zsh问题\n\n### Step 5: 字幕生成\n\n**方案：** Pillow生成透明PNG → FFmpeg overlay叠加\n\n```python\nfrom PIL import Image, ImageDraw, ImageFont\n\n# 创建透明PNG\nimg = Image.new('RGBA', (1920, 160), (0,0,0,0))\ndraw = ImageDraw.Draw(img)\nfont = ImageFont.truetype('/System/Library/Fonts/PingFang.ttc', 48)\n\n# 白色大字 + 黑色描边\ndraw.text((960, 80), \"台词文本\", fill='white', font=font, \n          anchor='mm', stroke_width=3, stroke_fill='black')\n\n# FFmpeg overlay叠加\nffmpeg -i seg.mp4 -i sub.png -filter_complex \"overlay=0:H-h\" output.mp4\n```\n\n**字幕设计规范：**\n- 底部居中，距底部约60px\n- 白色大字 + 3px黑色描边\n- 字号48-56px（PingFang SC字体）\n- 可加角色标签（如\"旁白：\"、\"汪淼：\"）\n\n### Step 6: 最终合成\n\n**拼接视频：**\n```bash\n# 生成file list\nfor f in seg_*.mp4; do echo \"file '$f'\" >> video_list.txt; done\nffmpeg -f concat -safe 0 -i video_list.txt -c copy video_concat.mp4\n```\n\n**拼接音频：**\n```bash\nfor f in audio_*.mp3; do echo \"file '$f'\" >> audio_list.txt; done\nffmpeg -f concat -safe 0 -i audio_list.txt -c copy audio_concat.aac\n```\n\n**音视频合并：**\n```bash\nffmpeg -i video_concat.mp4 -i audio_concat.aac -c:v copy -c:a aac final.mp4\n```\n\n### Step 7: 素材导出与成本核算\n\n**桌面文件夹结构：**\n```\n~/Desktop/项目名称/\n├── 01_字幕/     → 字幕PNG文件\n├── 02_配音/     → TTS音频MP3\n├── 03_主图/     → 镜头缩略图JPG\n├── 04_视频/     → 分段视频MP4\n├── 05_矩阵表/   → 矩阵表.html + 素材结构.json\n└── 最终成片.mp4\n```\n\n**成本核算模板：**\n\n| 项目 | 计算方式 | 参考单价 |\n|------|---------|---------|\n| Grok Imagine视频 | 总秒数 × 重试次数 × ¥0.05 | ¥0.05/秒 |\n| TTS配音 | 总字数 × ¥0.0006 | ¥0.0006/字 |\n| WorkBuddy算力 | 对话轮次 × ¥0.0022 | ¥0.0022/轮 |\n| 硬件折旧 | Mac mini ¥3,999/3年寿命 | ¥3.65/天 |\n| 电费 | 16h × 65W × ¥0.6/度 | ¥0.62/天 |\n\n---\n\n## 速创API平台速查\n\n**平台地址：** https://api.wuyinkeji.com\n**注册链接：** https://api.wuyinkeji.com/user/register?cps=UXPjoCgN\n**文档中心：** https://api.wuyinkeji.com/doc\n\n**常用模型及价格：**\n\n| 模型/接口 | 价格 | 说明 |\n|-----------|------|------|\n| Grok Imagine 视频生成 | ¥0.05/秒 | 文生视频/图生视频，6-15秒 |\n| audio_tts 配音 | ¥0.0006/字 | 多音色TTS |\n| video_digital_humans 数字人 | 按次计费 | 需公网音频URL+视频URL |\n| Sora2（已弃用） | — | 持续400错误，不可用 |\n\n**API Key传递：**\n- ✅ Authorization Header（推荐，不带Bearer前缀）\n- ❌ URL参数 ?key=xxx（会返回403）\n\n---\n\n## 三体EP1实战参考\n\n**项目规模：** 25个镜头，127秒成片，8个角色\n**总成本：** ¥44.17（含重试+硬件折旧）\n**工具链：** Grok Imagine × 25 + TTS × 25 + FFmpeg + Python Pillow\n**迭代版本：** v5min → v6 → v7 → v7.1 → v8（5个版本迭代）\n\n**关键经验：**\n1. Sora2不可用，全部切Grok Imagine\n2. 源视频短于TTS时用stream_loop循环填充\n3. FFmpeg 8.x无drawtext，用Pillow生成PNG替代\n4. TTS部分任务卡住需重试\n5. 逐段精确裁剪避免累积漂移\n\n---\n\n## 专业审核与迭代流程\n\nAI生成的第一版通常不是最终版。必须经过\"制作→审核→修改\"的迭代循环才能达到交付标准。\n\n### 审核维度\n\n| 维度 | 检查内容 | 常见问题 |\n|------|---------|---------|\n| **音画同步** | 画面内容是否匹配配音台词 | 角色A说话但画面是角色B |\n| **时长匹配** | 每段视频是否完整覆盖TTS | 短镜头被截断，话没说完画面就切 |\n| **视觉重复** | 循环播放是否超过3次 | 火鸡演讲循环9s，观众能看出重复 |\n| **字幕准确** | 字幕文本是否与TTS一致 | 错别字、标点错误 |\n| **节奏感** | 整体叙事节奏是否流畅 | 某段太长拖沓，某段太短仓促 |\n| **画面质量** | 是否有明显AI生成瑕疵 | 人物变形、闪烁、分辨率低 |\n\n### 迭代流程\n\n```\nV1（初版合成）\n  ↓\n专业审核（逐段检查以上6个维度）\n  ↓\n问题清单 → 按严重程度排序\n  ├── P0（必须修）：音画不匹配、字幕错误、画面截断\n  ├── P1（建议修）：节奏拖沓、视觉重复感强\n  └── P2（可优化）：画面质量、色调统一\n  ↓\nV2（修复P0问题）\n  ↓\n再次审核\n  ↓\nV3...（逐轮修复，直到P0=0、P1≤2）\n  ↓\n最终交付\n```\n\n### 实战案例：三体EP1迭代记录\n\n| 版本 | 问题 | 修复方案 |\n|------|------|---------|\n| v5min | 252秒成片，但TTS只有127秒，大量空白 | 重新按TTS时长裁剪 |\n| v6 | 音频驱动剪辑，但3个短镜头被截断 | 修复中 |\n| v7 | 短镜头截断（火鸡演讲缺9s） | stream_loop循环填充 |\n| v7.1 | 循环修复完成，但无字幕 | 加字幕 |\n| v8 | 字幕+音画同步修复+矩阵表 | ✅ 最终交付 |\n\n**审核工具：**\n- 逐段对比：`ffprobe` 获取每段TTS和视频的精确时长\n- 偏差检查：每段TTS vs 视频时长差 > 0.5s 即标记为问题段\n- 画面检查：播放时逐段确认画面内容与台词匹配\n\n---\n\n## 资源文件\n\n### references/\n- `sucuang_api.md` — 速创API完整接口文档和踩坑经验\n- `production_workflow.md` — 制作流程详细参考\n\n### scripts/\n- （按需添加：批量提交脚本、合成脚本模板等）\n\n### assets/\n- （按需添加：字幕模板、片头片尾素材等）\n\nFile v1.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn703gwc11aqnnaatk69f339d9822e08\",\n  \"slug\": \"ai-short-film-producer\",\n  \"version\": \"1.0.0\",\n  \"publishedAt\": 1777541805422\n}\n\nFile v1.0.0:references/production_workflow.md\n\n# AI短剧制作流程详细参考\n\n## 一、项目启动\n\n### 需求确认\n与用户确认以下信息：\n1. **主题**：科幻/悬疑/科普/剧情/搞笑/教育等\n2. **风格**：写实/动画/赛博朋克/古风等\n3. **时长**：30秒/60秒/2分钟/5分钟\n4. **角色**：需要几个角色？是否有特定音色要求？\n5. **参考素材**：用户是否提供文案/图片/参考视频？\n\n### 脚本模板\n\n```markdown\n# 项目名称 · 分镜脚本\n\n## 总览\n- 总时长：XX秒\n- 镜头数：XX个\n- 角色数：XX个\n\n## 分镜表\n| # | 镜头ID | 画面描述 | 配音台词 | 角色 | 音色 | 时长 |\n|---|--------|---------|---------|------|------|------|\n| 1 | shot01_xxx | 画面描述 | 台词内容 | 角色名 | 音色ID | 10s |\n| 2 | shot02_xxx | 画面描述 | 台词内容 | 角色名 | 音色ID | 10s |\n```\n\n---\n\n## 二、视频生成\n\n### Grok Imagine Prompt编写指南\n\n**结构模板：**\n```\n[场景描述], [主体描述], [光线/氛围], [构图/镜头运动], [风格关键词]\n```\n\n**示例：**\n```\n\"Deep space, Milky Way galaxy slowly rotating across a star-filled cosmos,\ncountless stars twinkling, nebulae in deep blue and purple hues,\ncinematic wide shot, photorealistic, 4K quality, slow gentle rotation\"\n```\n\n**各类型场景Prompt关键词：**\n\n| 场景类型 | 关键词 |\n|---------|--------|\n| 太空/宇宙 | deep space, stars, nebula, galaxy, cosmic, celestial |\n| 城市/街头 | city street, urban, bustling, modern, buildings |\n| 室内/会议室 | conference room, modern, screens, professional |\n| 人物特写 | close-up, portrait, expression, emotion, cinematic lighting |\n| 自然/风景 | landscape, mountains, ocean, sunset, cinematic |\n| 科技/实验室 | laboratory, technology, screens, equipment, futuristic |\n\n### 批量提交策略\n\n1. 25个镜头同时提交到API\n2. 使用ThreadPoolExecutor(max_workers=10)\n3. 每5秒轮询一次结果\n4. 失败自动重试（最多5次）\n5. 下载后检查文件完整性（ffprobe验证时长）\n\n---\n\n## 三、TTS配音生成\n\n### 多角色音色分配策略\n\n| 角色数量 | 分配策略 |\n|---------|---------|\n| 1-2个角色 | 旁白用jingying，对话角色用对应音色 |\n| 3-5个角色 | 主要角色各分配独立音色，次要角色复用 |\n| 6-10个角色 | 核心角色独立音色，路人/群演用通用音色 |\n\n### 台词字数控制\n- 每段TTS建议2-20字（太长影响听感）\n- 10秒镜头配2-4秒台词最合适\n- 留白时间给观众消化内容\n\n---\n\n## 四、音频驱动剪辑（核心节奏控制）\n\n### 核心理念\n\n**音频驱动剪辑 = 画面长度由语音旁白决定，而非固定时长。**\n\n传统剪辑思维是\"先定视频长度，再往里塞配音\"，结果配音节奏被画面绑架。音频驱动反过来——先录制TTS配音，再让每段视频精确匹配对应配音的时长。这样：\n- 观众听到的每句话都有完整的画面时长\n- 叙事节奏由台词自然驱动\n- 不会出现\"话没说完画面就切了\"\n\n### 核心算法\n\n```\n对于每一段（镜头, TTS）：\n  1. 获取TTS音频时长 tts_dur（ffprobe精确到毫秒）\n  2. 获取源视频时长 src_dur\n  3. 对比决策：\n     ├── src_dur >= tts_dur + 0.5s  → 直接裁剪到tts_dur\n     ├── src_dur ≈ tts_dur（差<0.5s）→ 直接裁剪\n     └── src_dur < tts_dur           → stream_loop循环填充\n  4. 输出：seg_NNN.mp4（时长精确=tts_dur）\n```\n\n### 逐段精确裁剪（避免累积漂移）\n\n```python\nimport subprocess\nfrom pathlib import Path\n\nFFPROBE = '/opt/homebrew/bin/ffprobe'\nFFMPEG = '/opt/homebrew/bin/ffmpeg'\n\ndef get_duration(filepath):\n    \"\"\"获取媒体文件精确时长\"\"\"\n    result = subprocess.run(\n        [FFPROBE, '-v', 'quiet', '-show_entries', 'format=duration',\n         '-of', 'csv=p=0', str(filepath)],\n        capture_output=True, text=True\n    )\n    return float(result.stdout.strip())\n\ndef process_segment(tts_file, shot_file, output_file):\n    \"\"\"处理单段：按TTS时长裁剪/循环视频\"\"\"\n    tts_dur = get_duration(tts_file)\n    src_dur = get_duration(shot_file)\n    \n    cmd = [FFMPEG, '-y']\n    \n    if src_dur >= tts_dur:\n        # 视频够长，直接裁剪\n        cmd.extend(['-t', str(tts_dur), '-i', str(shot_file)])\n    else:\n        # 视频不够长，循环填充\n        cmd.extend(['-stream_loop', '-1', '-i', str(shot_file),\n                     '-t', str(tts_dur)])\n    \n    cmd.extend(['-c:v', 'libx264', '-preset', 'fast', str(output_file)])\n    subprocess.run(cmd, check=True)\n    \n    # 验证输出时长\n    out_dur = get_duration(output_file)\n    diff = abs(out_dur - tts_dur)\n    if diff > 0.5:\n        print(f\"⚠️ 时长偏差 {diff:.2f}s: {output_file.name}\")\n    \n    return tts_dur\n\n# 批量处理所有段\ntotal = 0.0\nfor i, (tts_file, shot_file) in enumerate(segments):\n    dur = process_segment(tts_file, shot_file, f\"seg_{i:03d}.mp4\")\n    total += dur\n\nprint(f\"总时长: {total:.2f}s\")\n```\n\n### 短镜头循环填充策略\n\n当源视频短于TTS时，用stream_loop让视频循环播放：\n\n```bash\n/opt/homebrew/bin/ffmpeg -y -stream_loop -1 -i shot.mp4 -t {tts_dur} -c:v libx264 -preset fast seg.mp4\n```\n\n**循环填充的视觉容忍度：**\n| 循环次数 | 观众感知 | 建议 |\n|---------|---------|------|\n| 1次（补0-5s） | 几乎察觉不到 | ✅ 可用 |\n| 2次（补5-10s） | 部分观众能察觉 | ⚠️ 谨慎使用 |\n| 3次以上（补>10s） | 明显重复感 | ❌ 建议换镜头或补新素材 |\n\n### 音画同步验证\n\n合成后必须逐段验证：\n\n```python\ndef verify_sync(segments_dir, tts_dir):\n    \"\"\"验证所有段的音画同步\"\"\"\n    issues = []\n    for i in range(25):\n        seg = Path(segments_dir) / f\"seg_{i:03d}.mp4\"\n        tts = Path(tts_dir) / f\"tts_{i:03d}.mp3\"\n        \n        seg_dur = get_duration(seg)\n        tts_dur = get_duration(tts)\n        diff = seg_dur - tts_dur\n        \n        if abs(diff) > 0.5:\n            issues.append(f\"#{i}: 偏差{diff:+.2f}s\")\n    \n    if issues:\n        print(\"⚠️ 同步问题:\")\n        for issue in issues:\n            print(f\"  {issue}\")\n    else:\n        print(\"✅ 全部同步\")\n```\n\n---\n\n## 五、字幕生成\n\n### Pillow字幕生成模板\n\n```python\nfrom PIL import Image, ImageDraw, ImageFont\n\ndef create_subtitle(text, role=\"\", output_path=\"sub.png\"):\n    \"\"\"生成字幕PNG\"\"\"\n    WIDTH, HEIGHT = 1920, 160\n    img = Image.new('RGBA', (WIDTH, HEIGHT), (0, 0, 0, 0))\n    draw = ImageDraw.Draw(img)\n    \n    font = ImageFont.truetype('/System/Library/Fonts/PingFang.ttc', 48)\n    \n    full_text = f\"{role}：{text}\" if role else text\n    \n    # 黑色描边 + 白色填充\n    draw.text((WIDTH//2, HEIGHT//2), full_text, \n              fill='white', font=font, anchor='mm',\n              stroke_width=3, stroke_fill='black')\n    \n    img.save(output_path)\n```\n\n### FFmpeg叠加字幕\n\n```bash\n/opt/homebrew/bin/ffmpeg -y -i {video}.mp4 -i {subtitle}.png \\\n  -filter_complex \"overlay=0:H-h\" \\\n  -c:v libx264 -preset fast {output}.mp4\n```\n\n---\n\n## 六、最终合成\n\n### 视频拼接\n\n```python\nimport subprocess\nfrom pathlib import Path\n\ndef concat_videos(seg_dir, output_path):\n    \"\"\"拼接所有分段视频\"\"\"\n    segs = sorted(Path(seg_dir).glob(\"seg_*.mp4\"))\n    \n    # 生成file list\n    list_path = Path(seg_dir) / \"video_list.txt\"\n    with open(list_path, 'w') as f:\n        for seg in segs:\n            f.write(f\"file '{seg.absolute()}'\\n\")\n    \n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-f', 'concat', '-safe', '0',\n        '-i', str(list_path),\n        '-c', 'copy',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n### 音频拼接\n\n```python\ndef concat_audios(audio_dir, output_path):\n    \"\"\"拼接所有TTS音频\"\"\"\n    audios = sorted(Path(audio_dir).glob(\"*.mp3\"))\n    \n    list_path = Path(audio_dir) / \"audio_list.txt\"\n    with open(list_path, 'w') as f:\n        for audio in audios:\n            f.write(f\"file '{audio.absolute()}'\\n\")\n    \n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-f', 'concat', '-safe', '0',\n        '-i', str(list_path),\n        '-c', 'copy',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n### 音视频合并\n\n```python\ndef merge_av(video_path, audio_path, output_path):\n    \"\"\"合并视频和音频\"\"\"\n    cmd = [\n        '/opt/homebrew/bin/ffmpeg', '-y',\n        '-i', str(video_path),\n        '-i', str(audio_path),\n        '-c:v', 'copy',\n        '-c:a', 'aac',\n        '-shortest',\n        str(output_path)\n    ]\n    subprocess.run(cmd, check=True)\n```\n\n---\n\n## 七、素材导出\n\n### 桌面文件夹结构\n\n```python\nimport os, shutil\n\ndef export_to_desktop(project_name, segments_data, desktop_path):\n    \"\"\"导出结构化素材到桌面\"\"\"\n    base = os.path.join(desktop_path, project_name)\n    \n    dirs = {\n        \"01_字幕\": \"subtitle_pngs\",\n        \"02_配音\": \"tts_mp3s\",\n        \"03_主图\": \"thumbnails\",\n        \"04_视频\": \"seg_videos\",\n        \"05_矩阵表\": \"matrix\"\n    }\n    \n    for name in dirs:\n        os.makedirs(os.path.join(base, name), exist_ok=True)\n    \n    # 生成矩阵表HTML\n    generate_matrix_html(segments_data, os.path.join(base, \"05_矩阵表\", \"矩阵表.html\"))\n    \n    # 生成JSON\n    generate_json(segments_data, os.path.join(base, \"05_矩阵表\", \"素材结构.json\"))\n```\n\n---\n\n## 八、成本核算\n\n### 完整成本模型\n\n```python\ndef calculate_cost(params):\n    \"\"\"\n    params = {\n        'shot_seconds': 234,      # 镜头总时长\n        'retry_times': 3,          # 平均重试次数\n        'tts_chars': 350,          # TTS总字数\n        'dialog_rounds': 250,      # WorkBuddy对话轮次\n        'project_days': 2,         # 项目天数\n    }\n    \"\"\"\n    grok = params['shot_seconds'] * 0.05 * params['retry_times']\n    tts = params['tts_chars'] * 0.0006 * 1.5  # 含重试\n    wb = params['dialog_rounds'] * 0.0022 * 1.5  # 含隐性消耗\n    hw = 3.65 * params['project_days']  # 硬件折旧\n    power = 0.62 * params['project_days']  # 电费\n    \n    return {\n        'Grok Imagine': grok,\n        'TTS配音': tts,\n        'WorkBuddy算力': wb,\n        '硬件折旧': hw,\n        '电费': power,\n        '总计': grok + tts + wb + hw + power\n    }\n```\n\n### 参考成本（基于三体EP1实战）\n\n| 项目规模 | 预估成本 | 制作周期 |\n|---------|---------|---------|\n| 30秒 / 6镜头 | ¥10-15 | 0.5天 |\n| 60秒 / 12镜头 | ¥20-30 | 1天 |\n| 128秒 / 25镜头 | ¥40-50 | 2天 |\n| 5分钟 / 50镜头 | ¥80-120 | 3-4天 |\n\n---\n\n## 九、常见问题排查\n\n### 视频生成失败\n- **症状**: API返回错误或超时\n- **排查**: 检查API Key是否有效、余额是否充足\n- **解决**: 重试（换IP节点）、切换模型\n\n### TTS卡住\n- **症状**: status一直=0\n- **排查**: 检查参数格式（扁平JSON）\n- **解决**: 重新提交任务\n\n### 音画不同步\n- **症状**: 画面和声音对不上\n- **排查**: 检查每段TTS时长和视频裁剪时长\n- **解决**: 逐段精确裁剪，不要整体缩放\n\n### 字幕不显示\n- **症状**: 视频没有字幕\n- **排查**: 检查FFmpeg版本是否支持drawtext\n- **解决**: 用Pillow生成PNG + overlay叠加\n\n### 视频拼接报错\n- **症状**: concat失败\n- **排查**: 检查所有分段视频编码是否一致\n- **解决**: 统一用libx264编码重新转码\n\n---\n\n## 十、专业审核与迭代流程\n\nAI生成的第一版几乎从来不是最终版。必须经过\"制作→审核→修改\"的迭代循环。\n\n### 10.1 六维审核检查表\n\n| 维度 | 检查方法 | 判定标准 |\n|------|---------|---------|\n| **① 音画同步** | 逐段播放，对比画面内容与配音台词 | 角色A说话时画面必须是角色A |\n| **② 时长匹配** | ffprobe对比每段视频和TTS时长 | 偏差 < 0.5s |\n| **③ 视觉重复** | 检查stream_loop循环次数 | 不超过2次循环 |\n| **④ 字幕准确** | 逐句对照字幕文本和TTS台词 | 无错别字、标点正确 |\n| **⑤ 节奏感** | 整体观看，标记拖沓或仓促段落 | 每段TTS时长占镜头60-80%最佳 |\n| **⑥ 画面质量** | 检查AI生成瑕疵 | 无变形、闪烁、分辨率异常 |\n\n### 10.2 问题分级与修复优先级\n\n```\nP0（必须修复）—— 影响观看体验的根本问题\n├── 音画不匹配：画面内容与台词无关\n├── 字幕错误：错别字、台词与字幕不一致\n├── 画面截断：话没说完画面就切了\n└── 时长严重偏差：偏差 > 1s\n→ 优先级：最高，不修不能交付\n\nP1（建议修复）—— 影响观看体验但可接受\n├── 节奏拖沓：某段画面太长，观众失去耐心\n├── 视觉重复感：循环超过2次\n├── 转场生硬：相邻镜头切换突兀\n└── 音色不匹配：角色音色与形象不符\n→ 优先级：中，尽量修\n\nP2（可优化）—— 锦上添花\n├── 画面色调不统一\n├── 字幕样式可美化\n├── 背景音效可丰富\n└── 片头片尾可添加\n→ 优先级：低，有时间再修\n```\n\n### 10.3 迭代工作流\n\n```python\ndef review_and_fix(version, issues):\n    \"\"\"\n    version: 当前版本号\n    issues: 审核发现的问题列表\n    \n    返回: 是否需要继续迭代\n    \"\"\"\n    p0_count = sum(1 for i in issues if i['level'] == 'P0')\n    p1_count = sum(1 for i in issues if i['level'] == 'P1')\n    \n    print(f\"版本 {version} 审核结果:\")\n    print(f\"  P0(必须修): {p0_count}\")\n    print(f\"  P1(建议修): {p1_count}\")\n    print(f\"  P2(可优化): {len(issues) - p0_count - p1_count}\")\n    \n    if p0_count > 0:\n        print(\"→ 进入下一轮迭代\")\n        return True\n    elif p1_count > 2:\n        print(\"→ 建议再修一轮\")\n        return True\n    else:\n        print(\"→ 达到交付标准 ✅\")\n        return False\n```\n\n### 10.4 实战案例：三体EP1迭代记录\n\n| 版本 | 时长 | 问题发现 | 修复内容 | 审核结论 |\n|------|------|---------|---------|---------|\n| v5min | 252s | 视频总长252s但TTS仅127s，大量空白段落 | 重新按TTS时长裁剪 | ❌ P0: 节奏断裂 |\n| v6 | — | 音频驱动剪辑，3个短镜头被截断 | 修复中 | ❌ 未完成 |\n| v7 | 127s | 3个短镜头截断：火鸡演讲缺9s | stream_loop循环填充 | ❌ P0: 画面截断 |\n| v7.1 | 127.9s | 循环修复完成，但无字幕 | 加字幕 | ⚠️ P1: 缺字幕 |\n| v8 | 127.9s | 字幕+音画同步修复+矩阵表 | 全部修复 | ✅ 交付 |\n\n### 10.5 审核工具脚本\n\n```python\n#!/usr/bin/env python3\n\"\"\"一键审核脚本：检查所有段的音画同步和时长匹配\"\"\"\n\nimport subprocess\nfrom pathlib import Path\n\nFFPROBE = '/opt/homebrew/bin/ffprobe'\n\ndef get_duration(p):\n    r = subprocess.run([FFPROBE,'-v','quiet','-show_entries','format=duration',\n                        '-of','csv=p=0',str(p)], capture_output=True, text=True)\n    return float(r.stdout.strip())\n\ndef audit(segments_dir, tts_dir, num_segments=25):\n    issues = []\n    print(f\"{'#':>3} {'角色':<20} {'TTS':>7} {'视频':>7} {'偏差':>7} {'状态'}\")\n    print(\"-\" * 55)\n    \n    for i in range(num_segments):\n        seg = Path(segments_dir) / f\"seg_{i:03d}.mp4\"\n        tts = sorted(Path(tts_dir).glob(\"*.mp3\"))[i]\n        \n        seg_dur = get_duration(seg) if seg.exists() else 0\n        tts_dur = get_duration(tts)\n        diff = seg_dur - tts_dur\n        \n        status = \"✅\" if abs(diff) < 0.5 else \"⚠️\"\n        if abs(diff) > 0.5:\n            issues.append(f\"#{i}: 偏差{diff:+.2f}s\")\n        \n        print(f\"{i:3d} {tts.stem:<20s} {tts_dur:>6.2f}s {seg_dur:>6.2f}s {diff:>+6.2f}s {status}\")\n    \n    print(f\"\\n问题段: {len(issues)}\")\n    for issue in issues:\n        print(f\"  {issue}\")\n    \n    return issues\n\nif __name__ == '__main__':\n    audit(Path('v7_assets'), Path('ep1_tts'))\n```\n\nFile v1.0.0:references/sucuang_api.md\n\n# 速创API 接口文档与踩坑经验\n\n## 平台信息\n\n- **平台地址**: https://api.wuyinkeji.com\n- **注册链接**: https://api.wuyinkeji.com/user/register?cps=UXPjoCgN\n- **文档中心**: https://api.wuyinkeji.com/doc\n- **API Key获取**: 注册登录后进入控制台获取\n\n## 通用鉴权方式\n\n**推荐方式 — Authorization Header（不带Bearer前缀）：**\n```python\nHEADERS = {\n    \"Authorization\": \"你的API_KEY\",\n    \"Content-Type\": \"application/json\"\n}\n```\n\n**❌ 不要用URL参数传key：**\n```python\n# 会返回403，不要这样用\nrequests.get(\"https://api.wuyinkeji.com/api/xxx?key=你的API_KEY\")\n```\n\n---\n\n## 1. Grok Imagine 视频生成\n\n### 接口信息\n- **接口**: POST `/api/async/video/grok_imagine`\n- **价格**: ¥0.05/秒（按生成视频时长计费，不足1秒按1秒）\n- **点数**: 5点/秒\n- **免费额度**: 无\n- **QPS限制**: 100次/秒\n- **每日限制**: 付费用户不限制\n\n### 请求参数\n```json\n{\n  \"prompt\": \"英文描述效果更稳定，包含场景、光线、构图、镜头运动\",\n  \"duration\": 10,\n  \"style\": \"cinematic\"\n}\n```\n\n### 结果查询\n- **接口**: `GET /api/async/detail?id=xxx`\n- **轮询策略**: 每5秒查询一次\n- **状态码**: status=2 表示完成，status=0/1 表示处理中\n- **返回内容**: 包含视频下载URL\n\n### 批量生成策略\n```python\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\n\ndef submit_shot(shot):\n    # 提交生成任务\n    resp = requests.post(url, headers=HEADERS, json=params)\n    task_id = resp.json()[\"data\"][\"id\"]\n    # 轮询直到完成\n    while True:\n        result = requests.get(f\"{BASE}/detail?id={task_id}\", headers=HEADERS)\n        if result.json()[\"data\"][\"status\"] == 2:\n            return download_video(result.json()[\"data\"][\"video_url\"])\n        time.sleep(5)\n\n# 批量25个镜头同时提交\nwith ThreadPoolExecutor(max_workers=10) as executor:\n    futures = [executor.submit(submit_shot, shot) for shot in SHOTS]\n    for future in as_completed(futures):\n        results.append(future.result())\n```\n\n### 踩坑经验\n- Sora2接口（sora2/video）已不可用，持续返回400错误，全部使用Grok Imagine\n- 英文Prompt比中文Prompt效果更稳定\n- 平均重试3次才能获得满意结果\n- 生成耗时约30-60秒/个\n\n---\n\n## 2. TTS配音生成\n\n### 接口信息\n- **接口**: `POST /api/async/audio_tts`\n- **价格**: ¥0.0006/字\n- **返回格式**: tar包（需解压获取mp3）\n\n### 请求参数（重要：扁平JSON）\n```json\n{\n  \"text\": \"台词内容\",\n  \"voice_id\": \"male-qn-jingying\",\n  \"speed\": 1.0\n}\n```\n\n### 可用音色列表\n| 音色ID | 描述 | 适用角色 |\n|--------|------|---------|\n| male-qn-jingying | 精英青年男声 | 旁白、汪淼、常伟思 |\n| male-qn-badao | 霸道男声 | 史强 |\n| male-qn-daxuesheng | 大学生男声 | 研究员 |\n| male-chunhou | 醇厚男声 | 长辈角色 |\n| junlang_nanyou | 俊朗男声 | 潘寒 |\n| female-chengshu | 成熟女声 | 申玉菲 |\n| female-shaonv | 少女音 | 杨冬 |\n\n### 踩坑经验（重要）\n1. **❌ 不要传 format 参数** — 会报500\"存在未绑定的参数\"\n2. **❌ 不要嵌套参数** — 不要写成 `{\"model\":\"audio_tts\",\"params\":{...}}`，直接扁平JSON\n3. **✅ 状态码判断** — 用 `status == 2` 判断完成，不要用字符串 `\"completed\"`\n4. **⚠️ 部分任务会卡住** — status一直=0，重试可换到不同IP节点\n5. **✅ 返回tar包** — 需要用 `tarfile` 解压获取mp3文件\n\n### TTS生成代码模板\n```python\nimport requests, time, tarfile, io\n\ndef generate_tts(text, voice_id, output_path):\n    payload = {\"text\": text, \"voice_id\": voice_id, \"speed\": 1.0}\n    resp = requests.post(f\"{BASE}/api/async/audio_tts\", headers=HEADERS, json=payload)\n    task_id = resp.json()[\"data\"][\"id\"]\n    \n    while True:\n        result = requests.get(f\"{BASE}/api/async/detail?id={task_id}\", headers=HEADERS)\n        data = result.json()[\"data\"]\n        if data[\"status\"] == 2:  # 完成\n            audio_url = data[\"audio_url\"]\n            audio_resp = requests.get(audio_url)\n            tar = tarfile.open(fileobj=io.BytesIO(audio_resp.content))\n            for member in tar.getmembers():\n                if member.name.endswith('.mp3'):\n                    f = tar.extractfile(member)\n                    with open(output_path, 'wb') as out:\n                        out.write(f.read())\n            return\n        elif data[\"status\"] == -1:  # 失败\n            raise Exception(f\"TTS failed: {data}\")\n        time.sleep(3)\n```\n\n---\n\n## 3. 数字人视频生成\n\n### 接口信息\n- **接口**: `POST /api/async/video_digital_humans`\n- **价格**: 按次计费\n\n### 请求参数\n```json\n{\n  \"audio_url\": \"公网可访问的音频URL\",\n  \"video_url\": \"公网可访问的视频URL\"\n}\n```\n\n### 注意事项\n- 音频和视频URL必须公网可访问\n- 推荐搭配腾讯云COS存储素材\n\n---\n\n## 4. 腾讯云COS（素材存储）\n\n### 配置信息\n- **SecretId**: AKIDd9FF2hAh9QVegYIrbBZlz42zsgMyXyJU\n- **Bucket**: video-1304671784（广州区域 ap-guangzhou）\n- **用途**: 存储GEO项目视频和音频文件\n\n### 上传代码模板\n```python\nfrom qcloud_cos import CosConfig, CosS3Client\n\nconfig = CosConfig(Region=\"ap-guangzhou\", SecretId=SECRET_ID, SecretKey=SECRET_KEY)\nclient = CosS3Client(config)\n\nresponse = client.upload_file(\n    Bucket=\"video-1304671784\",\n    LocalFilePath=\"local_file.mp4\",\n    Key=\"remote_path/file.mp4\"\n)\n```\n\n---\n\n## 5. 其他可用模型\n\n速创API平台还提供以下模型（价格以平台实际为准）：\n- 文生图模型（多种）\n- 视频编辑模型\n- 语音识别\n- 大语言模型对话\n\n具体价格请查看：https://api.wuyinkeji.com/type/all","readmeExcerpt":"Skill: AI短剧制作助手 | AI Short Film Producer Owner: hitjcl Summary: AI短剧制作助手 | AI Short Film Producer — 低成本AI短剧/短片全流程制作技能。使用Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成。适用于从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动... Tags: ai:1.0.3, film:1.0.3, latest:1.0.3, production:1.0.3, video:1.0.3 Version history: v1.0.3 | 2026-04-30T11:23:17.316Z | user 标题改为中英文；移除外部链接和具体定价避免安全误报 v1.0.2 | 2026-04-30T09:50:26.768Z | use","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"Step 1: 脚本创作\n  ├── 确定主题/时长/风格\n  ├── 编写分镜脚本（镜头×台词×角色）\n  └── 输出：分镜表 + TTS文本清单\n\nStep 2: 视频镜头生成\n  ├── 调用速创API Grok Imagine\n  ├── 25个镜头批量异步生成\n  └── 输出：ep1_shots/*.mp4\n\nStep 3: TTS配音生成\n  ├── 调用速创API audio_tts\n  ├── 多角色多音色\n  └── 输出：ep1_tts/*.mp3\n\nStep 4: 音频驱动剪辑\n  ├── 逐段按TTS时长裁剪/循环镜头\n  ├── 短镜头自动stream_loop填充\n  └── 输出：分段seg_*.mp4\n\nStep 5: 字幕生成\n  ├── Python Pillow生成透明PNG字幕\n  ├── FFmpeg overlay叠加（因FFmpeg 8.x无drawtext）\n  └── 输出：带字幕的分段视频\n\nStep 6: 最终合成\n  ├── concat拼接25段视频\n  ├── concat拼接25段音频\n  ├── 音视频合并\n  └── 输出：最终成片.mp4\n\nStep 7: 素材导出\n  ├── 结构化桌面文件夹\n  ├── 矩阵表 + JSON\n  └── 成本核算"},{"language":"json","snippet":"{\n  \"text\": \"台词内容\",\n  \"voice_id\": \"male-qn-jingying\",\n  \"speed\": 1.0\n}"},{"language":"text","snippet":"每段（镜头, TTS）的处理流程：\n\n1. 获取TTS音频实际时长 tts_dur（用ffprobe精确到毫秒）\n2. 获取源视频时长 src_dur\n3. 对比决策：\n   ├── src_dur >= tts_dur + 0.5s  → 直接裁剪到tts_dur（视频多出的部分舍弃）\n   ├── src_dur ≈ tts_dur（差<0.5s）→ 直接裁剪，不做额外处理\n   └── src_dur < tts_dur           → stream_loop循环播放填满tts_dur\n4. 输出：seg_NNN.mp4（时长=tts_dur，精确匹配配音）"},{"language":"bash","snippet":"# 循环播放直到填满tts_dur\n/opt/homebrew/bin/ffmpeg -y -stream_loop -1 -i shot.mp4 -t {tts_dur} -c:v libx264 -preset fast seg.mp4"},{"language":"python","snippet":"# 关键：每段独立裁剪，不整体缩放\ncumulative = 0.0\nfor i, (tts_file, shot_file) in enumerate(segments):\n    tts_dur = get_duration(tts_file)  # ffprobe获取\n    # 精确裁剪到tts_dur，不依赖前一段的结束时间\n    trim_video(shot_file, tts_dur, f\"seg_{i:03d}.mp4\")\n    cumulative += tts_dur\n\n# 最终验证：所有seg时长之和 ≈ audio_concat时长 ≈ 最终成片时长"},{"language":"python","snippet":"from PIL import Image, ImageDraw, ImageFont\n\n# 创建透明PNG\nimg = Image.new('RGBA', (1920, 160), (0,0,0,0))\ndraw = ImageDraw.Draw(img)\nfont = ImageFont.truetype('/System/Library/Fonts/PingFang.ttc', 48)\n\n# 白色大字 + 黑色描边\ndraw.text((960, 80), \"台词文本\", fill='white', font=font, \n          anchor='mm', stroke_width=3, stroke_fill='black')\n\n# FFmpeg overlay叠加\nffmpeg -i seg.mp4 -i sub.png -filter_complex \"overlay=0:H-h\" output.mp4"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: ai-short-film-producer\ndescription: AI短剧制作助手 | AI Short Film Producer — 低成本AI短剧/短片全流程制作技能。使用Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成。适用于从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动剪辑、字幕叠加、最终合成、成本核算的全套SOP。\n---\n\n# AI短剧制作助手 | AI Short Film Producer\n\n## 概述\n\n本Skill提供一套完整的**低成本AI短剧制作流程**，从脚本创作到最终成片，总成本仅需**¥30-50/部**（128秒短片）。核心思路：用AI API生成素材 → 本地FFmpeg合成 → WorkBuddy编排调度。\n\n**适用场景：**\n- 用户说\"帮我做一个短片/短剧/预告片\"\n- 用户说\"把这段文案做成视频\"\n- 用户说\"生成一个XX题材的短视频\"\n- 用户需要从零到一完成AI视频制作\n\n**核心成本优势：**\n- 视频生成：Grok Imagine（速创API，按秒计费）\n- 配音生成：TTS（速创API，按字计费）\n- 合成剪辑：本地FFmpeg免费\n- AI编排：WorkBuddy Lite版\n\n---\n\n## 制作流程总览\n\n```\nStep 1: 脚本创作\n  ├── 确定主题/时长/风格\n  ├── 编写分镜脚本（镜头×台词×角色）\n  └── 输出：分镜表 + TTS文本清单\n\nStep 2: 视频镜头生成\n  ├── 调用速创API Grok Imagine\n  ├── 25个镜头批量异步生成\n  └── 输出：ep1_shots/*.mp4\n\nStep 3: TTS配音生成\n  ├── 调用速创API audio_tts\n  ├── 多角色多音色\n  └── 输出：ep1_tts/*.mp3\n\nStep 4: 音频驱动剪辑\n  ├── 逐段按TTS时长裁剪/循环镜头\n  ├── 短镜头自动stream_loop填充\n  └── 输出：分段seg_*.mp4\n\nStep 5: 字幕生成\n  ├── Python Pillow生成透明PNG字幕\n  ├── FFmpeg overlay叠加（因FFmpeg 8.x无drawtext）\n  └── 输出：带字幕的分段视频\n\nStep 6: 最终合成\n  ├── concat拼接25段视频\n  ├── concat拼接25段音频\n  ├── 音视频合并\n  └── 输出：最终成片.mp4\n\nStep 7: 素材导出\n  ├── 结构化桌面文件夹\n  ├── 矩阵表 + JSON\n  └── 成本核算\n```\n\n---\n\n## 详细步骤\n\n### Step 1: 脚本创作\n\n**输入：** 用户需求（主题、风格、时长、参考素材）\n**输出：** 分镜脚本文档 + TTS台词清单\n\n**工作流程：**\n1. 与用户确认主题方向（科幻/悬疑/科普/剧情等）\n2. 编写分镜脚本，包含：\n   - 镜头编号、画面描述、时长\n   - 配音台词、角色分配、音色选择\n   - 音效说明\n3. 输出TTS台词清单（25段以内，每段2-20字最佳）\n4. 角色音色分配表：\n\n| 角色类型 | 推荐音色ID | 说明 |\n|---------|-----------|------|\n| 旁白/叙述者 | male-qn-jingying | 精英青年男声，通用 |\n| 男主角 | male-qn-jingying | 精英青年男声 |\n| 霸道/硬汉 | male-qn-badao | 霸道男声 |\n| 反派/俊朗 | junlang_nanyou | 俊朗男声 |\n| 成熟女性 | female-chengshu | 成熟女声 |\n| 少女 | female-shaonv | 少女音 |\n| 研究员/学生 | male-qn-daxuesheng | 大学生男声 |\n| 醇厚长辈 | male-chunhou | 醇厚男声 |\n\n### Step 2: 视频镜头生成（速创API Grok Imagine）\n\n**API平台：** 速创API（详见 references/sucuang_api.md）\n**模型：** Grok Imagine（xAI Aurora引擎）\n**价格：** 按秒计费（具体见平台）\n\n**API调用方式：**\n- 鉴权：Authorization Header 传API Key（不带Bearer前缀）\n- 接口：POST /api/async/video/grok_imagine\n- 参数格式：扁平JSON\n- 结果查询：GET /api/async/detail?id=xxx（轮询直到status=2）\n\n**批量生成策略：**\n1. 25个镜头同时提交（用ThreadPoolExecutor）\n2. 每个镜头约10秒，生成耗时约30-60秒\n3. 失败自动重试（平均重试3次）\n4. 注意：Sora2接口已不可用（持续400错误），全部使用Grok Imagine\n\n**Prompt编写要点：**\n- 英文Prompt效果更稳定\n- 包含：场景描述、光线、构图、镜头运动\n- 示例：`\"Deep space, Milky Way galaxy slowly rotating, cinematic wide shot, photorealistic, 4K quality\"`\n\n### Step 3: TTS配音生成（速创API audio_tts）\n\n**API接口：** POST /api/async/audio_tts\n**价格：** 按字计费（具体见平台）\n**参数格式（重要）：** 扁平JSON，不要嵌套\n\n```json\n{\n  \"text\": \"台词内容\",\n  \"voice_id\": \"male-qn-jingying\",\n  \"speed\": 1.0\n}\n```\n\n**注意事项（踩坑经验）：**\n- ❌ 不要传 format 参数（会报500\"存在未绑定的参数\"）\n- ❌ 不要嵌套成 `{\"model\":\"audio_tts\",\"params\":{...}}`\n- ✅ 状态码判断：status=2 完成，status=0/1 处理中\n- ⚠️ 部分任务会卡住（status一直=0），重试可换IP节点\n- ✅ 返回tar包，需解压获取mp3\n\n### Step 4: 音频驱动剪辑（核心节奏控制）\n\n**核心理念：** 画面长度由语音旁白决定，而非固定时长。先录制/生成TTS配音，再让每段视频精确匹配对应配音的时长。这样保证音画天然同步，且节奏由配音自然驱动。\n\n#### 4.1 节奏控制逻辑\n\n```\n每段（镜头, TTS）的处理流程：\n\n1. 获取TTS音频实际时长 tts_dur（用ffprobe精确到毫秒）\n2. 获取源视频时长 src_dur\n3. 对比决策：\n   ├── src_dur >= tts_dur + 0.5s  → 直接裁剪到"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn703gwc11aqnnaatk69f339d9822e08\",\n  \"slug\": \"ai-short-film-producer\",\n  \"version\": \"1.0.3\",\n  \"publishedAt\": 1777548197316\n}"},{"path":"references/production_workflow.md","content":"# AI短剧制作流程详细参考\n\n## 一、项目启动\n\n### 需求确认\n与用户确认以下信息：\n1. **主题**：科幻/悬疑/科普/剧情/搞笑/教育等\n2. **风格**：写实/动画/赛博朋克/古风等\n3. **时长**：30秒/60秒/2分钟/5分钟\n4. **角色**：需要几个角色？是否有特定音色要求？\n5. **参考素材**：用户是否提供文案/图片/参考视频？\n\n### 脚本模板\n\n```markdown\n# 项目名称 · 分镜脚本\n\n## 总览\n- 总时长：XX秒\n- 镜头数：XX个\n- 角色数：XX个\n\n## 分镜表\n| # | 镜头ID | 画面描述 | 配音台词 | 角色 | 音色 | 时长 |\n|---|--------|---------|---------|------|------|------|\n| 1 | shot01_xxx | 画面描述 | 台词内容 | 角色名 | 音色ID | 10s |\n| 2 | shot02_xxx | 画面描述 | 台词内容 | 角色名 | 音色ID | 10s |\n```\n\n---\n\n## 二、视频生成\n\n### Grok Imagine Prompt编写指南\n\n**结构模板：**\n```\n[场景描述], [主体描述], [光线/氛围], [构图/镜头运动], [风格关键词]\n```\n\n**示例：**\n```\n\"Deep space, Milky Way galaxy slowly rotating across a star-filled cosmos,\ncountless stars twinkling, nebulae in deep blue and purple hues,\ncinematic wide shot, photorealistic, 4K quality, slow gentle rotation\"\n```\n\n**各类型场景Prompt关键词：**\n\n| 场景类型 | 关键词 |\n|---------|--------|\n| 太空/宇宙 | deep space, stars, nebula, galaxy, cosmic, celestial |\n| 城市/街头 | city street, urban, bustling, modern, buildings |\n| 室内/会议室 | conference room, modern, screens, professional |\n| 人物特写 | close-up, portrait, expression, emotion, cinematic lighting |\n| 自然/风景 | landscape, mountains, ocean, sunset, cinematic |\n| 科技/实验室 | laboratory, technology, screens, equipment, futuristic |\n\n### 批量提交策略\n\n1. 25个镜头同时提交到API\n2. 使用ThreadPoolExecutor(max_workers=10)\n3. 每5秒轮询一次结果\n4. 失败自动重试（最多5次）\n5. 下载后检查文件完整性（ffprobe验证时长）\n\n---\n\n## 三、TTS配音生成\n\n### 多角色音色分配策略\n\n| 角色数量 | 分配策略 |\n|---------|---------|\n| 1-2个角色 | 旁白用jingying，对话角色用对应音色 |\n| 3-5个角色 | 主要角色各分配独立音色，次要角色复用 |\n| 6-10个角色 | 核心角色独立音色，路人/群演用通用音色 |\n\n### 台词字数控制\n- 每段TTS建议2-20字（太长影响听感）\n- 10秒镜头配2-4秒台词最合适\n- 留白时间给观众消化内容\n\n---\n\n## 四、音频驱动剪辑（核心节奏控制）\n\n### 核心理念\n\n**音频驱动剪辑 = 画面长度由语音旁白决定，而非固定时长。**\n\n传统剪辑思维是\"先定视频长度，再往里塞配音\"，结果配音节奏被画面绑架。音频驱动反过来——先录制TTS配音，再让每段视频精确匹配对应配音的时长。这样：\n- 观众听到的每句话都有完整的画面时长\n- 叙事节奏由台词自然驱动\n- 不会出现\"话没说完画面就切了\"\n\n### 核心算法\n\n```\n对于每一段（镜头, TTS）：\n  1. 获取TTS音频时长 tts_dur（ffprobe精确到毫秒）\n  2. 获取源视频时长 src_dur\n  3. 对比决策：\n     ├── src_dur >= tts_dur + 0.5s  → 直接裁剪到tts_dur\n     ├── src_dur ≈ tts_dur（差<0.5s）→ 直接裁剪\n     └── src_dur < tts_dur           → stream_loop循环填充\n  4. 输出：seg_NNN.mp4（时长精确=tts_dur）\n```\n\n### 逐段精确裁剪（避免累积漂移）\n\n```python\nimport subprocess\nfrom pathlib import Path\n\nFFPROBE = '/opt/homebrew/bin/ffprobe'\nFFMPEG = '/opt/homebrew/bin/ffmpeg'\n\ndef get_duration(filepath):\n    \"\"\"获取媒体文件精确时长\"\"\"\n    result = subprocess.run(\n        [FFPROBE, '-v', 'quiet', '-show_entries', 'format=duration',\n         '-of', 'csv=p=0', str(filepath)],\n        capture_output=True, text=True\n    )\n    return float(result.stdout.strip())\n\ndef process_segment(tts_file, shot_file, output_file):\n    \"\"\"处理单段：按TTS时长裁剪/循环视频\"\"\"\n    tts_dur = get_duration(tts_file)\n    src_dur = get_duration(shot_file)\n    \n    cmd = [FFMPEG, '-y']\n    \n    if src_dur >= tts_dur:\n        # 视频够长，直接裁剪\n        cmd.extend(['-t', str(tts_dur), '-i', str(shot_file)])\n    else:\n        # 视频不够长，循环填充\n        cmd.extend(['-stream_loop', '-1', '-i', str(shot_file),\n                     '-t', str(tts_dur)])\n    \n    cmd.extend(['-c:v', 'lib"},{"path":"references/sucuang_api.md","content":"# 速创API 接口文档与踩坑经验\n\n## 平台信息\n\n- **平台地址**: （注册后获取）\n- **文档中心**: （注册后获取）\n- **API Key获取**: 注册登录后进入控制台获取\n\n## 通用鉴权方式\n\n**推荐方式 — Authorization Header（不带Bearer前缀）：**\n```python\nHEADERS = {\n    \"Authorization\": \"你的API_KEY\",\n    \"Content-Type\": \"application/json\"\n}\n```\n\n**❌ 不要用URL参数传key：**\n```python\n# 会返回403，不要这样用\nrequests.get(\"平台API地址/api/xxx?key=你的API_KEY\")\n```\n\n---\n\n## 1. Grok Imagine 视频生成\n\n### 接口信息\n- **接口**: POST `/api/async/video/grok_imagine`\n- **价格**: 按秒计费（具体见平台）\n- **点数**: 5点/秒\n- **免费额度**: 无\n- **QPS限制**: 100次/秒\n- **每日限制**: 付费用户不限制\n\n### 请求参数\n```json\n{\n  \"prompt\": \"英文描述效果更稳定，包含场景、光线、构图、镜头运动\",\n  \"duration\": 10,\n  \"style\": \"cinematic\"\n}\n```\n\n### 结果查询\n- **接口**: `GET /api/async/detail?id=xxx`\n- **轮询策略**: 每5秒查询一次\n- **状态码**: status=2 表示完成，status=0/1 表示处理中\n- **返回内容**: 包含视频下载URL\n\n### 批量生成策略\n```python\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\n\ndef submit_shot(shot):\n    # 提交生成任务\n    resp = requests.post(url, headers=HEADERS, json=params)\n    task_id = resp.json()[\"data\"][\"id\"]\n    # 轮询直到完成\n    while True:\n        result = requests.get(f\"{BASE}/detail?id={task_id}\", headers=HEADERS)\n        if result.json()[\"data\"][\"status\"] == 2:\n            return download_video(result.json()[\"data\"][\"video_url\"])\n        time.sleep(5)\n\n# 批量25个镜头同时提交\nwith ThreadPoolExecutor(max_workers=10) as executor:\n    futures = [executor.submit(submit_shot, shot) for shot in SHOTS]\n    for future in as_completed(futures):\n        results.append(future.result())\n```\n\n### 踩坑经验\n- Sora2接口（sora2/video）已不可用，持续返回400错误，全部使用Grok Imagine\n- 英文Prompt比中文Prompt效果更稳定\n- 平均重试3次才能获得满意结果\n- 生成耗时约30-60秒/个\n\n---\n\n## 2. TTS配音生成\n\n### 接口信息\n- **接口**: `POST /api/async/audio_tts`\n- **价格**: 按字计费（具体见平台）\n- **返回格式**: tar包（需解压获取mp3）\n\n### 请求参数（重要：扁平JSON）\n```json\n{\n  \"text\": \"台词内容\",\n  \"voice_id\": \"male-qn-jingying\",\n  \"speed\": 1.0\n}\n```\n\n### 可用音色列表\n| 音色ID | 描述 | 适用角色 |\n|--------|------|---------|\n| male-qn-jingying | 精英青年男声 | 旁白、汪淼、常伟思 |\n| male-qn-badao | 霸道男声 | 史强 |\n| male-qn-daxuesheng | 大学生男声 | 研究员 |\n| male-chunhou | 醇厚男声 | 长辈角色 |\n| junlang_nanyou | 俊朗男声 | 潘寒 |\n| female-chengshu | 成熟女声 | 申玉菲 |\n| female-shaonv | 少女音 | 杨冬 |\n\n### 踩坑经验（重要）\n1. **❌ 不要传 format 参数** — 会报500\"存在未绑定的参数\"\n2. **❌ 不要嵌套参数** — 不要写成 `{\"model\":\"audio_tts\",\"params\":{...}}`，直接扁平JSON\n3. **✅ 状态码判断** — 用 `status == 2` 判断完成，不要用字符串 `\"completed\"`\n4. **⚠️ 部分任务会卡住** — status一直=0，重试可换到不同IP节点\n5. **✅ 返回tar包** — 需要用 `tarfile` 解压获取mp3文件\n\n### TTS生成代码模板\n```python\nimport requests, time, tarfile, io\n\ndef generate_tts(text, voice_id, output_path):\n    payload = {\"text\": text, \"voice_id\": voice_id, \"speed\": 1.0}\n    resp = requests.post(f\"{BASE}/api/async/audio_tts\", headers=HEADERS, json=payload)\n    task_id = resp.json()[\"data\"][\"id\"]\n\n    while True:\n        result = requests.get(f\"{BASE}/api/async/detail?id={task_id}\", headers=HEADERS)\n        data = result.json()[\"data\"]\n        if data[\"status\"] == 2:  # 完成\n            audio_url = data[\"audio_url\"]\n            audio_resp = requests.get(audio_url)\n            tar = tarfile.open(fileobj=io.BytesIO(audio_"},{"path":"skill-card.md","content":"## Description:\n\nAI短剧制作助手 | AI Short Film Producer helps agents plan and produce low-cost AI short films by creating shot scripts, generating video and TTS assets through third-party APIs, and assembling them locally with FFmpeg and Python.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[hitjcl](https://clawhub.ai/user/hitjcl)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users, developers, and creative operators use this skill to turn a topic, script, or concept into an AI short film workflow with shot planning, video generation, voiceover generation, subtitles, local composition, review, and cost tracking.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The workflow uses third-party video and TTS APIs that may receive user prompts, scripts, or generated content.\n\nMitigation: Do not submit secrets, regulated data, private scripts, or sensitive personal information to the referenced APIs; review provider terms before use.\n\nRisk: API keys may be exposed if copied into URLs, logs, scripts, or shared project files.\n\nMitigation: Pass API keys through headers or a local secret store, keep them out of URLs and logs, and avoid committing generated credentials or configuration files.\n\nRisk: Downloaded media archives and generated assets are processed locally with Python and FFmpeg.\n\nMitigation: Use request timeouts, retry limits, trusted download hosts, archive size checks, and safe FFmpeg concat manifests before processing untrusted media folders.\n\nRisk: Generated footage, TTS, or subtitles can be inaccurate, poorly synchronized, or visually defective.\n\nMitigation: Run the documented review workflow for audio-video sync, subtitle accuracy, duration drift, repeated loops, and visual quality before publishing.\n\n## Reference(s):\n\n- [AI Short Film Producer skill page](https://clawhub.ai/hitjcl/skills/ai-short-film-producer)\n- [AI短剧制作流程详细参考](artifact/references/production_workflow.md)\n- [速创API 接口文档与踩坑经验](artifact/references/sucuang_api.md)\n\n## Skill Output:\n\n**Output Type(s):** [Guidance, Markdown, Code, Shell commands, Configuration]\n\n**Output Format:** [Markdown with JSON, Python, and shell command examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Produces workflow guidance and implementation snippets for scripts, generated media assets, subtitles, FFmpeg composition, review checks, and cost calculations.]\n\n## Skill Version(s):\n\n1.0.3 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"AI短剧制作助手 | AI Short Film Producer — 低成本AI短剧/短片全流程制作技能。使用Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成。适用于从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动... Skill: AI短剧制作助手 | AI Short Film Producer Owner: hitjcl Summary: AI短剧制作助手 | AI Short Film Producer — 低成本AI短剧/短片全流程制作技能。使用Grok Imagine生成视频镜头、TTS生成配音，配合FFmpeg+Python本地合成。适用于从零制作AI短片、短视频、短剧EP、预告片等场景。包含完整的分镜脚本创作、视频生成、配音生成、音频驱动... Tags: ai:1.0.3, film:1.0.3, latest:1.0.3, production:1.0.3, video:1.0.3 Version history: v1.0.3 | 2026-04-30T11:23:17.316Z | user 标题改为中英文；移除外部链接和具体定价避免安全误报 v1.0.2 | 2026-04-30T09:50:26.768Z | use","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1235,"uniquenessScore":48,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T07:37:12.770Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T07:37:12.770Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:31:03.033Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}