<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Remotion on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/remotion/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Mon, 23 Feb 2026 12:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/remotion/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>口播视频自动剪辑：Whisper 词级时间轴 &#43; LLM 视觉规划</title>
      <link>https://ftmao.com/blog/posts/usewhispher/</link>
      <pubDate>Mon, 23 Feb 2026 12:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/posts/usewhispher/</guid>
      <description>&lt;h1 id=&#34;口播视频自动剪辑whisper-词级时间轴--llm-视觉规划&#34;&gt;口播视频自动剪辑：Whisper 词级时间轴 + LLM 视觉规划&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;我开发的 GeekCast Engine 是一个面向口播类视频的 AI 自动剪辑平台。用户上传一段口播视频后，系统自动完成转写、粗剪、视觉规划和成片渲染。这篇文章会重点拆解两个核心模块：&lt;strong&gt;Whisper 词级时间轴处理&lt;/strong&gt; 和 &lt;strong&gt;LLM 视觉元素规划&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一口播剪辑的核心痛点&#34;&gt;一、口播剪辑的核心痛点&lt;/h2&gt;
&lt;p&gt;口播视频通常是一个人对着镜头讲话，形式单一，但剪辑过程却很繁琐：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;气口和语气词太多&lt;/strong&gt;：「嗯」「啊」「这个」「那个」需要逐个删掉&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;节奏单调&lt;/strong&gt;：长时间只有说话人画面，观众容易疲劳&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;信息密度不均&lt;/strong&gt;：有些段落需要配合 B-roll、标题卡、代码块来强化表达&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;长视频处理困难&lt;/strong&gt;：10 分钟以上的口播，人工剪辑耗时往往在数小时&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我们的目标不是完全替代剪辑师，而是把&lt;strong&gt;重复、机械、规则明确&lt;/strong&gt;的工作自动化，让人专注于创意和审校。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二整体技术架构&#34;&gt;二、整体技术架构&lt;/h2&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[&amp;#34;口播视频上传&amp;#34;] --&amp;gt; B[&amp;#34;Whisper 词级转写&amp;#34;]
    B --&amp;gt; C[&amp;#34;LLM 语义分析 + 视觉规划&amp;#34;]
    C --&amp;gt; D[&amp;#34;自动粗剪（删气口/语气词/冗余片段）&amp;#34;]
    D --&amp;gt; E[&amp;#34;Remotion 组件化渲染&amp;#34;]
    E --&amp;gt; F[&amp;#34;FFmpeg 后处理输出成片&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;整个流程里，最关键的两个环节是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;时间轴精度&lt;/strong&gt;：决定了粗剪是否精准&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;视觉规划质量&lt;/strong&gt;：决定了成片是否好看&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三whisper-词级时间轴&#34;&gt;三、Whisper 词级时间轴&lt;/h2&gt;
&lt;h3 id=&#34;31-为什么选择-whisper&#34;&gt;3.1 为什么选择 Whisper&lt;/h3&gt;
&lt;p&gt;OpenAI Whisper 是目前开源语音识别模型中最成熟的选择之一，优势很明显：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;支持 99 种语言，中文识别效果不错&lt;/li&gt;
&lt;li&gt;提供 &lt;code&gt;word-level timestamps&lt;/code&gt;（词级时间戳），这是自动剪辑的基础&lt;/li&gt;
&lt;li&gt;模型大小可选，从小到大有 tiny/base/small/medium/large&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;32-词级时间戳的获取&#34;&gt;3.2 词级时间戳的获取&lt;/h3&gt;
&lt;p&gt;Whisper 本身不直接输出词级时间戳，需要借助 &lt;code&gt;whisper-timestamped&lt;/code&gt; 或 &lt;code&gt;faster-whisper&lt;/code&gt; 等工具。我们用 &lt;code&gt;faster-whisper&lt;/code&gt;，因为它：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;推理速度更快&lt;/li&gt;
&lt;li&gt;支持 VAD（语音活动检测），减少静音误判&lt;/li&gt;
&lt;li&gt;对长音频更稳定&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; faster_whisper &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; WhisperModel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;model &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; WhisperModel(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;small&amp;#34;&lt;/span&gt;, device&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cuda&amp;#34;&lt;/span&gt;, compute_type&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;float16&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;segments, info &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; model&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;transcribe(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;input.mp3&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    word_timestamps&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vad_filter&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    language&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;zh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;words &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; segment &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; segments:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; word &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; segment&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;words:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        words&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;: word&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;word,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;: word&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;start,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;: word&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;end,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;probability&amp;#34;&lt;/span&gt;: word&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;probability
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        })&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;33-词级数据结构&#34;&gt;3.3 词级数据结构&lt;/h3&gt;
&lt;p&gt;转写完成后，每个词对应一个时间片段：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;大家好&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.98&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;probability&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.95&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;多个词可以聚合成句子、段落，形成完整的时间轴树：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Paragraph
  ├── Sentence 1
  │     ├── Word 1
  │     ├── Word 2
  │     └── Word 3
  └── Sentence 2
        ├── Word 4
        └── Word 5&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;34-气口和语气词删除&#34;&gt;3.4 气口和语气词删除&lt;/h3&gt;
&lt;p&gt;基于词级时间轴，我们可以做很多精细化编辑：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 语气词列表&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FILLER_WORDS &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;嗯&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;啊&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;这个&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;那个&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;就是&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;然后&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;对吧&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;remove_fillers&lt;/span&gt;(words, filler_words&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;FILLER_WORDS):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&amp;#34;删除单个语气词，保留相邻词的时间连续性&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; w &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; words:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; w[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;strip() &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; filler_words:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        result&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(w)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;remove_long_pauses&lt;/span&gt;(words, threshold&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0.8&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&amp;#34;删除过长的停顿片段&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i, w &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; enumerate(words):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            gap &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; w[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; words[i&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; gap &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; threshold:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# 也可以只压缩，不完全删除&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        result&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(w)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; result&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;35-时间轴漂移问题&#34;&gt;3.5 时间轴漂移问题&lt;/h3&gt;
&lt;p&gt;实际使用中发现，Whisper 的词级时间戳在语速快、口音重、背景音乐干扰时会出现漂移。我们做了几个处理：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;置信度过滤&lt;/strong&gt;：识别概率低于 0.7 的词标记为待审校&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;句子级对齐&lt;/strong&gt;：用 VAD 检测到的语音段和转写句子做二次对齐&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;人工修正入口&lt;/strong&gt;：前端提供波形图 + 时间轴，允许用户微调&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四llm-视觉规划&#34;&gt;四、LLM 视觉规划&lt;/h2&gt;
&lt;h3 id=&#34;41-视觉元素类型&#34;&gt;4.1 视觉元素类型&lt;/h3&gt;
&lt;p&gt;我们定义了口播视频中常用的几类视觉元素：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;元素类型&lt;/th&gt;
					&lt;th&gt;作用&lt;/th&gt;
					&lt;th&gt;示例&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;标题卡&lt;/td&gt;
					&lt;td&gt;章节切换、强调重点&lt;/td&gt;
					&lt;td&gt;大标题 + 副标题&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;B-roll&lt;/td&gt;
					&lt;td&gt;缓解视觉疲劳，补充画面&lt;/td&gt;
					&lt;td&gt;相关图片/视频片段&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;引用卡&lt;/td&gt;
					&lt;td&gt;引用名人名言、数据&lt;/td&gt;
					&lt;td&gt;金句 + 出处&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;代码块&lt;/td&gt;
					&lt;td&gt;技术类口播展示代码&lt;/td&gt;
					&lt;td&gt;高亮代码片段&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;列表卡&lt;/td&gt;
					&lt;td&gt;展示多个要点&lt;/td&gt;
					&lt;td&gt;1/2/3 列表&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;42-llm-规划任务&#34;&gt;4.2 LLM 规划任务&lt;/h3&gt;
&lt;p&gt;输入是一段按句子切分好的口播文本，输出是每个句子应该配什么视觉元素。Prompt 设计如下：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;你是一名专业的口播视频剪辑师。请根据以下口播文案，为每个句子规划合适的视觉元素。

可用视觉元素：
- TitleCard: 标题卡，用于章节开头或强调核心观点
- BRoll: B-roll 画面，用于补充说明内容
- QuoteCard: 引用卡，用于展示名言、数据
- CodeBlock: 代码块，用于展示代码
- ListCard: 列表卡，用于展示多个要点
- TalkingHead: 保持说话人画面，不添加额外元素

口播文案：
{script}

请输出 JSON 数组，每个元素包含：
- sentence_index: 句子序号
- element_type: 视觉元素类型
- reason: 选择理由
- suggested_content: 建议展示的内容（如 B-roll 的画面描述、标题文字等）&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;43-输出结构化&#34;&gt;4.3 输出结构化&lt;/h3&gt;
&lt;p&gt;LLM 返回的结果类似：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;sentence_index&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;element_type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;TitleCard&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;reason&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;开场需要点题&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;suggested_content&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AI 自动剪辑实战&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;sentence_index&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;element_type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;BRoll&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;reason&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;解释&amp;#39;时间轴&amp;#39;概念时需要补充画面&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;suggested_content&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;视频编辑软件中的时间轴界面&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;sentence_index&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;element_type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CodeBlock&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;reason&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;展示 Whisper 调用代码&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;suggested_content&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;faster_whisper 示例代码&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;44-与素材库联动&#34;&gt;4.4 与素材库联动&lt;/h3&gt;
&lt;p&gt;视觉规划中的 &lt;code&gt;suggested_content&lt;/code&gt; 会作为查询条件，调用我们在第二篇文章中讲的 RAG 素材库，检索匹配的 B-roll、图片或文案片段。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;plan_and_retrieve&lt;/span&gt;(script: str):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# 1. LLM 做视觉规划&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    plan &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; llm&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;generate_visual_plan(script)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# 2. 对每个 B-roll 规划项检索素材&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; item &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; plan:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; item[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;element_type&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;BRoll&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            item[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;materials&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; rag_retrieve(item[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;suggested_content&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; plan&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;五长视频-token-限制处理&#34;&gt;五、长视频 Token 限制处理&lt;/h2&gt;
&lt;p&gt;口播视频动辄 10 分钟以上，对应的文案可能超过 3000 字，直接塞给 LLM 做视觉规划会触发 Token 限制，而且单次规划效果也不好。&lt;/p&gt;
&lt;p&gt;我们的解决方案是：&lt;strong&gt;分段生成 + 本地组装&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;51-分段策略&#34;&gt;5.1 分段策略&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;按段落切分：每段约 800-1200 字&lt;/li&gt;
&lt;li&gt;保留上下文：每段开头会附带上一段的结尾摘要&lt;/li&gt;
&lt;li&gt;独立规划：每段分别调用 LLM 做视觉规划&lt;/li&gt;
&lt;li&gt;全局对齐：最后统一调整时间轴、样式和转场&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;split_script&lt;/span&gt;(script: str, max_chars: int &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&amp;#34;按段落切分文案，尽量保持段落完整性&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    paragraphs &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; script&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;split(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chunks &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    current &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; p &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; paragraphs:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; len(current) &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; len(p) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; max_chars &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; current:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            chunks&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(current)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            current &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; p
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            current &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; p
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; current:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        chunks&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(current)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; chunks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;52-本地组装&#34;&gt;5.2 本地组装&lt;/h3&gt;
&lt;p&gt;分段规划完成后，需要在本地合并：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;统一句子索引&lt;/li&gt;
&lt;li&gt;统一视觉风格（字体、配色、动画）&lt;/li&gt;
&lt;li&gt;处理段与段之间的转场&lt;/li&gt;
&lt;li&gt;生成最终的 Remotion 渲染数据&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六remotion-组件化渲染&#34;&gt;六、Remotion 组件化渲染&lt;/h2&gt;
&lt;h3 id=&#34;61-为什么用-remotion&#34;&gt;6.1 为什么用 Remotion&lt;/h3&gt;
&lt;p&gt;Remotion 让我们可以用 React 组件来描述视频画面，非常契合「视觉元素 = 组件」的思路。&lt;/p&gt;
&lt;p&gt;每个视觉元素对应一个 React 组件：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-tsx&#34; data-lang=&#34;tsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 标题卡组件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;TitleCard&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;React.FC&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;{ &lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;subtitle&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; }&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ({ &lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;subtitle&lt;/span&gt; }) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;AbsoluteFill&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;backgroundColor&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#111&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;justifyContent&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;center&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;alignItems&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;center&amp;#39;&lt;/span&gt; }}&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;h1&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;color&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#fff&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;fontSize&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;80&lt;/span&gt; }}&amp;gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;}&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;h1&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;color&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#aaa&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;fontSize&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;36&lt;/span&gt; }}&amp;gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;subtitle&lt;/span&gt;}&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;AbsoluteFill&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;62-渲染流程&#34;&gt;6.2 渲染流程&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[&amp;#34;视觉规划结果&amp;#34;] --&amp;gt; B[&amp;#34;生成 Remotion composition（每个视觉元素对应一个组件实例）&amp;#34;]
    B --&amp;gt; C[&amp;#34;Remotion 渲染为视频文件&amp;#34;]
    C --&amp;gt; D[&amp;#34;FFmpeg 后处理：合成音频、加字幕、转码、多分辨率输出&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;63-多分辨率输出&#34;&gt;6.3 多分辨率输出&lt;/h3&gt;
&lt;p&gt;平台需要同时支持横屏（16:9）和竖屏（9:16），我们在 Remotion 组件内部做响应式布局：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-tsx&#34; data-lang=&#34;tsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;width&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;height&lt;/span&gt; } &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;useVideoConfig&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;isVertical&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;height&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;width&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;七踩过的坑&#34;&gt;七、踩过的坑&lt;/h2&gt;
&lt;h3 id=&#34;71-whisper-模型选择纠结&#34;&gt;7.1 Whisper 模型选择纠结&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tiny&lt;/code&gt; 速度最快但准确率太低&lt;/li&gt;
&lt;li&gt;&lt;code&gt;large&lt;/code&gt; 准确率最高但显存和速度压力大&lt;/li&gt;
&lt;li&gt;最终我们选 &lt;code&gt;small&lt;/code&gt; 做默认模型，&lt;code&gt;large&lt;/code&gt; 做可选质量模式&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;72-llm-规划风格不一致&#34;&gt;7.2 LLM 规划风格不一致&lt;/h3&gt;
&lt;p&gt;同一个文案多次调用 LLM，返回的视觉规划可能风格差异很大。我们做了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prompt 里加入平台风格示例&lt;/li&gt;
&lt;li&gt;视觉元素类型和样式模板固定&lt;/li&gt;
&lt;li&gt;对返回结果做规则校验和兜底&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;73-代码块渲染需要特殊处理&#34;&gt;7.3 代码块渲染需要特殊处理&lt;/h3&gt;
&lt;p&gt;代码块里的长行、特殊字符、换行等都会影响 Remotion 渲染。我们专门封装了一个 &lt;code&gt;CodeBlock&lt;/code&gt; 组件，处理：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自动换行和字体缩放&lt;/li&gt;
&lt;li&gt;语法高亮&lt;/li&gt;
&lt;li&gt;行号显示&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八效果与反思&#34;&gt;八、效果与反思&lt;/h2&gt;
&lt;p&gt;目前 GeekCast Engine 能在一分钟左右完成 5-10 分钟口播视频的自动粗剪和视觉规划，最终成片需要人工简单审校即可发布。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;量化效果（待补充真实数据）&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;10 分钟口播视频，人工剪辑平均 X 小时，自动剪辑约 X 分钟&lt;/li&gt;
&lt;li&gt;气口和语气词删除覆盖率约 X%&lt;/li&gt;
&lt;li&gt;LLM 视觉规划采纳率约 X%&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;反思&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自动剪辑还不能做到 100% 无人工，但已经能替代 60%-70% 的重复劳动&lt;/li&gt;
&lt;li&gt;视觉规划比粗剪更难，未来需要结合用户反馈做迭代优化&lt;/li&gt;
&lt;li&gt;长视频场景下，分段策略和上下文保留是关键&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九总结&#34;&gt;九、总结&lt;/h2&gt;
&lt;p&gt;口播视频自动剪辑是把 ASR、LLM、视频渲染三项技术串联起来的典型 AI 工程场景。几个关键经验：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;词级时间轴是粗剪的基础&lt;/strong&gt;，Whisper + faster-whisper 是性价比较高的方案&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LLM 视觉规划要把输出结构固定&lt;/strong&gt;，Prompt 设计决定可控性&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;长视频必须分段处理&lt;/strong&gt;，本地组装时注意风格和转场一致性&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remotion 让视频渲染工程化&lt;/strong&gt;，组件化思路适合多变的视觉需求&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;如果你也在做 AI 视频生成或自动剪辑相关的项目，欢迎交流 Whisper 调优和 LLM 规划的经验。&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
