图像与设计
需要把任意 URL 或 GitHub 仓库做成约…
适用于用真实浏览器走查任意 URL(GitHub 仓库、产品页、文档站、博客或发布页),生成约 60-80 秒、带浏览器边框、头像口型同步和元素缩放解说的视频。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
需要把任意 URL 或 GitHub 仓特定
解决思路
- 在任何付费 MCP 调用前,调用 `identity_balance({verbose: true})` 一次。
- 展示当前余额、近期消耗速率和剩余可用量。
- 用指定消息做成本门禁:估算成本约 50-500 credits(约 $0.50-$5.00),取决于 lipsync provider、旁白、字幕和 preview 模式;用户回复 `proceed` 才继续,回复 `cancel` 则停止。
- 成本门禁在 URL 和可选 flags 已知后、头像生成、语音、lipsync、字幕、视频合成前执行。
- 静默解析 avatar/voice,不问用户是否使用头像或选择哪个 voice。
- 尊重显式 `--avatar`、`--voice`;否则生成 presenter avatar 并选默认 voice。
- 只有成本门禁要求 `proceed`;`--preview` 对显式 avatar 默认 opt-in,但 generated/regenerated fallback avatar 强制自动 preview。
- 不主动询问 `--focus`,先按页面结构自信尝试,用户可用 `--focus X` 重跑。
- Claude Desktop 不能把粘贴图片传给 MCP 工具;若用户粘贴照片或提本地文件作 `--avatar`,暂停 Step1 并提示粘贴 URL 或附文件。
- 本地文件到达后,用 `upload_asset` 转成 public URL,把返回 `public_url` 作为 `--avatar <url>`;已托管 `https://...` 可直接用;无 avatar 则静默生成 presenter portrait。
- Step0:从 `$ARGUMENTS` 去掉 flags 和 key=value 参数。
- 若剩余无 `https://...` URL 或为空,原样打印菜单并停止等待用户下一条消息,不调工具。
- 若已有 URL,跳过 Step0 静默进入 Step1;用户回复 URL 后视为解析输入,不再重复询问。
- Step1 必填 `url` 必须 `https://...`;可选参数 `--avatar <url>`、`--voice <minimax-voice-id>`、`--focus ...`、`--live-url <url>`、`--lipsync-provider <pika|kling>`、`--no-captions`、`--preview`;`--skip-preview` 和 `--yes` 为 no-op。
- 模式检测:GitHub 模式 = host `github.com` 且 path `/{owner}/{repo}` 无更深段,启用 README 扫描、live-demo 检测、GitHub selectors;其他为 Generic-URL 模式,跳过 GitHub extras,用通用 CSS selectors 走 URL 本身。
- Avatar 解析:有 `--avatar <url>` 就用;否则调 `generate_image` 一次,prompt 为 professional presenter, friendly tech narrator, studio portrait, 1:1, natural lighting,用返回 URL;记录 `avatar_source` 为 `explicit`、`generated` 或 `regenerated`。
- Avatar suitability gate:在 Step4 TTS 和任何 `generate_lipsync` 预览/全量前,调 `analyze_media(media=<avatar>, query=<gate_query>)` 一次。
- Gate query 返回 JSON,含 `is_single_front_facing_coherent_human_face`、`has_visible_mouth`、`is_faceless_or_masked`、`is_mascot_illustration_or_non_human`、`face_suitability_score`、`apparent_gender`、`reason`。
- 仅当 `is_single_front_facing_coherent_human_face == true`、`has_visible_mouth == true`、`is_faceless_or_masked == false`、`is_mascot_illustration_or_non_human == false`、`face_suitability_score >= 75` 才通过。
- 若 explicit avatar 失败,付费 lipsync 前停止,要求 `--avatar <real-looking-photo-url>` 或允许生成 presenter portrait。
- 若 generated avatar 失败,用 prompt 为 realistic professional presenter portrait, single front-facing coherent human face, visible mouth, friendly tech narrator, neutral studio background, 1:1, natural lighting 再 `generate_image` 一次,设 `avatar_source = regenerated` 并重跑 gate;再失败则报错中止。
- 若 `avatar_source` 为 `generated` 或 `regenerated`,设 `avatar_auto_preview_required = true`;否则除非用户传 `--preview`,为 false。
- Voice 解析:有 `--voice <id>` 就用;否则选 MiniMax `speech-2.8-hd` 预设匹配 avatar apparent gender:female → `English_PlayfulGirl`,male → `English_Jovialman`,unclear → `English_Jovialman`。
- 根据 avatar suitability gate 的 `apparent_gender` 推断,不询问用户;不要用 `English_FriendlyPerson`;其他 female 可用 `English_Upbeat_Woman`、`English_LovelyGirl`、`English_radiant_girl`。
- Step2:Both 模式用 `WebFetch` 拉输入 URL 主内容(h1、hero、headings、primary copy)。
- 构建 `proper_noun_glossary`,包含产品、repo、公司、模型、框架和专有名词规范拼写,来自 URL/domain、页面标题、h1、README headings、repo metadata、包名和重复大写 token;GitHub 保留 README/source scan 的准确拼写如 `Ollama`、`Llama`、`DeepSeek`、`Gemma`,用于旁白和字幕防止 `Olama`、`DeepSeq` 等漂移。
- GitHub 模式额外:拉顶层文件树、(best-effort) `package.json`/`pyproject.toml`、`gh api repos/{owner}/{repo}` 获取 `homepage`、`description`、`language`、`topics`。
- 按优先级检测候选 `live_url`:1 用户 `--live-url`;2 GitHub API `meta.homepage`;3 `package.json` 的 `homepage`;4 README 中首个匹配 vercel.app/netlify.app/github.io/fly.dev/railway.app/render.com/herokuapp.com/surge.sh 的 URL;5 README 中 badge area / Live Demo / Project Page / Demo 文字指向的任意 URL;6 GitHub Pages `https://{owner}.github.io/{repo}`,仅当深树含 frontend signal(`index.html`、`App.tsx`、`App.jsx`、`App.vue`、`app.py`、`main.py`)。
- 若无候选 `live_url`,beat sheet 跳过 beats 6-7。
- Generic-URL 模式:输入 URL 是唯一 URL,不推断 `live_url`,不拉额外 metadata;跳过 Step2.5 和 Step3.0,直接 Step3。
- Step2.5:GitHub 模式写 beats 6-7 前,对候选 `live_url` 用 `WebFetch` 验证可达性;4xx/5xx 则 drop 到 None 并跳过 beats 6-7。
- 若响应是 GitHub Pages 404 — There isn't a GitHub Pages site here. 模板,或 body 含 There isn't a GitHub Pages site here,也 drop 并跳过;否则保留。
- Step2.6 Generic URL pre-flight:WebFetch 输入 URL 检查,防止录 captcha/bot-block、cookie banner 吃掉前 3 秒、通用 selector 错过 hero/sections。
- 若 body 含 Verify you are human、verify you are not a robot、captcha、CAPTCHA、reCAPTCHA、403 Forbidden、Access Denied、Just a moment 加 cf-chl-bypass、We're sorry, something went wrong,或 title/h1 只是 Robot Check/Are you a robot?,ABORT 并告知用户 headless Chrome 无法渲染。
- 扫描 cookie/consent:id/class 以 `onetrust-`、`truste-`、`cookie-banner`、`cookie-consent`、`gdpr-`、`consent-`、`cmp-` 开头;按钮匹配 `(?i)accept (all )?cookies`、`(?i)agree.{0,10}cookies`、`(?i)i (accept|agree)`;Apple id `ac-gdpr-banner` 或 class `as-globalfooter-curtain`;Google consent `[role='dialog']` 文本 Before you continue;检测到则 `cookie_banner_present = true`。
- 若检测到 cookie banner,防御双层:在 `capture_website` 传 `extra_css` 隐藏常见 banner;在 `at_s: 0.0` 对最可能 dismissal selector 发 `click` `timed_action`(如 `#onetrust-accept-btn-handler`、`[aria-label*='Accept all' i]`、`button[id*='accept']`)。
- 使用给定 `extra_css` payload:`#onetrust-banner-sdk, #onetrust-pc-sdk, #onetrust-consent-sdk { display: none !important; } #truste-consent-track, #truste-consent-content, .truste_box_overlay { display: none !important; } [id*='gdpr-cookie'], [id*='cookie-consent'], [id*='cookie-banner'] { display: none !important; } [class*='cookie-banner'], [class*='cookie-consent'], [class*='consent-banner'] { display: none !important; } [class*='CookieBanner'], [class*='CookieConsent'], [class*='ConsentBanner'] { display: none !important; } #ac-gdpr-banner, .as-globalfooter-curtain { display: none !important; } [role='dialog'][aria-label*='cookie' i], [role='dialog'][aria-label*='consent' i] { display: none !important; } .cmp-container, .cmp-modal, .cmp-banner { display: none !important; }`
- Generic-URL 真实 DOM 识别:对每个 beat 优先用 WebFetch 观察到的实际 DOM 元素;读 rendered HTML/markdown,记录 primary h1 文本/class、section 结构、CTA/signup/pricing 元素。
- 对每个 `zoom_target.selector` 按 selector ladder:1 稳定 id/class(`#hero`、`.tile-headline`、`.as-headline-section-title`、`.pricing-card`);2 accessibility/link 属性(`[aria-label*='Get started' i]`、`a[href*='pricing']`、`a[href='/new']`);3 语义结构(`main > section:nth-of-type(N) h2`、`main section:nth-of-type(N) [role='img']`、`footer h2`);4 broad fallback(`h1`、`main`、`section h2`、`button`、`a[href]`)。
- 所有 selector 必须是 `document.querySelector` 可解析的 vanilla CSS;不要 `:contains(...)`、`:has-text(...)`、`text=...` 或 XPath。
- 若 WebFetch 少于 3 个可见 headings 或文本极少,视为 SPA/lazy-render,emit 更长 initial wait `{type: wait, at_s: 0.0, ms: 2500}`,普通页 1500ms。
- `--focus` 若提供则遵循,不主动询问;无 `--focus` 用 generic structure cues 静默自信首轮;有则锚定匹配的具体页面 sections,忽略无关营销 chrome。
- Step3.0 GitHub only:写 beat sheet 前扫描 README(大小写不敏感全文)必需 section,找到则必须加 dedicated beat,必要时替换 generic beats 4-5。
- README section 到 beat 映射:`overview`/`what is` → scroll_to heading,zoom `.markdown-heading:has(#user-content-overview) .heading-element`;`how it works` → `.markdown-heading:has(#user-content-how-it-works) .heading-element`;`audio layer`/`audio timeline` → scroll_to audio-layer diagram,zoom 渲染图或周围 heading;`claude code`/`mcp integration` → scroll_to section,zoom `article pre` 或 `.highlight`;`architecture`/`system design` → `.markdown-heading:has(#user-content-architecture) .heading-element`;`features` 顶部显著 → `.markdown-heading:has(#user-content-features) .heading-element`;`getting started`/`quick start`/`installation` → `.markdown-heading:has(#user-content-installation) .heading-element` 或 `article pre`;`usage`/`examples` → `.markdown-heading:has(#user-content-usage) .heading-element` 或其第一个 code block。
- GitHub heading slug 规则:lowercase、空格转 dash、去掉非 `[a-z0-9-]` 字符;如 How it works → `#user-content-how-it-works`。
- GitHub DOM verified 2026-05-28:repo name `strong[itemprop='name'] a`;README body `.markdown-body`;README title `.markdown-body h1.heading-element`;section headings `.markdown-heading:has(#user-content-<slug>) .heading-element`,fallback `.markdown-body h2.heading-element`。
- 若 GitHub beat 的 `action_bboxes[].found` 为 false,停止并重新验证 GitHub 当前 DOM,不要用 default-position fallback。
- Selector contract:`bbox_selector` 必须是 `document.querySelector` 可解析的 vanilla CSS;避免 `:has-text(...)`、`text=...`、`:visible`;CSS Level 4 `:has(...)` 可用。
- Step3 编写 JSON array 8-10 beats,硬总时长 65-80 秒,硬总词数 165-200 words(按 2.5 words/sec)。
- 每个 beat 字段:`t_start`、`t_end`、`action`(含 `type` 为 `navigate`/`scroll_to`/`hover`、`url`、`selector`)、`zoom_target`(含 `selector`、`description`)、`vo_text`(1-2 句对话)。
- Hard constraints:每 beat 五字段;`t_start` beat0=0.0;`t_end[i] == t_start[i+1]`;`len(vo_text.split())/2.5` ≈ `t_end - t_start` 且 ±10%;最后 `t_end <= 80` 秒;总词数 165-200。
- 每 beat `zoom_target.selector` 必须对落地页面有效 CSS;GitHub 优先 `strong[itemprop='name'] a`、`.markdown-body h1.heading-element`、`.markdown-heading:has(#user-content-<slug>) .heading-element`、`.markdown-body h2.heading-element`、`.blob-code-inner`、`.highlight`、`.octicon-star`、`nav`;Generic 优先 `h1`、`[role='main']`、`main`、`header`、`nav`、`.hero`、`.feature`、`section h2`、`[class*='cta']`、`[class*='hero']`、`button`、`a[href]`;选择器需在 action 稳定后解析,发前用 WebFetch DOM 验证。
- `vo_text` 1-2 句对话,dev voice,无 stage directions,无 markdown;`action.url` 当 `type == navigate` 时是有效 `https://...`。
- Step4 前自检:`total_words` 在 `[165,200]` 且 `total_seconds`(`beats[-1].t_end`)在 `[65,80]`;任一越界则重写 beat sheet,不进入 TTS。
- GitHub 结构骨架:Beat1 navigate repo root,zoom `strong[itemprop='name'] a`,hook;Beats2-3 navigate 具体源码文件 `https://github.com/{owner}/{repo}/blob/HEAD/<path>`,zoom `.blob-code-inner` 或 `.highlight`,选与 narration 声明匹配的文件;Beats4-5 scroll_to README sections,zoom heading/body,Step3.0 要求时替换;Beats6-7 仅 `live_url` 存活时 navigate 到它,zoom `nav`/`h1`/`.hero`/`main`/`button`/`.feature`;Beat8 回 repo root,zoom `.octicon-star`,outro。
- Generic 结构骨架:Beat1 navigate 输入 URL,zoom `h1` 或 `[class*='hero'] h1`,hook;Beats2-3 scroll_to hero/value-prop/first feature,zoom `.hero`、`[class*='hero']`、`[class*='feature']`、`section:nth-of-type(1) h2`;Beats4-5 scroll_to 更深 sections,zoom `section h2`、`[class*='feature'] img`、`[class*='testimonial']`、`[class*='pricing']` 或显著语义元素;Beats6-7 scroll_to CTA/signup/demo,zoom `[class*='cta']`、`button`、`a[class*='button']`、`[id*='signup']`;Beat8 scroll_to footer/closing,zoom `footer h2`、`footer` 或回顶 `h1`,outro。
- 若 `--focus` 提供,融入 `vo_text` 但不改结构骨架;优先 CSS selectors 而非 `text_content`。
- Step4 TTS:调 `generate_speech`,`provider: minimax-tts`,`text` 为完整 `vo_text` join,可选 `voice_id`(来自 `--voice` 或 Step1 默认预设)。
- 捕获 `result.audio_url`(dispatcher 返回在 `audio_url` 不是 `url`)和 `result.duration_seconds`。
- Stale-voice fallback:dispatcher 在 Minimax `status_code:2054` 时用默认 `Calm_Woman` 重试一次;若响应含 `voice_id_requested` 和 `fallback_reason: invalid_minimax_voice_id`,提示用户注册 voice 过期并用系统默认,可 `clone_voice` 恢复,不重试。
- Cookie-banner 音频 padding:Generic 且 `cookie_banner_present == true` 时,默认 MiniMax 路径在 `text:` 前 prepend `<#1.5#>`;若 Step4 用 `provider=elevenlabs`,跳过 marker 用 fallback audio-mix padding。
- Fallback:若 marker 被忽略,正常 `generate_speech`,再 `edit_audio_mix` 将结果 overlay 到 1.5s 静音 base 的 offset 1.5s;然后 `analyze_media(url=<padded_audio_url>)` 探测 padded duration 并 rebind `duration_seconds = result.duration_seconds`;以 `analyze_media` 为权威 duration probe,不依赖 `edit_audio_mix` payload。
- Step4.5 对 `audio_duration_seconds`(含 cookie lead-in pad)做音频长度验证和 beat-sheet rescale;所有 `beats[]` 修改都在这里;Step6/8 只读。
- Gate1:若 `audio_duration_seconds > 90`,abort 并用更紧词预算重写 beat sheet,因为 Kling avatar/image2video 超过 ~90s 会卡。
- Gate2:计算 `narration_duration = audio_duration_seconds - (1.5 if cookie_banner_present else 0.0)`;若 <30s,重试 Step4 一次并重算;仍 <30s 则 abort 调查(截断 MiniMax、静音、vo_text 未正确 join)。
- Gate3:`narration_duration = audio_duration_seconds - (1.5 if cookie_banner_present else 0.0)`;`scale = narration_duration / beats[-1].t_end`;若 `scale < 0.5` 或 `> 1.5`,abort 重写。
- Gate3 缩放:对每个 beat `t_start *= scale; t_end *= scale`;若 `cookie_banner_present`,对每个 beat `t_start += 1.5; t_end += 1.5`;最终 `beats[-1].t_end = audio_duration_seconds` 精确 clamp。
- Gate3 后输出一行日志:`Rescaled beats by scale=X.XX (audio=Y.YYs, narration_duration=Z.ZZs, cookie_pad=W.Ws)`。
- Advisory:scale 近 1.0 理想;>1.2 音频更慢视觉拉伸但同步;<0.85 音频更快视觉匆忙但同步;均通过 gate。
- Step5 Preview gate:仅当用户未传 `--preview` 且 `avatar_auto_preview_required == false` 时可跳过;`--skip-preview` 和 `--yes` 为 no-op。
- 若 `--preview` 或 `avatar_auto_preview_required == true`:`generate_speech` with `provider: minimax-tts`、可选 `voice_id`、text 为 Hi, I'm your presenter. Let's explore this repo together. → `preview_audio_url`。
- 然后 `generate_lipsync` with `provider: <resolved_lipsync_provider>`(默认 `pika`,honor `--lipsync-provider kling`)、`image: <avatar>`、`audio: preview_audio_url` → `preview_lipsync_url`(bare lipsync ~3s);preview 与 Step9 使用同 provider。
- 展示 verbatim 预览消息,包含 `preview_lipsync_url`、说明确认 avatar+voice 组合、全量渲染长耗时、回复 `yes` 继续或其他取消;匹配 `^(yes|go|proceed|confirm|y)$` 大小写不敏感;否则 STOP,不再 MCP 调用。
- Step6 将 beat sheet 转 `capture_website` `timed_actions`;每 beat 一个 `timed_action`,`bbox_selector = beat.zoom_target.selector`;`capture_website` 内部捕获 post-action bbox(600ms settle → smooth-scroll-to `top - 60 px` → 1300ms post-anim → measure)。
- navigate beats 发 `{type: navigate, at_s: <t_start>, url: <action.url>, bbox_selector: <zoom_target.selector>}`;scroll_to/hover beats 发 `{type: scroll, at_s: <t_start>, selector: <action.selector 或 zoom_target.selector>, bbox_selector: <zoom_target.selector>}`。
- 不要 prepend intro scroll-through,因为 lipsync 音频从 `t=0`,prepend 会导致音视频偏移。
- 调 `capture_website`:`url: <beat 0 action.url>`,`timed_actions: <N-element list>`,`duration_s: ceil(audio_duration_seconds)`。
- Generic-URL additions:传 `extra_css: <cookie-banner-hiding CSS payload>`;为 SPA/lazy 页 prepend `{type: wait, at_s: 0.0, ms: 2500}`,普通页 1500ms;若 `cookie_banner_present`,prepend `{type: click, at_s: 0.5, selector: <detected dismissal selector>}`;beats 已 +1.5s,音频已 pad,无需再移;无 cookie 仅 wait。
- 捕获 `video_url`、`recording_viewport`、`action_bboxes`;`action_bboxes[].idx` 是输入 `timed_actions` 位置;GitHub 模式 `idx` 1:1 beat,Generic 模式 `beat_idx = entry.idx - prepend_count`,prepend_count 1 或 2,跳过 `beat_idx < 0`;`selector` 字段报告 `bbox_selector`。
- Generic bbox hit-rate:计算 `bbox_total_count`、`bbox_found_count`、`bbox_hit_rate`,用 Step8b 过滤 degenerate;若 `<0.70`,设 `bbox_warning` 为指定用户可见句子并带至 Step12。
- Step7 `edit_browser_frame`:`video_url: <Step6 video_url>`,`url: (live_url if GitHub 且 survived Step2.5 else input_url, truncated to 65 chars)`,`tab_title: <30-char title>`;GitHub 用 `(meta.description or repo_name or 空)[:30]`;Generic 用页面 `<title>` 或 hostname truncated 30,防 None/empty;返回 `framed_url`(1280×800 Sonoma + chrome)。
- Step8 常量:`INTRO_BEATS = 2`(跳过 beat index 0 和 1)、`HOLD_GAP = 0.6`、`MIN_BEAT_DUR = 1.5`、`SCALE = 1.35`、`FALLBACK_SCALE = 1.25`、`FALLBACK_RAMP = 0.4`;`edit_browser_frame` 内偏移 `CONTENT_X=56`、`CONTENT_Y=108`、`CONTENT_W=1168`、`CONTENT_H=637`。
- Coord transform:`cx_framed = 56 + (bbox.x + bbox.w/2) * (1168 / recording_viewport.w)`;`cy_framed = 108 + (bbox.y + bbox.h/2) * (637 / recording_viewport.h)`。
- Step8a 对每个非 intro 且足够长 beat 预填 default-position keyframes:`DEFAULT_CX = 56 + 1168 // 2`;`DEFAULT_CY = 108 + 637 // 3`;从 index `INTRO_BEATS` 开始;若 `t_end - t_start < MIN_BEAT_DUR` skip;interior interval `[t_start + HOLD_GAP, t_end - HOLD_GAP]` 若 <1.0s skip;否则 `zoom_keyframes_by_beat[beat_idx] = {cx: DEFAULT_CX, cy: DEFAULT_CY, scale: FALLBACK_SCALE, ramp_s: FALLBACK_RAMP, t_start/t_end trimmed}`。
- Step8b 用 bbox override:GitHub `beat_idx = entry.idx`;Generic `beat_idx = entry.idx - prepend_count`;若 `beat_idx < INTRO_BEATS` skip;`entry.found` false skip;beat 不在 map skip;过滤 degenerate bbox:`bbox.y > recording_viewport.h` 或 `bbox.h > recording_viewport.h * 1.5` skip;计算 cx/cy 并 override `{cx: cx_framed, cy: cy_framed, scale: SCALE, ramp_s: min(0.5, (t_end - t_start) * 0.15)}`。
- Final list:按 `t_start` 排序 `zoom_keyframes`;若 `len(zoom_keyframes) > 0`,调 `edit_animate_zoom` with `video_url: framed_url, zoom_keyframes` → `zoomed_url`;否则用 `framed_url` 作为 `zoomed_url`。
- Step9 全量 lipsync:调 `generate_lipsync`,`provider: <resolved_lipsync_provider>` 默认 `pika`,honor `--lipsync-provider kling`;`image: <avatar>`;`audio: <Step4 audio_url>`;若 provider 为 `kling`,加 `mode: pro` 和 `prompt: talking head, face centered, mouth syncs to audio, minimal head movement, professional presenter`;pika 忽略这些。
- Provider tradeoffs:`pika` 默认 ~2-5 min,头部运动略多但自然;`kling` opt-in ~5-30 min,最小头部运动、face-centered、presenter-style,高价值渲染用。
- 若响应 `{task_id, status: queued}`,紧凑轮询 `task_status` 直到 terminal(`completed`/`failed`/`cancelled`);completed 捕获 `lipsync_url`;failed/cancelled 切另一 provider。
- Failover:`pika` 失败重试一次 `kling`;`kling` 超过 worker 1200s ceiling 时 fallback `pika`。
- Pika 默认原因:速度,典型 wall-clock 从 ~10-15min 降到 ~5-7min;质量足够;Kling polish 在 246px 圆内多数不可见。
- Face-coherence gate:捕获 `lipsync_url` 后 Step10 前,调 `extract_frame(video_url=<lipsync_url>, at_times=[1.0, audio_duration_seconds * 0.5, max(1.0, audio_duration_seconds - 1.0)])` 获 start/mid/end;batch 用 `frame_urls = extract_result.urls`,legacy `url` 作为 fallback;每个 frame_url 单独 `analyze_media(media=<frame_url>, query=<single_frame_gate_query>)`,不要传数组。
- 单帧 gate query 返回 JSON 含 `face_integrity_score`、`is_coherent_human_face`、`has_visible_mouth`、`is_abstract_melting_mask_or_non_human`、`observation`、`recommended_action`。
- 聚合:仅当最低 `face_integrity_score >= 75`、所有 `is_coherent_human_face == true`、所有 `has_visible_mouth == true`、所有 `is_abstract_melting_mask_or_non_human == false` 通过;保留 per-frame observations。
- 若第一 provider fail,换另一 provider 重试一次并重跑 gate;两者都 fail,abort 并返回 gate observations,不进入 Step10;第二 provider pass 用其 `lipsync_url`。
- Step10 PiP:`edit_pip` 参数 `main_video_url: <zoomed_url>`、`overlay_video_url: <lipsync_url>`、`shape: circle`、`size_px: 246`(240 inner + 3+3 stroke ring)、`stroke_width_px: 3`、`stroke_color: white`、`position_px: {x: 20, y: 476}`(`800 - 246 - 78` 为 dock clearance)。
- 传 `size_px` 不传 `size`;返回 `final_url`。
- Master-duration/audio-source contract:`edit_pip` 默认 `shortest=1`,composite 时长取 zoomed screen recording 与 lipsync video 较短者;Step6 `duration_s = ceil(audio_duration_seconds)` 确保屏幕长度与 lipsync 匹配;composite 时长由 lipsync 经 `shortest=1` 决定;音频来自 lipsync video 音轨;若 lipsync 短于屏幕(Kling 修剪尾部静音),屏幕在 lipsync 结束处截断,接受。
- Step11 Burn captions:从最终 joined `vo_text` 构建 `caption_script_text`,应用 `proper_noun_glossary` 规范拼写;不要依赖自动转录品牌/模型名。
- 选择 placement:默认 `position: bottom`;当 beat plan 或 captured page 显示重要 hero text/headline/value-prop/CTA/code 在下三分之一,用 `position: top`。
- 调 `add_captions(video_url=<final_url>, style=classic, caption_mode: manual, subtitle_text=<caption_script_text>, position=<caption_position>)`;捕获 `captioned_url`;仅当用户传 `--no-captions` 跳过;默认 captions on;`/pika:podcast` 不 burn captions。
- Step12:若 Step6 设了 `bbox_warning`,在最终 URL 前立即发出;然后输出 `captioned_url`(或跳过 Step11 则 `final_url`)一行:`Done: <url>`。
- Post-flight quality gate:声明成功前,对 `captioned_url` 或 `final_url` 调 `analyze_media` 要结构化 verdict JSON;检查 captions 存在除非 `--no-captions`、zoom target/bbox 对 narrated UI、无 blank frames/white flash、avatar PiP 不覆盖重要内容、presenter face coherent、`proper_noun_glossary` 拼写正确、captions 不遮挡 hero text/headline/value-prop/CTA/code。
- 根据 verdict:`clean` 正常发出;`degraded` 发 URL + `quality_warning`;`catastrophic` 不宣告完成,发 verdict + `re_roll_suggestion`。
- Failure modes:OAuth/401 第一次 MCP 调用 → 停止并让用户重新认证 Pika MCP connector,auth 成功前不重试付费步骤。
- `capture_website` blank frames/empty `action_bboxes`/blocked page → 用 WebFetch text fallback 事实,或请求粘贴源材料/更简单 URL。
- TTS/lipsync transient 5xx/429 → 按 hinted backoff 重试同一调用一次;再失败停止并给 provider error + last checkpoint。
- Caption/final QA unreadable proper nouns、occlusion、blank frames、incoherent avatar → 返回 `not publish-ready` + QA JSON + 具体 reroll suggestion;不要宣告成功。
- Load-bearing phrases:保持 `vanilla CSS that resolves via document.querySelector`、`GitHub URLs activate repo-aware mode`、`8-10 beats`/`65-80 seconds`/`165-200 words`、`all beats[] mutations happen here`、`extra_css` cookie-banner hiding payload。
- Engine choice:默认 Pika/parrot lipsync 以保持短迭代;仅用户显式 `--lipsync-provider kling` 或高价值渲染需更居中 presenter 且能容忍长耗时时用 Kling;screen capture、browser frame、zoom、PiP、captions 仍为确定性 edit/composite。
- Runtime expectations:典型 5-10 min Pika 或 10-30+ min Kling;URL read+pre-flight 10-60s;TTS+audio rescale 30-90s;screen recording 60-180s;browser frame+zooms 1-3 min;lipsync 2-5 min Pika / 5-30 min Kling;PiP+captions 1-3 min(`--no-captions` 则跳过)。
- Known gaps 应对:Kling avatar mode/prompt 已可用,用 `--lipsync-provider kling` 加 `mode: pro` 和 prompt;无 caller-controlled white-frame trim,用 `wait` action 缓解;无 `networkidle` wait,SPA blob 页可能 bbox 未挂载;无 per-step output-size verification gates;`text_content` bbox 未实现,优先 CSS selectors;beat-sheet wording 非确定性,视觉 kind 是契约;Generic-URL 大牌企业站点可能 bot 检测、混淆类名、滚动动画不触发、懒加载图未解析,优先简单营销页并传 `--focus`,必要时服务端 PR;cookie-banner click 单次,`extra_css` 是主要防御。
适用边界 · 注意事项
- 需要 Pika MCP connector、付费 credits、MiniMax/Kling/Pika lipsync 等服务;无 OAuth/账号或无法通过 cost gate 时不适用。
- 目标站点有强 bot 检测、captcha、登录门禁、Cloudflare challenge,或大牌企业站点 headless 渲染失败、滚动动画/懒加载导致 bbox 缺失时不适用或需换更简单页面。
- 需要像素级可复现、确定性的 vo_text/zoom 位置,或音频超过 90 秒/Kling 长耗时不可接受时,不适合直接套用此流程。