<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>O&#39;s World</title>
  
  <subtitle>Mr. O 的分享小站，分享有趣的事情</subtitle>
  <link href="https://ooo.run/atom.xml" rel="self"/>
  
  <link href="https://ooo.run/"/>
  <updated>2026-10-22T16:32:14.833Z</updated>
  <id>https://ooo.run/</id>
  
  <author>
    <name>Mr. O</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Claude Duet、Grok Bot、ChatGPT dots 与 Meta Muse 全面对比：功能、价格与订阅权益</title>
    <link href="https://ooo.run/post/claude-duet-vs-grok-bot-vs-chatgpt-dots-vs-meta-muse.html"/>
    <id>https://ooo.run/post/claude-duet-vs-grok-bot-vs-chatgpt-dots-vs-meta-muse.html</id>
    <published>2026-10-22T16:00:04.000Z</published>
    <updated>2026-10-22T16:32:14.833Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>更新日期：2026 年 10 月 23 日<br>对比产品：Claude Duet、Grok Bot、ChatGPT dots、Meta Muse  </p></blockquote><p>随着 AI 助手从被动问答转向主动执行任务，Anthropic、xAI、OpenAI 和 Meta 相继推出了具备长期记忆、后台工作和应用操作能力的个人智能体。</p><p>它们不再只是回答问题的聊天机器人，<strong>而是能够接收长期目标、持续检查任务进度</strong>，并在必要时主动联系用户的 AI 助手。</p><p>不过，四款产品在定价、地区开放范围、自动化能力和订阅权益方面存在明显差异。</p><p>本文将从以下维度进行横向对比：</p><ul><li>订阅价格与最低使用门槛</li><li>地区限制与开放资格</li><li>后台任务、自动化和记忆能力</li><li>浏览器、电脑与本地文件操作</li><li>编程、应用连接器与多智能体协作</li><li>各家公司完整的订阅套餐</li><li>使用额度和额外计费规则</li></ul><p><img src="https://img.nep.me/ooo/ds-ai-agents-2026.webp" alt="ds-ai-agents-2026.png"></p><hr><h2 id="一、价格与使用门槛"><a href="#一、价格与使用门槛" class="headerlink" title="一、价格与使用门槛"></a>一、价格与使用门槛</h2><p>首先来看最直接的问题：使用这些 AI 助手需要多少钱？</p><table><thead><tr><th>产品</th><th>最低订阅门槛</th><th>免费或试用</th><th>开放范围</th></tr></thead><tbody><tr><td>Claude Duet</td><td>Claude Pro：**$20&#x2F;月**</td><td>暂无 Free 常规使用权限</td><td><strong>仅美国</strong>，Pro &#x2F; Max 用户还需要候补邀请</td></tr><tr><td>Grok Bot</td><td>The X Subscription Premium：**$30&#x2F;月**</td><td>有限额试用及 7 天使用窗口</td><td>宣布全球推出</td></tr><tr><td>ChatGPT dots</td><td>Pro 100：**$100&#x2F;月**</td><td>Free、Go、Plus 均不包含</td><td>符合资格的地区分批开放</td></tr><tr><td>Meta Muse</td><td>免费起步；Power $20&#x2F;月</td><td>Free 已包含智能体能力</td><td>有限测试，美国、加拿大等市场优先</td></tr></tbody></table><p><strong>注意：订阅门槛不等于购买后立即获得使用资格。</strong></p><p>Claude Duet 和 ChatGPT dots 都采用分批开放方式，付费套餐只代表符合申请或使用条件。</p><h3 id="1-Claude-Duet"><a href="#1-Claude-Duet" class="headerlink" title="1. Claude Duet"></a>1. Claude Duet</h3><p>Claude Duet 是 Anthropic 推出的主动式个人 AI 助手。</p><p>最低使用门槛是 Claude Pro：</p><ul><li>月付：$20</li><li>年付：$200</li><li>年付折合：约 $16.67&#x2F;月</li></ul><p>Duet 也向 Claude Max 用户开放，但目前有两个重要限制：</p><ol><li>仅面向美国用户。</li><li>需要加入候补名单并获得邀请。</li></ol><p>因此，即使已经支付 Claude Pro 的订阅费用，也不意味着立即能够使用 Duet。</p><p>官方资料：</p><ul><li><a href="https://claude.com/pricing">Claude Pricing</a></li><li><a href="https://support.claude.com/en/articles/17631495-getting-started-with-claude-duet">Getting Started with Claude Duet</a></li></ul><h3 id="2-Grok-Bot"><a href="#2-Grok-Bot" class="headerlink" title="2. Grok Bot"></a>2. Grok Bot</h3><p>Grok Bot 是 xAI 旗下的智能体产品。</p><p>2026 年 10 月，xAI 推出新的 The X Subscription，将 Grok、Grok Bot、Cursor 和 X 的部分权益整合到统一的订阅体系中。</p><p>最低完整使用门槛为 Premium：</p><ul><li>月付：$30</li><li>年付：$300</li><li>年付折合：$25&#x2F;月</li></ul><p>需要区分：</p><p>这里的 Premium 是新版 The X Subscription Premium，而不是旧版 X Premium。</p><p>它也并非单独的 Grok Bot 套餐。</p><p>官方资料：</p><ul><li><a href="https://docs.x.ai/x-subscription/pricing">The X Subscription Pricing</a></li><li><a href="https://cursor.com/help/grok-bot/plans">Grok Bot Plans</a></li></ul><h3 id="3-ChatGPT-dots"><a href="#3-ChatGPT-dots" class="headerlink" title="3. ChatGPT dots"></a>3. ChatGPT dots</h3><p>ChatGPT dots 是 OpenAI 推出的持续性个人智能体。</p><p>目前最低使用门槛为：</p><ul><li>ChatGPT Pro 100：$100&#x2F;月</li></ul><p>更高的 Pro 200、Pro 500 也包含 dots。</p><p>个人版要求用户年满 18 岁，目前不向欧洲经济区、英国和瑞士开放。</p><p>官方资料：</p><ul><li><a href="https://help.openai.com/en/articles/9793128-about-chatgpt-pro-tiers">About ChatGPT Pro Tiers</a></li><li><a href="https://learn.chatgpt.com/docs/dots">ChatGPT dots Documentation</a></li></ul><h3 id="4-Meta-Muse"><a href="#4-Meta-Muse" class="headerlink" title="4. Meta Muse"></a>4. Meta Muse</h3><p>Meta Muse 与其他三款产品最大的区别在于：</p><p><strong>免费套餐已经包含基础智能体能力。</strong></p><p>目前公布的订阅档位包括：</p><table><thead><tr><th>套餐</th><th align="right">月费</th></tr></thead><tbody><tr><td>Free</td><td align="right">$0</td></tr><tr><td>Power</td><td align="right">$20</td></tr><tr><td>Maximum</td><td align="right">$100</td></tr></tbody></table><p>但 Muse 仍处于有限测试和逐步推出阶段。官方已提及美国、加拿大等市场，其他地区尚未确认正式开放日期。</p><p>官方资料：</p><ul><li><a href="https://muse.ai/business">Muse</a></li><li><a href="https://www.meta.com/help/subscriptions/1021145227643680/">Meta Muse Subscription</a></li></ul><hr><h2 id="二、核心功能横向对比"><a href="#二、核心功能横向对比" class="headerlink" title="二、核心功能横向对比"></a>二、核心功能横向对比</h2><p>四款产品都试图实现一个共同目标：</p><p><strong>让 AI 不再只是等待用户提问，而是成为能够长期承担任务、主动推进工作的助手。</strong></p><p>但它们的产品设计并不完全相同。</p><table><thead><tr><th>功能</th><th>Claude Duet</th><th>Grok Bot</th><th>ChatGPT dots</th><th>Meta Muse</th></tr></thead><tbody><tr><td>产品定位</td><td>专业工作与商务助理</td><td>多智能体 AI 同事</td><td>持续性个人工作代理</td><td>个人生活与目标管理助理</td></tr><tr><td>长期任务</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>主动通知</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>定时执行</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>事件触发</td><td>支持部分场景</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>长期记忆</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>云端电脑</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>云端浏览器</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>查看或接管云浏览器</td><td>暂不支持</td><td>支持</td><td>支持</td><td>依当前入口与权限</td></tr><tr><td>本地电脑操作</td><td>不是当前主要能力</td><td>有桌面客户端</td><td>支持连接本地电脑</td><td>Mac 已有本地操作能力</td></tr><tr><td>多 Agent 协作</td><td>以任务和频道组织</td><td>多个具名 Bot 协作</td><td>委派 Work &#x2F; Codex 任务</td><td>多任务与 Goals</td></tr><tr><td>编程能力</td><td>支持</td><td>支持，并结合 Cursor</td><td>支持 Codex</td><td>支持</td></tr><tr><td>语音交互</td><td>支持语音消息</td><td>支持</td><td>支持相应 ChatGPT 语音能力</td><td>支持</td></tr><tr><td>主动拨打电话</td><td>不支持</td><td>未确认通用能力</td><td>不是当前通用能力</td><td>测试中</td></tr><tr><td>移动端</td><td>iOS &#x2F; Android</td><td>iOS &#x2F; Android</td><td>iOS &#x2F; Android</td><td>移动端和其他入口</td></tr><tr><td>桌面端</td><td>网页等入口</td><td>macOS &#x2F; Windows &#x2F; Linux</td><td>桌面应用</td><td>Mac 应用</td></tr></tbody></table><p>注：表中的「支持」表示官方公布过对应的产品能力，不代表所有地区、所有账户及全部套餐都已获得该功能。</p><hr><h2 id="三、Claude-Duet：主动管理工作，而不是等待命令"><a href="#三、Claude-Duet：主动管理工作，而不是等待命令" class="headerlink" title="三、Claude Duet：主动管理工作，而不是等待命令"></a>三、Claude Duet：主动管理工作，而不是等待命令</h2><p>Claude Duet 更接近一个专门面向知识工作者和小企业主的 AI 助理。</p><p>它最大的特点不是拥有浏览器，而是能够主动发现值得处理的事情。</p><h3 id="主要功能"><a href="#主要功能" class="headerlink" title="主要功能"></a>主要功能</h3><p><strong>1. 主动生成每日简报</strong></p><p>Duet 可以根据用户已经连接的日历、邮件和业务工具，整理当天的重要事项。</p><p>例如：</p><ul><li>今天有哪些会议？</li><li>哪些客户需要回复？</li><li>是否有日程冲突？</li><li>哪些工作需要提前准备？</li><li>有哪些业务指标出现变化？</li></ul><p>相比普通的聊天机器人，Duet 的目标是减少用户每天重新描述工作背景的时间。</p><p><strong>2. 周期性检查任务</strong></p><p>Duet 可以在后台持续检查已经连接的账户和任务。</p><p>当发现需要用户处理的事项时，可以主动提醒。</p><p><strong>3. 处理专业工作</strong></p><p>Duet 可以参与：</p><ul><li>文档与报告制作</li><li>财务模型</li><li>幻灯片</li><li>仪表盘</li><li>商业数据分析</li><li>客户跟进</li><li>发票与经营事务</li><li>简单应用原型开发</li></ul><p><strong>4. 继承 Claude 生态</strong></p><p>Duet 可以使用 Claude 已经建立的部分记忆、Skills 和连接器。</p><p>对于长期使用 Claude 的用户，这能够减少重复配置。</p><h3 id="当前限制"><a href="#当前限制" class="headerlink" title="当前限制"></a>当前限制</h3><p>Claude 官方目前明确指出：</p><ul><li>Duet 固定使用 Claude Opus 5.5。</li><li>用户不能手动切换 Duet 的模型。</li><li>当前无法查看或接管 Duet 的云浏览器。</li><li>Microsoft 365 暂未在 Duet 中提供完整支持。</li><li>部分 Slack 功能存在限制。</li><li>支持录制语音消息，但不会代替用户拨打电话或发送短信。</li></ul><p>这些限制尤其值得注意。</p><p>例如，Claude Pro 自身可能包含 Microsoft 365 相关能力，但不能据此推断 Duet 已经拥有相同的集成能力。</p><h3 id="适合谁？"><a href="#适合谁？" class="headerlink" title="适合谁？"></a>适合谁？</h3><p>Claude Duet 更适合：</p><ul><li>企业经营者</li><li>自由职业者</li><li>日常处理大量邮件和日历的用户</li><li>已经长期使用 Claude 的知识工作者</li></ul><p>它的产品思路偏向于：</p><p><strong>让 AI 主动告诉你今天应该处理什么。</strong></p><p>官方介绍：</p><p><a href="https://claude.com/resources/articles/claude-duet">Introducing Claude Duet</a></p><hr><h2 id="四、Grok-Bot：把-AI-组织成一个团队"><a href="#四、Grok-Bot：把-AI-组织成一个团队" class="headerlink" title="四、Grok Bot：把 AI 组织成一个团队"></a>四、Grok Bot：把 AI 组织成一个团队</h2><p>Grok Bot 的设计更接近一个由多个 AI 同事构成的团队。</p><p>与单一助手不同，Grok Bot 强调多个具名 Bot 之间的分工与协作。</p><h3 id="主要功能-1"><a href="#主要功能-1" class="headerlink" title="主要功能"></a>主要功能</h3><p><strong>1. 创建多个 AI Bot</strong></p><p>用户可以创建不同职责的 Bot。</p><p>例如：</p><ul><li>Research Bot：负责信息收集</li><li>Coding Bot：负责编程和修复问题</li><li>Content Bot：负责文章和内容生产</li><li>Operations Bot：负责监控和日常运营</li></ul><p>不同 Bot 可以拥有各自的角色和工作上下文。</p><p><strong>2. 多 Bot 协作</strong></p><p>Grok Bot 支持群聊和任务交接。</p><p>例如：</p><p>Research Bot 完成资料收集后，可以把结果交给 Content Bot，由后者撰写文章。</p><p>这种产品设计更接近组织中的工作分工。</p><p><strong>3. 云端电脑</strong></p><p>Grok Bot 提供持久的云电脑环境，包括：</p><ul><li>浏览器</li><li>文件系统</li><li>命令行</li><li>工作文件</li><li>登录状态</li></ul><p>用户可以观看并接管云电脑。</p><p>但需要注意：</p><p><strong>同一账户的多个 Bot 共用云电脑资源、文件、浏览器登录状态和终端凭据。</strong></p><p>它们不是完全隔离的独立虚拟机。</p><p><strong>4. Skills、Routines 与自动化</strong></p><p>Grok Bot 可以把重复工作保存为 Skill，再通过 Routine 定时执行。</p><p>目前官方文档列出的限制包括：</p><ul><li>每个 Bot 最多 50 个 Routine</li><li>运行间隔至少 5 分钟</li></ul><p>此外，Grok Bot 还有通过操作示范学习任务的能力，但部分功能仍处于分批开放阶段。</p><h3 id="Grok-Bot-不只使用-Grok-模型"><a href="#Grok-Bot-不只使用-Grok-模型" class="headerlink" title="Grok Bot 不只使用 Grok 模型"></a>Grok Bot 不只使用 Grok 模型</h3><p>这是一个比较容易被忽略的细节。</p><p>Grok Bot 可以根据任务自动选择不同模型，包括 xAI 自家模型和第三方模型。</p><p>官方文档甚至提到了 Opus 5.5 路由。</p><p>不过：</p><ul><li>用户不能指定具体模型。</li><li>用户也不能查看每个任务实际使用的模型。</li><li>自动模型路由不等于 Cursor 内第三方模型的免费使用权。</li></ul><h3 id="适合谁？-1"><a href="#适合谁？-1" class="headerlink" title="适合谁？"></a>适合谁？</h3><p>Grok Bot 特别适合：</p><ul><li>希望创建多个专业 AI 助手的用户</li><li>有大量重复任务的开发者</li><li>同时使用 Grok、Cursor 和 X 的用户</li><li>希望通过 Skills 和 Routines 构建自动化流程的用户</li></ul><p>它的产品思路可以概括为：</p><p><strong>不是雇佣一个 AI 助理，而是组织一支 AI 团队。</strong></p><p>官方文档：</p><ul><li><a href="https://docs.x.ai/grok-bot/overview">Grok Bot Overview</a></li><li><a href="https://docs.x.ai/grok-bot/skills-routines-and-automations">Skills, Routines and Automations</a></li><li><a href="https://docs.x.ai/grok-bot/computer-and-apps">Computer and Apps</a></li></ul><hr><h2 id="五、ChatGPT-dots：让一个-AI-长期负责你的工作"><a href="#五、ChatGPT-dots：让一个-AI-长期负责你的工作" class="headerlink" title="五、ChatGPT dots：让一个 AI 长期负责你的工作"></a>五、ChatGPT dots：让一个 AI 长期负责你的工作</h2><p>ChatGPT dots 的核心理念是持续性。</p><p>用户不再需要为同一个项目每天创建新对话、重新交代上下文，而是可以将长期任务交给 dots。</p><p>它会持续推进任务，并在适当的时候主动跟进。</p><h3 id="主要功能-2"><a href="#主要功能-2" class="headerlink" title="主要功能"></a>主要功能</h3><p><strong>1. 持续跟踪长期目标</strong></p><p>例如：</p><ul><li>持续研究特定技术领域</li><li>关注软件项目的开发进度</li><li>跟进工作中的待办事项</li><li>分析项目变化</li><li>定期准备工作简报</li></ul><p>dots 可以将一个长期目标拆成多个任务。</p><p><strong>2. 委派 Work 和 Codex</strong></p><p>这是 dots 区别于普通聊天助手的重要能力之一。</p><p>当工作需要浏览器操作、文件处理或代码执行时，dots 可以委派给相应的工作环境。</p><p>对于编程任务，它还可以与 Codex 配合。</p><p><strong>3. 云电脑和本地电脑</strong></p><p>dots 可以使用云端电脑与浏览器。</p><p>用户也可以连接自己的电脑，让它访问本地工作环境。</p><p>需要注意：</p><p>云端任务可以在本地设备关机后继续，但依赖本地电脑的任务仍然需要电脑在线，并保持相应应用运行。</p><p><strong>4. 长期记忆</strong></p><p>dots 可以结合：</p><ul><li>ChatGPT 已有记忆</li><li>自身的笔记</li><li>用户偏好</li><li>长期目标</li><li>任务结果</li><li>已连接应用中的工作上下文</li></ul><p><strong>5. 主动研究与执行权限分离</strong></p><p>dots 可以主动发现值得关注的信息，但主动研究中的部分工具采用只读权限。</p><p>需要对外部系统采取实际行动时，还需要遵循对应的授权和审批规则。</p><p>因此，主动发现问题与自动修改系统并不是一回事。</p><h3 id="适合谁？-2"><a href="#适合谁？-2" class="headerlink" title="适合谁？"></a>适合谁？</h3><p>dots 更适合：</p><ul><li>已经使用 ChatGPT 的专业用户</li><li>使用 Codex 的开发者</li><li>有长期研究任务的知识工作者</li><li>需要协调多个项目的用户</li><li>希望 AI 持续跟进工作而非只完成一次对话的用户</li></ul><p>它的设计理念更像：</p><p><strong>一个长期负责结果，并且能够协调其他工具的 AI 项目负责人。</strong></p><p>官方文档：</p><ul><li><a href="https://learn.chatgpt.com/docs/dots/tasks-and-memory">dots Tasks and Memory</a></li><li><a href="https://learn.chatgpt.com/docs/dots/computers-and-apps">dots Computers and Apps</a></li><li><a href="https://learn.chatgpt.com/docs/dots/controls">dots Controls</a></li></ul><hr><h2 id="六、Meta-Muse：免费个人智能体，强调生活与目标管理"><a href="#六、Meta-Muse：免费个人智能体，强调生活与目标管理" class="headerlink" title="六、Meta Muse：免费个人智能体，强调生活与目标管理"></a>六、Meta Muse：免费个人智能体，强调生活与目标管理</h2><p>Muse 是 Meta 推出的个人智能体。</p><p>它的特点是：</p><p><strong>免费版就可以使用基础智能体功能，而不是必须先购买昂贵的专业套餐。</strong></p><h3 id="主要功能-3"><a href="#主要功能-3" class="headerlink" title="主要功能"></a>主要功能</h3><p><strong>1. 长期目标管理</strong></p><p>Muse 提供 Goals 功能，用于管理和持续推进个人目标。</p><p>例如：</p><ul><li>旅行规划</li><li>学习安排</li><li>个人财务整理</li><li>家庭事务</li><li>购物与生活计划</li><li>小型企业经营</li></ul><p><strong>2. 云端电脑</strong></p><p>Muse 可以使用自己的云端环境，包括：</p><ul><li>浏览器</li><li>文件系统</li><li>命令行</li><li>安全虚拟机</li></ul><p>它可以生成文档、网页、追踪工具及仪表盘。</p><p><strong>3. Mac 本地操作</strong></p><p>Meta 已经公布 Muse 的 Mac 本地操作能力。</p><p>获得相应权限后，Muse 可以处理部分本地文件以及：</p><ul><li>iMessage</li><li>Notes</li><li>Reminders</li><li>Mail</li><li>Calendar</li></ul><p>这一能力对于深度使用 macOS 的用户具有吸引力。</p><p><strong>4. 商业连接器</strong></p><p>Muse 还扩展了小企业经营相关工具，包括：</p><ul><li>Shopify</li><li>QuickBooks</li><li>Stripe</li><li>Slack</li><li>Notion</li><li>Facebook</li><li>Instagram</li><li>Meta 广告账户</li></ul><p><strong>5. 语音与电话功能</strong></p><p>Muse 已经公布语音交互功能。</p><p>Meta 还展示了替用户联系商家的电话操作，但这仍属于实验性能力，不代表所有用户都已获得通用电话外呼功能。</p><h3 id="模型方面"><a href="#模型方面" class="headerlink" title="模型方面"></a>模型方面</h3><p>Muse 最初主要基于 Muse Spark。</p><p>2026 年 10 月，Meta 又宣布 Wonder 模型将优先向 Muse 订阅用户推出。</p><p>不过，目前不能据此认定所有 Muse Power 或 Maximum 用户已经全面切换到 Wonder。</p><h3 id="适合谁？-3"><a href="#适合谁？-3" class="headerlink" title="适合谁？"></a>适合谁？</h3><p>Muse 更适合：</p><ul><li>希望免费尝试个人智能体的用户</li><li>Mac 用户</li><li>有较多日常事务的用户</li><li>希望 AI 管理长期个人目标的用户</li><li>使用 Meta 商业生态的小企业主</li></ul><p>它的设计更接近：</p><p><strong>一个长期了解你的生活、习惯和目标的私人助理。</strong></p><p>官方资料：</p><ul><li><a href="https://introducing.muse.ai/">Introducing Muse</a></li><li><a href="https://muse.ai/business">Muse Business</a></li><li><a href="https://www.meta.com/help/subscriptions/1021145227643680/">Meta Muse Subscription</a></li></ul><hr><h1 id="七、完整订阅权益对比"><a href="#七、完整订阅权益对比" class="headerlink" title="七、完整订阅权益对比"></a>七、完整订阅权益对比</h1><p>仅比较 AI 助手的最低价格并不公平。</p><p>因为这些助手并不是独立售卖的产品，部分功能直接包含在母公司的 AI 订阅中。</p><p>下面分别整理四家的套餐。</p><h2 id="7-1-Claude-套餐"><a href="#7-1-Claude-套餐" class="headerlink" title="7.1 Claude 套餐"></a>7.1 Claude 套餐</h2><table><thead><tr><th>套餐</th><th align="right">月付</th><th align="right">年付</th><th>主要权益</th><th>Duet</th></tr></thead><tbody><tr><td>Free</td><td align="right">$0</td><td align="right">—</td><td>基础聊天、搜索、文件、记忆、Artifacts 等</td><td>不包含</td></tr><tr><td>Pro</td><td align="right">$20</td><td align="right">$200</td><td>更多用量、Claude Code、Projects、Research、连接器等</td><td>美国用户可候补</td></tr><tr><td>Max 5x</td><td align="right">$100</td><td align="right">暂无</td><td>更高用量、优先访问、每月 $100 API Credits</td><td>美国用户可候补</td></tr><tr><td>Max 20x</td><td align="right">$200</td><td align="right">暂无</td><td>更高用量、每月 $200 API Credits</td><td>美国用户可候补</td></tr></tbody></table><h3 id="Claude-Max-的-API-Credits"><a href="#Claude-Max-的-API-Credits" class="headerlink" title="Claude Max 的 API Credits"></a>Claude Max 的 API Credits</h3><p>目前 Claude Max 还提供相应的月度 API Credits：</p><ul><li>Max 5x：$100&#x2F;月</li><li>Max 20x：$200&#x2F;月</li></ul><p>但是有重要限制：</p><ol><li>新订阅需要满 7 天并关联 Claude Console 组织后领取。</li><li>每个计费周期刷新，不结转。</li><li>可用于 Claude API、Managed Agents、Agent SDK 等。</li><li>不能用于交互式 Claude Code。</li><li>不能抵扣 Claude、Cowork 或 Claude Code 的超额使用费用。</li></ol><p>因此不能把 API Credits 简单视为 Duet 可额外消耗的额度。</p><p>官方来源：</p><ul><li><a href="https://claude.com/pricing">Claude Pricing</a></li><li><a href="https://support.claude.com/en/articles/11049741-what-is-the-max-plan">What Is the Max Plan?</a></li><li><a href="https://support.claude.com/en/articles/17154008-monthly-api-credits-for-max-and-team-plans">Monthly API Credits</a></li></ul><hr><h2 id="7-2-Grok-The-X-Subscription-套餐"><a href="#7-2-Grok-The-X-Subscription-套餐" class="headerlink" title="7.2 Grok &#x2F; The X Subscription 套餐"></a>7.2 Grok &#x2F; The X Subscription 套餐</h2><p>新版 The X Subscription 将多款产品整合到统一订阅中。</p><table><thead><tr><th>套餐</th><th align="right">月付</th><th align="right">年付</th><th>AI 用量倍率</th><th>Grok Bot</th></tr></thead><tbody><tr><td>Free</td><td align="right">$0</td><td align="right">—</td><td>有限使用</td><td>不包含常规权限</td></tr><tr><td>Plus</td><td align="right">$8</td><td align="right">$80</td><td>1×</td><td>不包含</td></tr><tr><td>Premium</td><td align="right">$30</td><td align="right">$300</td><td>4×</td><td>包含</td></tr><tr><td>Super</td><td align="right">$100</td><td align="right">$1,000</td><td>15×</td><td>包含</td></tr><tr><td>Ultra</td><td align="right">$200</td><td align="right">$2,000</td><td>50×</td><td>包含</td></tr></tbody></table><p>倍率均以 Plus 套餐为基准。</p><p>这不意味着不同套餐的 Bot 数量、执行任务数量或速度严格按照这些倍率增加。</p><h3 id="各档权益"><a href="#各档权益" class="headerlink" title="各档权益"></a>各档权益</h3><p><strong>Plus：$8&#x2F;月</strong></p><p>主要包括：</p><ul><li>Grok Chat</li><li>Grok Voice</li><li>Grok Imagine</li><li>Grok Build</li><li>Cursor 基础代理</li><li>部分 X 认证和创作者权益</li></ul><p><strong>Premium：$30&#x2F;月</strong></p><p>在 Plus 的基础上，增加：</p><ul><li>Grok Bot</li><li>Cursor 云端代理</li><li>自动化功能</li><li>Origin 代码托管</li><li>Bugbot 代码评审</li><li>视频生成</li><li>更多 X 权益</li></ul><p><strong>Super：$100&#x2F;月</strong></p><p>主要增加：</p><ul><li>更多共享 AI 用量</li><li>高峰时期的模型优先访问</li></ul><p><strong>Ultra：$200&#x2F;月</strong></p><p>主要增加：</p><ul><li>最高档共享 AI 用量</li><li>新产品与模型优先体验资格</li></ul><h3 id="Grok-套餐的两个重要限制"><a href="#Grok-套餐的两个重要限制" class="headerlink" title="Grok 套餐的两个重要限制"></a>Grok 套餐的两个重要限制</h3><p><strong>第一，Cursor 第三方模型单独计费。</strong></p><p>如果用户在 Cursor 中手动选择 Claude、GPT 等第三方模型，从首次使用起就会按照对应的 API 标价额外收费。</p><p>不是包含在 30 美元订阅内。</p><p><strong>第二，Grok API 不赠送 API 使用额度。</strong></p><p>能够访问 Grok API，不等于订阅包含免费的 API Credits。</p><p>API 仍然按照相应的使用价格计费。</p><p>因此，如果购买 Premium 主要用于 Cursor 编程，应该将第三方模型的用量成本一起考虑。</p><p>官方来源：</p><ul><li><a href="https://docs.x.ai/x-subscription/pricing">The X Subscription Pricing</a></li><li><a href="https://cursor.com/pricing">Cursor Pricing</a></li><li><a href="https://cursor.com/help/grok-bot/plans">Grok Bot Plans</a></li></ul><hr><h2 id="7-3-ChatGPT-套餐"><a href="#7-3-ChatGPT-套餐" class="headerlink" title="7.3 ChatGPT 套餐"></a>7.3 ChatGPT 套餐</h2><table><thead><tr><th>套餐</th><th align="right">月付</th><th>主要权益</th><th>dots</th></tr></thead><tbody><tr><td>Free</td><td align="right">$0</td><td>基础聊天与工具</td><td>不包含</td></tr><tr><td>Go</td><td align="right">$8</td><td>入门付费、更高基础使用额度</td><td>不包含</td></tr><tr><td>Plus</td><td align="right">$20</td><td>更高模型用量、图像、语音、研究及 Codex</td><td>不包含</td></tr><tr><td>Pro 100</td><td align="right">$100</td><td>高级模型、更多工具与用量</td><td>包含</td></tr><tr><td>Pro 200</td><td align="right">$200</td><td>比 Pro 100 更多的包含用量</td><td>包含</td></tr><tr><td>Pro 500</td><td align="right">$500</td><td>更高用量、部分高级模型的 Ultrafast 模式</td><td>包含</td></tr></tbody></table><h3 id="dots-是否单独收费？"><a href="#dots-是否单独收费？" class="headerlink" title="dots 是否单独收费？"></a>dots 是否单独收费？</h3><p>目前首个 dot 包含在符合条件的 Pro 或 Business Premium 套餐中。</p><p>无需额外支付一份独立的 dots 订阅费。</p><p>但是，必须区分两个概念：</p><ul><li>与 dot 的对话</li><li>dot 实际委派执行的工作</li></ul><p>官方说明，与 dot 的对话不计入普通 ChatGPT 使用限制。</p><p>但 dot 创建或管理的 Work、Codex 等任务仍然会消耗对应工具的使用额度。</p><p>因此，不能把 dots 理解成一个每月支付 100 美元就能无限执行复杂任务的助手。</p><h3 id="ChatGPT-Business"><a href="#ChatGPT-Business" class="headerlink" title="ChatGPT Business"></a>ChatGPT Business</h3><table><thead><tr><th>套餐</th><th align="right">月付&#x2F;人</th><th align="right">年付折月&#x2F;人</th><th>dots</th></tr></thead><tbody><tr><td>Business Standard</td><td align="right">$25</td><td align="right">$20</td><td>当前不包含</td></tr><tr><td>Business Premium</td><td align="right">$125</td><td align="right">$100</td><td>包含，分批开放</td></tr></tbody></table><p>Business 新建工作区至少需要两个付费席位。</p><p>所以，个人 Pro 100 的每月 $100 与 Business Premium 的年付折月 $100，不是同一种购买方式。</p><p>Enterprise 用户则需要满足对应资格，并由管理员启用相关功能。</p><p>官方来源：</p><ul><li><a href="https://learn.chatgpt.com/docs/pricing">ChatGPT Pricing</a></li><li><a href="https://help.openai.com/en/articles/9793128-about-chatgpt-pro-tiers">About ChatGPT Pro Tiers</a></li><li><a href="https://help.openai.com/en/articles/8980713-sign-up-for-chatgpt-business">ChatGPT Business</a></li><li><a href="https://learn.chatgpt.com/docs/dots">ChatGPT dots</a></li></ul><hr><h2 id="7-4-Muse-套餐"><a href="#7-4-Muse-套餐" class="headerlink" title="7.4 Muse 套餐"></a>7.4 Muse 套餐</h2><table><thead><tr><th>套餐</th><th align="right">月付</th><th align="right">每周 Muse Tokens</th><th>特点</th></tr></thead><tbody><tr><td>Free</td><td align="right">$0</td><td align="right">未公布明确数值</td><td>基础智能体能力</td></tr><tr><td>Power</td><td align="right">$20</td><td align="right">500M（5 亿）</td><td>更多使用量</td></tr><tr><td>Maximum</td><td align="right">$100</td><td align="right">3B（30 亿）</td><td>更高使用量</td></tr></tbody></table><p>根据 Meta 公布的数据：</p><ul><li>Power：每周 5 亿 Muse Tokens</li><li>Maximum：每周 30 亿 Muse Tokens</li></ul><p>Maximum 的价格是 Power 的 5 倍，而公布的周额度是 Power 的 6 倍。</p><p>不过，不能直接把 Muse Tokens 与 Claude、Grok 或 ChatGPT 的订阅额度进行数字比较。</p><p>因为不同平台的 Token 统计、工具执行成本与任务计费方式并不统一。</p><h3 id="Muse-和-Muse-Code-不是同一个订阅"><a href="#Muse-和-Muse-Code-不是同一个订阅" class="headerlink" title="Muse 和 Muse Code 不是同一个订阅"></a>Muse 和 Muse Code 不是同一个订阅</h3><p>需要特别注意：</p><p>Muse Code 是 Meta 的独立编程产品。</p><p>它拥有自己的订阅与使用规则。</p><p>因此不能将 Muse Code 的：</p><ul><li>编程额度</li><li>Wonder 模型权益</li><li>API 使用规则</li></ul><p>直接算作 Muse 助手 Power 或 Maximum 套餐的权益。</p><p>官方来源：</p><ul><li><a href="https://www.meta.com/help/subscriptions/1021145227643680/">Muse Subscription</a></li><li><a href="https://dev.meta.ai/docs/muse-code/subscriptions">Muse Code Subscriptions</a></li></ul><hr><h1 id="八、后台任务如何消耗额度？"><a href="#八、后台任务如何消耗额度？" class="headerlink" title="八、后台任务如何消耗额度？"></a>八、后台任务如何消耗额度？</h1><p>对主动式 AI 助手来说，订阅价格不一定是最重要的成本。</p><p>因为这些助手可能在用户没有主动聊天时，依然继续运行任务。</p><table><thead><tr><th>产品</th><th>额度机制</th><th>注意事项</th></tr></thead><tbody><tr><td>Claude Duet</td><td>与 Claude 共用五小时及每周使用限制</td><td>早间简报、后台检查也消耗订阅额度</td></tr><tr><td>Grok Bot</td><td>与 Grok、Cursor 相关功能共用每周 AI 额度池</td><td>Bot 使用越多，留给其他功能的额度越少</td></tr><tr><td>ChatGPT dots</td><td>对话与委派任务分别计量</td><td>Work、Codex 任务继续消耗相应额度</td></tr><tr><td>Meta Muse</td><td>免费版有限额，付费使用周 Token 额度</td><td>Token 数字不能直接换算成任务数量</td></tr></tbody></table><h2 id="Claude-Duet-的问题"><a href="#Claude-Duet-的问题" class="headerlink" title="Claude Duet 的问题"></a>Claude Duet 的问题</h2><p>Claude Duet 与 Claude 主产品共用订阅限制。</p><p>例如，Duet 在后台进行日常检查、准备晨间简报时，也会计入相应额度。</p><p>因此，Claude Pro 的 20 美元并不代表能够获得一个无限工作的常驻秘书。</p><h2 id="Grok-Bot-的问题"><a href="#Grok-Bot-的问题" class="headerlink" title="Grok Bot 的问题"></a>Grok Bot 的问题</h2><p>Grok Bot、Grok 和 Cursor 的相关功能使用同一个共享 AI 额度体系。</p><p>因此，当 Bot 执行大量自动化任务时，可能减少其他 AI 功能的可用额度。</p><p>Premium 的 $30 不能理解为每个产品分别赠送一整份独立额度。</p><h2 id="ChatGPT-dots-的问题"><a href="#ChatGPT-dots-的问题" class="headerlink" title="ChatGPT dots 的问题"></a>ChatGPT dots 的问题</h2><p>与 dots 交流并不等于所有工作都免费。</p><p>当 dots 创建或委派 Work、Codex 等实际任务时，依然需要消耗相应工具的额度。</p><p>对于高频率执行代码修改、浏览器操作和文件处理的用户，这一点尤其重要。</p><h2 id="Muse-的问题"><a href="#Muse-的问题" class="headerlink" title="Muse 的问题"></a>Muse 的问题</h2><p>Muse 公布了相对明确的周 Token 数字。</p><p>但目前缺少统一标准，无法将它转换为：</p><ul><li>每周可以完成多少复杂任务</li><li>可以运行多少小时浏览器</li><li>可以执行多少次编程操作</li><li>可以同时管理多少长期目标</li></ul><p>因此不能单纯根据数字大小认定 Muse 的性价比一定高于其他产品。</p><hr><h1 id="九、不同用户应该怎么选择？"><a href="#九、不同用户应该怎么选择？" class="headerlink" title="九、不同用户应该怎么选择？"></a>九、不同用户应该怎么选择？</h1><p>将功能、套餐与实际使用方式综合考虑，可以得到以下建议。</p><table><thead><tr><th>用户需求</th><th>推荐优先考虑</th><th>理由</th></tr></thead><tbody><tr><td>免费体验个人智能体</td><td>Meta Muse Free</td><td>免费版具备基础智能体功能</td></tr><tr><td>管理邮件、日历与商务工作</td><td>Claude Duet</td><td>重点在主动整理工作与发现待办</td></tr><tr><td>建立多个专业 AI 助手</td><td>Grok Bot</td><td>多 Bot、群聊、Skills、Routines</td></tr><tr><td>同时使用 Cursor、Grok 与 X</td><td>Grok Premium</td><td>多项产品整合进 $30 套餐</td></tr><tr><td>长期管理开发与研究项目</td><td>ChatGPT dots</td><td>可以持续跟进并委派 Work、Codex</td></tr><tr><td>在 Mac 上处理生活事务</td><td>Meta Muse</td><td>拥有 Mac 本地操作能力</td></tr><tr><td>已有深度 Claude 工作流</td><td>Claude Duet</td><td>能利用已有记忆、Skills 和连接器</td></tr><tr><td>主要需要更多编程额度</td><td>先比较原有编程套餐</td><td>AI 助手套餐并不一定等于更多代码模型额度</td></tr></tbody></table><hr><h1 id="十、总结：四种不同的-AI-助手路线"><a href="#十、总结：四种不同的-AI-助手路线" class="headerlink" title="十、总结：四种不同的 AI 助手路线"></a>十、总结：四种不同的 AI 助手路线</h1><p>虽然 Claude Duet、Grok Bot、ChatGPT dots 和 Meta Muse 都被定位为下一代主动式 AI 助手，但它们并不是完全相同的产品。</p><p><strong>Claude Duet：工作优先</strong></p><p>更关注用户的日历、邮件、业务任务与每日工作安排。</p><p>它希望成为一个主动整理信息、发现问题的工作秘书。</p><p><strong>Grok Bot：多智能体团队</strong></p><p>强调 Bot 分工、协作、技能复用与自动化。</p><p>它希望让用户像管理团队一样管理多个 AI 助手。</p><p><strong>ChatGPT dots：持续负责</strong></p><p>强调长期任务、上下文延续、跨工具协调，以及 Work 和 Codex 的任务委派。</p><p>它希望成为一个持续推进目标的 AI 项目负责人。</p><p><strong>Meta Muse：个人生活与目标</strong></p><p>强调长期个人记忆、日常生活、Goals、商业连接器和本地设备操作。</p><p>它希望成为一个能够长期了解用户的私人助理。</p><h2 id="最后的价格结论"><a href="#最后的价格结论" class="headerlink" title="最后的价格结论"></a>最后的价格结论</h2><p>从最低订阅门槛来看：</p><table><thead><tr><th>排序</th><th>产品</th><th align="right">最低月费</th><th>关键条件</th></tr></thead><tbody><tr><td>1</td><td>Meta Muse</td><td align="right">$0</td><td>免费可用，但地区有限</td></tr><tr><td>2</td><td>Claude Duet</td><td align="right">$20</td><td>仅美国，候补邀请</td></tr><tr><td>3</td><td>Grok Bot</td><td align="right">$30</td><td>Premium 起</td></tr><tr><td>4</td><td>ChatGPT dots</td><td align="right">$100</td><td>Pro 100 起，分批开放</td></tr></tbody></table><p><strong>但月费最低并不意味着实际使用成本最低，月费最高也不意味着任务能力一定最强。</strong></p><p>目前各家公司并没有提供可直接比较的统一 Agent 任务基准。</p><p>更合理的评估方式应该是使用同一批任务，比较：</p><ol><li>任务完成成功率</li><li>单次任务实际消耗</li><li>是否需要人工介入</li><li>自动化执行稳定性</li><li>工具连接与数据权限</li><li>是否能持续跟进和修正任务</li><li>每月真正完成的有效工作量</li></ol><p>对于已经购买 Claude、ChatGPT 或 Cursor 订阅的用户，首先需要核对自己现有套餐是否已经包含对应的智能体权益，避免重复付费。</p><p>因此，购买前最好先确认账户是否已获得实际使用入口，而不是单凭订阅页面上的功能介绍进行升级。</p><hr><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><h3 id="Anthropic-Claude"><a href="#Anthropic-Claude" class="headerlink" title="Anthropic &#x2F; Claude"></a>Anthropic &#x2F; Claude</h3><ul><li><a href="https://claude.com/pricing">Claude Pricing</a></li><li><a href="https://claude.com/resources/articles/claude-duet">Introducing Claude Duet</a></li><li><a href="https://support.claude.com/en/articles/17631495-getting-started-with-claude-duet">Getting Started with Claude Duet</a></li><li><a href="https://support.claude.com/en/articles/11049741-what-is-the-max-plan">What Is the Max Plan?</a></li><li><a href="https://support.claude.com/en/articles/17154008-monthly-api-credits-for-max-and-team-plans">Monthly API Credits</a></li></ul><h3 id="xAI-Grok-Cursor"><a href="#xAI-Grok-Cursor" class="headerlink" title="xAI &#x2F; Grok &#x2F; Cursor"></a>xAI &#x2F; Grok &#x2F; Cursor</h3><ul><li><a href="https://docs.x.ai/x-subscription/pricing">The X Subscription Pricing</a></li><li><a href="https://docs.x.ai/grok-bot/overview">Grok Bot Overview</a></li><li><a href="https://cursor.com/help/grok-bot/plans">Grok Bot Plans</a></li><li><a href="https://cursor.com/pricing">Cursor Pricing</a></li><li><a href="https://docs.x.ai/grok-bot/skills-routines-and-automations">Skills, Routines and Automations</a></li><li><a href="https://docs.x.ai/grok-bot/computer-and-apps">Computer and Apps</a></li></ul><h3 id="OpenAI-ChatGPT"><a href="#OpenAI-ChatGPT" class="headerlink" title="OpenAI &#x2F; ChatGPT"></a>OpenAI &#x2F; ChatGPT</h3><ul><li><a href="https://learn.chatgpt.com/docs/pricing">ChatGPT Pricing</a></li><li><a href="https://help.openai.com/en/articles/9793128-about-chatgpt-pro-tiers">ChatGPT Pro Tiers</a></li><li><a href="https://help.openai.com/en/articles/8980713-sign-up-for-chatgpt-business">ChatGPT Business</a></li><li><a href="https://learn.chatgpt.com/docs/dots">ChatGPT dots</a></li><li><a href="https://learn.chatgpt.com/docs/dots/tasks-and-memory">dots Tasks and Memory</a></li><li><a href="https://learn.chatgpt.com/docs/dots/computers-and-apps">dots Computers and Apps</a></li></ul><h3 id="Meta-Muse"><a href="#Meta-Muse" class="headerlink" title="Meta &#x2F; Muse"></a>Meta &#x2F; Muse</h3><ul><li><a href="https://introducing.muse.ai/">Introducing Muse</a></li><li><a href="https://muse.ai/business">Muse Business</a></li><li><a href="https://www.meta.com/help/subscriptions/1021145227643680/">Muse Subscription</a></li><li><a href="https://dev.meta.ai/docs/muse-code/subscriptions">Muse Code Subscriptions</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;更新日期：2026 年 10 月 23 日&lt;br&gt;对比产品：Claude Duet、Grok Bot、ChatGPT dots、Meta Muse  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;随着 AI 助手从被动问答转向主动执行任务，Anthr</summary>
      
    
    
    
    <category term="工具资源" scheme="https://ooo.run/categories/%E5%B7%A5%E5%85%B7%E8%B5%84%E6%BA%90/"/>
    
    
    <category term="Claude Duet" scheme="https://ooo.run/tags/Claude-Duet/"/>
    
    <category term="Grok Bot" scheme="https://ooo.run/tags/Grok-Bot/"/>
    
    <category term="ChatGPT dots" scheme="https://ooo.run/tags/ChatGPT-dots/"/>
    
    <category term="Meta Muse" scheme="https://ooo.run/tags/Meta-Muse/"/>
    
  </entry>
  
  <entry>
    <title>Google 大幅提升付费用户 Antigravity 中的 Gemini 4 Argon 配额</title>
    <link href="https://ooo.run/post/gemini-4-argon-antigravity-quota-update.html"/>
    <id>https://ooo.run/post/gemini-4-argon-antigravity-quota-update.html</id>
    <published>2026-10-22T11:43:09.000Z</published>
    <updated>2026-10-22T12:19:57.704Z</updated>
    
    <content type="html"><![CDATA[<p>面对首批用户对 Gemini 4 Argon 初始配额“不够塞牙缝”的密集反馈，Google 近期悄然完成了配额提升，并对周额度进行了一次全面重置。此次调整中，主力订阅档位的可用额度近乎翻倍。</p><p>即便账面额度翻倍，不同订阅档位折算成真实 API 额度后对比 Codex &#x2F; Claude Pro 订阅依然差距悬殊。本文将结合最新实测数据，全面拆解 Gemini 4 Argon 的最新配额机制、Token 折算标准、四大渠道权限矩阵以及当下的订阅策略。</p><hr><h2 id="核心要点速览"><a href="#核心要点速览" class="headerlink" title="核心要点速览"></a>核心要点速览</h2><ul><li><strong>配额大幅跃升</strong>：Pro（$20&#x2F;月）升至 <strong>$15&#x2F;周</strong>；Ultra（$100&#x2F;月）翻倍至 <strong>$50&#x2F;5小时、$200&#x2F;周</strong>。</li><li><strong>Token 换算标准</strong>：在常规高缓存命中率下，**$1 约合 1.6M 至 2.0M Tokens**。</li><li><strong>白嫖&#x2F;特惠限制</strong>：通过<strong>学生优惠、印度 Jio</strong> 等渠道获取的“非付费 Pro”账号，<strong>无法在 Antigravity IDE 中调用该模型</strong>，但现已获准在 <strong>AI Studio</strong> 中免费体验。</li><li><strong>订阅防坑指南</strong>：<strong>Ultra $100 档</strong> 为当前性价比最高的档位；鉴于官方策略调整频繁，强烈建议<strong>按月付费</strong>，切勿盲目锁定长期或年付订阅。</li></ul><p><img src="https://img.nep.me/ooo/cover-gemini4-argon-agy-ds.webp" alt="cover-gemini4-argon-agy-ds.png"></p><hr><h2 id="一、-新旧配额实测对比：主力档位近乎翻倍"><a href="#一、-新旧配额实测对比：主力档位近乎翻倍" class="headerlink" title="一、 新旧配额实测对比：主力档位近乎翻倍"></a>一、 新旧配额实测对比：主力档位近乎翻倍</h2><p>在完成周配额重置后，各付费档位的账面可用额度（以等效 API 消耗美金计）迎来了显著提升：</p><table><thead><tr><th align="left">档位</th><th align="left">价格&#x2F;月</th><th align="left">旧版配额</th><th align="left">最新配额</th><th align="left">实测表现与定位</th></tr></thead><tbody><tr><td align="left"><strong>Pro</strong></td><td align="left">$20</td><td align="left">$10 &#x2F; 周</td><td align="left"><strong>$15&#x2F;周</strong></td><td align="left">提升 50%。经社群实测，用于深度撰写单篇长论文或中型代码库重构仍略显局促。</td></tr><tr><td align="left"><strong>Ultra 5x</strong></td><td align="left">$100</td><td align="left">$25&#x2F;5H<br>$100&#x2F;周</td><td align="left"><strong>$50&#x2F;5H</strong><br><strong>$200&#x2F;周</strong></td><td align="left"><strong>额度全面翻倍</strong>。实测消耗 6% 的 5 小时额度约合 $3，是目前综合性价比最高的 <strong>主力档位</strong>。</td></tr><tr><td align="left"><strong>Ultra 20x</strong></td><td align="left">$200</td><td align="left">$70&#x2F;5H<br>$200&#x2F;周</td><td align="left"><strong>$200&#x2F;5H</strong><br><strong>$800&#x2F;周</strong></td><td align="left">迎来爆发式扩容（网传测算数据），适合极高强度的全天候自动化 Agent 与大型工程开发。</td></tr></tbody></table><hr><h2 id="二、-美金额度与-Token-数量直观换算"><a href="#二、-美金额度与-Token-数量直观换算" class="headerlink" title="二、 美金额度与 Token 数量直观换算"></a>二、 美金额度与 Token 数量直观换算</h2><p>抛开单纯的账面美金数字，结合真实开发环境下的后台用量统计，可以更直观地评估各档位的实际生产力：</p><ul><li><strong>实测基准参考</strong>：单日 45 次调用产生 <strong>4.83M 总 Token</strong>（其中输入用量 696.5k，包含直接输入与 4.02M 缓存读取；输出用量 119.2k，包含内容生成 78.3k 与思考推理 40.9k），在 <strong>85.2% 缓存命中率</strong>下，预估费用为 <strong>$2.99</strong>。</li><li><strong>折算比率</strong>：综合测算下来，<strong>每 $1 配额约可支撑 1.6M - 2.0M Tokens</strong> 的调用量。</li></ul><p>按此基准比率折算，各档位的实际 Token 承载力如下：</p><ul><li><strong>Pro（$20 档）</strong>：<ul><li>每周可用：<strong>24M - 30M Tokens</strong></li></ul></li><li><strong>Ultra 5x</strong>：<ul><li>每 5 小时可用：<strong>80M - 100M Tokens</strong></li><li>每周合计可用：<strong>320M - 400M Tokens</strong>（约为 Pro 档的 13 倍以上）</li></ul></li><li><strong>Ultra 50x</strong>：<ul><li>每 5 小时可用：<strong>320M - 400M Tokens</strong></li><li>每周合计可用：<strong>1,280M - 1,600M Tokens</strong></li></ul></li></ul><hr><h2 id="三、-四大渠道权限矩阵与“非付费-Pro”限制说明"><a href="#三、-四大渠道权限矩阵与“非付费-Pro”限制说明" class="headerlink" title="三、 四大渠道权限矩阵与“非付费 Pro”限制说明"></a>三、 四大渠道权限矩阵与“非付费 Pro”限制说明</h2><p>很多用户关心通过<strong>学生教育优惠（Student Discount）</strong>、<strong>印度 Jio 联名赠送</strong>或试用活动获得的“非付费 Pro（Unpaid Pro）”账号，在此次更新后能否愉快玩耍。以下是四大官方渠道的最新权限划分：</p><table><thead><tr><th align="left">平台 &#x2F; 渠道</th><th align="left">适用人群与权限要求</th><th align="left">核心政策说明</th></tr></thead><tbody><tr><td align="left"><strong>Antigravity IDE</strong></td><td align="left"><strong>仅限真实付费 Pro &#x2F; Ultra</strong></td><td align="left"><strong>维持严格付费墙</strong>。通过学生优惠、Jio 赠送等渠道获得的<strong>非付费 Pro 账号无法在 Antigravity 中使用</strong>。即便未来向非付费用户开放，免费配额也将面临极其严苛的限流瓶颈。</td></tr><tr><td align="left"><strong>Google AI Studio</strong></td><td align="left"><strong>非付费 Pro</strong> &#x2F; 付费 Pro &#x2F; Ultra</td><td align="left"><strong>权限正式拓宽</strong>。手持学生优惠或 Jio 非付费 Pro 账号的用户，现已可以在 AI Studio 中正式调用并体验 Gemini 4 Argon。</td></tr><tr><td align="left"><strong>Gemini App &amp; Web</strong></td><td align="left">所有 Pro 及 Ultra 用户</td><td align="left">政策维持不变，含非付费与付费在内的所有 Pro&#x2F;Ultra 订阅用户均可正常使用。</td></tr><tr><td align="left"><strong>Vertex AI</strong></td><td align="left">仅限付费 API 用户</td><td align="left">政策维持不变，仅面向绑定结算账户的企业及付费 API 开发者开放调用。</td></tr></tbody></table><hr><h2 id="四、-订阅决策与“防坑”建议"><a href="#四、-订阅决策与“防坑”建议" class="headerlink" title="四、 订阅决策与“防坑”建议"></a>四、 订阅决策与“防坑”建议</h2><ol><li><strong>首选档位推荐</strong>：<br>如果你在 Antigravity IDE 中有高频编码、长上下文分析或重度 Agent 生产力需求，$20 的 Pro 档位（24M-30M Tokens&#x2F;周）很容易触发周上限；建议直接选择 <strong>Ultra $100 档位</strong>，其每 5 小时 80M-100M Tokens、每周最高 400M Tokens 的容量足以应对绝大多数高强度开发场景，且单位 Token 成本远低于 Pro 档。</li><li><strong>切勿锁定长期订阅</strong>：<br>虽然 Google 此次迅速响应社区呼声、将配额翻倍的操作值得肯定，但熟悉 Google 在 Antigravity 及 AI 订阅生态历史操作的老玩家都非常清楚其策略调整与模型更迭的频繁程度（如随时可能出现的动态限流、计费权重调整或新模型分流）。因此，当下强烈建议坚持<strong>“按月付费（Month-to-Month）”</strong>，保持随时升降级或退订的灵活性，切忌盲目锁死年付等长期订阅。</li><li><strong>非付费 Pro 用户的最优解</strong>：<br>持有学生认证优惠或 Jio 权益的用户，无需在 Antigravity IDE 中耗费精力尝试突破权限限制，直接转向 <strong>Google AI Studio</strong> 或 <strong>Gemini Web&#x2F;App</strong> 即可零成本体验 Gemini 4 Argon 的完整能力。</li></ol><hr><h2 id="五、-延伸评估：Google-AI-Pro（-20-月）还值得订阅吗？"><a href="#五、-延伸评估：Google-AI-Pro（-20-月）还值得订阅吗？" class="headerlink" title="五、 延伸评估：Google AI Pro（$20&#x2F;月）还值得订阅吗？"></a>五、 延伸评估：Google AI Pro（$20&#x2F;月）还值得订阅吗？</h2><p>如果单看 Antigravity IDE 中的 AI 编程配额，$20&#x2F;月的 Pro 档位（每周 $15，约合 24M - 30M Tokens）面对高强度 Vibe Coding 或大型代码库重构时确实略显局促，在纯编码性价比上不如 Codex &#x2F; Claude 订阅。</p><p>但如果跳出“纯编码工具”的单一维度，从 <strong>Google 全家桶生态</strong>的视角来审视，这 $20&#x2F;月的含金量依然极高 —— 甚至可以说属于“买全家桶送 AI 额度”：</p><ul><li><strong>5TB Google Drive 云端存储</strong>：大容量云盘空间（支持家庭组共享），涵盖 Google Photos 原画质备份、Gmail 与 Google Drive，单买同级别云存储本身就价值不菲。</li><li><strong>YouTube Premium Lite 权益</strong>：附加轻量级免广告视频体验，大幅提升日常浏览与查阅技术教程的舒适度。</li><li><strong>Google Colab 算力与权益加成</strong>：提供更充裕的云端计算单元与更强的 GPU 分配优先级，对需要跑数据科学、模型微调或脚本测试的开发者极为实用。</li><li><strong>GCE 每月 10 美元额度</strong>：除了解锁 AI Studio 权限外，还能在 Google 云计算平台每月 10 美元的额度。</li></ul><p><strong>选购建议总结</strong>：</p><ul><li><strong>全生态综合型用户（强烈推荐 Pro $20 档）</strong>：如果你本身就有 Google Drive 扩容、YouTube 观看、Colab 算力或日常综合 AI 助手的需求，那么 $20 的 Pro 套餐综合回本率极高，附赠的每周 24M - 30M Tokens 足以应付日常轻中度代码补全与脚本编写。</li><li><strong>重度沉浸式编码开发者（建议直上 Ultra 5x $100 档或专精工具）</strong>：如果你订阅的核心诉求是全天候在 Antigravity IDE 中进行高强度 Agent 编码，Pro 档的周限额很快就会见底，此时按月订阅 <strong>Ultra $100 档</strong>（每周最高 400M Tokens）才是更纯粹的生产力选择。</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;面对首批用户对 Gemini 4 Argon 初始配额“不够塞牙缝”的密集反馈，Google 近期悄然完成了配额提升，并对周额度进行了一次全面重置。此次调整中，主力订阅档位的可用额度近乎翻倍。&lt;/p&gt;
&lt;p&gt;即便账面额度翻倍，不同订阅档位折算成真实 API 额度后对比 Co</summary>
      
    
    
    
    <category term="开发工具" scheme="https://ooo.run/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
    
    
    <category term="Gemini 4 Argon" scheme="https://ooo.run/tags/Gemini-4-Argon/"/>
    
    <category term="Antigravity IDE" scheme="https://ooo.run/tags/Antigravity-IDE/"/>
    
    <category term="Google AI Studio" scheme="https://ooo.run/tags/Google-AI-Studio/"/>
    
    <category term="AI 编程" scheme="https://ooo.run/tags/AI-%E7%BC%96%E7%A8%8B/"/>
    
  </entry>
  
  <entry>
    <title>把金库密码设成 4？一文看懂 eMudhra 证书私钥泄露为何影响全球每个人</title>
    <link href="https://ooo.run/post/why-emudhra-key-leak-matters.html"/>
    <id>https://ooo.run/post/why-emudhra-key-leak-matters.html</id>
    <published>2026-10-21T15:08:24.000Z</published>
    <updated>2026-10-22T20:19:19.327Z</updated>
    
    <content type="html"><![CDATA[<p><strong>当你打开浏览器访问网上银行时，你怎么知道眼前这个页面是真的银行，而不是黑客精仿的钓鱼网站？</strong> </p><p>答案藏在浏览器地址栏旁边的安全认证机制里。最近爆发的 <strong>eMudhra（印度知名数字证书颁发机构，旗下品牌为 emSign）私钥缺陷事件</strong>，让 Google、苹果、微软、Mozilla 以及 Go 语言团队在同一天拉响了最高级别的紧急安全警报。</p><p>很多人的第一反应是：“我又没用过这家印度公司的产品，甚至都没听过它的名字，这关我什么事？”</p><p>在互联网的底层逻辑里，<strong>一家受信任的证书机构出事，全世界所有人的设备都会直接暴露在危险之中。</strong> 下面我们就用最通俗的语言，拆解这场让人啼笑皆非又细思极恐的安全大地震。</p><p><img src="https://img.nep.me/ooo/emudhra-ds.webp" alt="emudhra-ds.png"></p><hr><h2 id="一、-什么是-CA？互联网的“护照管理局”"><a href="#一、-什么是-CA？互联网的“护照管理局”" class="headerlink" title="一、 什么是 CA？互联网的“护照管理局”"></a>一、 什么是 CA？互联网的“护照管理局”</h2><p>在现实生活中，你去银行办业务，银行看你的身份证或护照就能相信你是谁。为什么？因为身份证是由<strong>国家公安机关</strong>签发的，银行无条件信任公安机关的防伪印章。</p><p>在互联网上，这个“发证机关”就叫做 <strong>CA（Certificate Authority，证书颁发机构）</strong>。</p><ul><li>当你访问 <code>google.com</code> 或 <code>taobao.com</code> 时，网站会向你的浏览器出示一张“数字身份证”（即 TLS&#x2F;SSL 证书）。</li><li>你的手机和电脑（无论是 Windows、macOS、iOS 还是 Android）在出厂时，系统里就内置了一份<strong>“绝对信任的发证机关名单”（根证书库）</strong>。</li><li><strong>eMudhra 就是这份全球白名单里的正式成员之一。</strong> 只要盖有它家“数字印章”的网站，全世界的手机和浏览器都会默认放行，告诉用户：“这个网站是安全的、正牌的。”</li></ul><hr><h2 id="二、-离谱的缺陷：把金库密码设成了“4”"><a href="#二、-离谱的缺陷：把金库密码设成了“4”" class="headerlink" title="二、 离谱的缺陷：把金库密码设成了“4”"></a>二、 离谱的缺陷：把金库密码设成了“4”</h2><p>CA 机构用来给网站“盖章”的核心工具，叫做<strong>私钥（Private Key）</strong>。</p><p>按照现代密码学（如椭圆曲线加密 ECC）的设计，一个合格的私钥应该是一个极其庞大、完全随机生成的数字。大到什么程度？就算把全地球所有的超级计算机加起来不眠不休地猜，也需要算到宇宙毁灭才能猜中。因此，即使全天下都能看到公开的证书（公钥），也绝对反推不出背后的私钥。</p><p>然而，在最近披露的漏洞中，安全研究人员发现 eMudhra 旗下有 <strong>8 张核心中级证书（Intermediate CA）</strong> 的私钥生成过程出现了灾难性的代码缺陷——<strong>随机数生成器（RNG）几乎完全失效了。</strong></p><p>这导致了什么结果？</p><ul><li>正常情况下，私钥应该是一个几百位的天文数字。</li><li>而 eMudhra 生成的这 8 把私钥，竟然全都是<strong>小于 256 的整数</strong>！</li><li>安全研究员 Scott Helme 测试后震惊地发现，<strong>其中一把核心私钥的数字竟然就是 4</strong>。</li></ul><p>这就好比一家掌控着全球通行证的顶级印钞厂，花重金建造了厚达十米的钛合金金库大门，结果锁匠在装密码锁时偷懒，把密码设成了 <code>0004</code>。</p><p><strong>为什么说它“不需要被黑客偷走就已经泄露了”？</strong><br>因为证书本身是公开在互联网上的。任何人用一台普通家用笔记本电脑，写几行简单的代码，从 <code>1</code> 开始往上试，<strong>不到 1 秒钟（甚至用 AI 跑一句提示词）</strong>，就能从公开的证书里把这 8 把绝密私钥全部算出来。</p><hr><h2 id="三、-为什么这会影响到“每一个人”？"><a href="#三、-为什么这会影响到“每一个人”？" class="headerlink" title="三、 为什么这会影响到“每一个人”？"></a>三、 为什么这会影响到“每一个人”？</h2><p>对于普通网民和初级开发者来说，理解这件事的杀伤力，需要明白互联网信任链中的一个核心软肋：<strong>木桶效应（最弱一环决定整体安全）</strong>。</p><p>在浏览器的信任机制里，默认情况下，<strong>任何一家受信任的 CA，都可以为全世界任何一个域名签发证书。</strong></p><p>哪怕 Google、苹果自己用的证书是由 DigiCert 或 Let’s Encrypt 签发的，跟印度的 eMudhra 半毛钱关系都没有，但只要你的电脑系统信任 eMudhra，攻击者算出那把等于 <code>4</code> 的私钥后，就能干出下面两件极其恐怖的事：</p><h3 id="1-完美的“中间人攻击”与网站伪造（针对-6-张-TLS-证书）"><a href="#1-完美的“中间人攻击”与网站伪造（针对-6-张-TLS-证书）" class="headerlink" title="1. 完美的“中间人攻击”与网站伪造（针对 6 张 TLS 证书）"></a>1. 完美的“中间人攻击”与网站伪造（针对 6 张 TLS 证书）</h3><p>泄露的 8 把钥匙里，有 6 把是用来给网站签发 HTTPS 证书的。攻击者拿到钥匙后，可以自己开个假网站，然后用 eMudhra 的私钥给自己盖个章，签发一张写着 <code>www.google.com</code> 或你常用的某家银行域名的<strong>“真证书”</strong>。</p><p>当你连上咖啡馆、机场的公共 Wi-Fi，或者你的路由器、DNS 被劫持时：</p><ul><li>黑客把你的流量引向他伪造的假银行网站。</li><li>你的浏览器上前检查身份证，一看：“哟，有 eMudhra 的亲笔签名，而且在我的出厂信任名单里！”</li><li><strong>浏览器不会弹出任何红色的安全警告</strong>，地址栏依然显示安全锁标志。你输入的账号、密码、聊天记录，会在毫不知情的情况下被黑客全部截获解密。</li></ul><h3 id="2-给木马病毒穿上“正版免死金牌”（针对-2-张代码签名证书）"><a href="#2-给木马病毒穿上“正版免死金牌”（针对-2-张代码签名证书）" class="headerlink" title="2. 给木马病毒穿上“正版免死金牌”（针对 2 张代码签名证书）"></a>2. 给木马病毒穿上“正版免死金牌”（针对 2 张代码签名证书）</h3><p>更要命的是，这 8 把钥匙里还有 <strong>2 把是代码签名证书（Code Signing CA）</strong>。<br>平时我们在 Windows 或 Mac 上安装软件时，如果是个来历不明的病毒程序，系统会弹出大大的黄色或红色警告拦截它。但如果黑客用这把泄露的私钥给勒索病毒“签个名”，操作系统就会认为这是经过权威机构认证的合法企业软件，直接静音放行。</p><hr><h2 id="四、-全球紧急拆弹：科技巨头们做了什么？"><a href="#四、-全球紧急拆弹：科技巨头们做了什么？" class="headerlink" title="四、 全球紧急拆弹：科技巨头们做了什么？"></a>四、 全球紧急拆弹：科技巨头们做了什么？</h2><p>正因为这把“万能钥匙”谁都能在 1 秒内算出来，整个互联网基础设施在短短几十小时内上演了一场生死时速的“拆弹行动”：</p><table><thead><tr><th align="left">参与方</th><th align="left">紧急应对措施</th><th align="left">影响范围</th></tr></thead><tbody><tr><td align="left"><strong>Google (Chrome &#x2F; Android)</strong></td><td align="left">通过在线更新机制，直接拉黑这 8 张问题证书，并启动对 eMudhra 根证书的全面审查与移除程序。</td><td align="left">全球数十亿 Chrome 浏览器及安卓设备。</td></tr><tr><td align="left"><strong>Mozilla (Firefox)</strong></td><td align="left">启用 OneCRL 远程吊销机制，并连夜发布 Firefox 158.0.1 等紧急补丁版本将黑名单焊死在代码里。</td><td align="left">所有火狐浏览器及依赖 NSS 安全库的系统。</td></tr><tr><td align="left"><strong>Apple &amp; Microsoft</strong></td><td align="left">在各自的信任库（Trust Store）中紧急拉黑受影响的证书链，拦截伪造签名。</td><td align="left">全球 Windows、macOS、iPhone 和 iPad 用户。</td></tr><tr><td align="left"><strong>Go 语言团队 (Golang)</strong></td><td align="left">走最高优先级的 URGENT 通道发布紧急版本（CVE-2026-111943），在底层直接拒绝包含这 8 把公钥的任何连接。</td><td align="left">全球无数互联网公司的后端服务器、云原生基础设施（如 Docker&#x2F;K8s 生态）。</td></tr></tbody></table><h3 id="真正可怕的暗雷：无法更新的“僵尸设备”"><a href="#真正可怕的暗雷：无法更新的“僵尸设备”" class="headerlink" title="真正可怕的暗雷：无法更新的“僵尸设备”"></a>真正可怕的暗雷：无法更新的“僵尸设备”</h3><p>看到科技巨头们光速打补丁，你可能会觉得危机已经解除了？<strong>恰恰相反，最恐怖的灾难才刚刚开始。</strong></p><p>你的日常手机和电脑浏览器会自动联网更新黑名单，但互联网的庞大底座是由无数<strong>“从不更新”</strong>的设备与环境构成的：</p><ul><li>出厂后固件就再也没升级过的智能电视、路由器、摄像头等物联网（IoT）设备；</li><li>企业内网里跑着老旧业务的 Docker 容器镜像（基础镜像里的 <code>ca-certificates</code> 停留在几年前）；</li><li>机房角落里被遗忘的 Linux 服务器；</li><li>开发者电脑上常年无人维护、静态编译的命令行工具（CLI）和自动化脚本。</li></ul><p>这些设备在出厂或构建的那一刻，就已经把 eMudhra 的根证书写死在了信任列表里，而且它们<strong>没有自动拉取证书黑名单（CRL&#x2F;OCSP）的能力</strong>。</p><p>这意味着，<strong>数百万台物联网设备、Docker 容器、被遗忘的 Linux 机器、无人维护的 CLI 工具等等，都将在未来几年甚至可能无限期地，被携带“合法安全签名”的恶意软件和中间人流量无情地入侵。</strong> 对黑客而言，这 8 把算出来的私钥不是一张限时体验卡，而是一把能长期打开无数老旧基础设施大门的永久万能钥匙。</p><hr><h2 id="五、-普通人与初级技术人员该做什么？"><a href="#五、-普通人与初级技术人员该做什么？" class="headerlink" title="五、 普通人与初级技术人员该做什么？"></a>五、 普通人与初级技术人员该做什么？</h2><p>这次事件给我们上了一堂生动的网络安全课：<strong>数字世界的信任是极其脆弱的，密码学算法本身固若金汤，但写代码和做配置的人却可能犯下最低级的错误。</strong></p><p>为了保护自己和公司的业务不受波及，建议立即采取以下行动：</p><ol><li><strong>普通用户：立即重启并更新你的浏览器和系统。</strong><br>去检查一下你的 Chrome、Edge、Firefox 或 Safari 是否有待重启的更新。虽然现代浏览器大多有自动后台推送黑名单的功能，但保持最新版本能确保那 8 把“假钥匙”在你的设备上彻底作废。如果近期上网看到浏览器弹出<strong>“您的连接不是私密连接”</strong>的红色拦截警告，<strong>千万不要点击“继续前往”</strong>。</li><li><strong>初级开发者 &#x2F; 运维人员：彻底排查后端环境与容器镜像。</strong><ul><li><strong>后端与依赖升级：</strong> 如果你的服务端或 CLI 工具使用了 Go 语言（Golang）编写并会主动发起外部 HTTPS 请求，或者在离线环境中使用了 Mozilla 的 <code>NSS</code> 库，请立刻升级到刚刚发布的紧急修复版本并<strong>重新编译部署</strong>。</li><li><strong>清理容器与老旧机器：</strong> 检查线上正在运行的 Docker 容器和 Linux 服务器，及时执行系统更新（如更新 <code>ca-certificates</code> 包）并重新构建基础镜像，避免它们成为上述永久暴露的“盲区”。</li><li><strong>排查自有域名：</strong> 检查公司业务是否采购过 <code>emSign</code>（eMudhra）签发的 SSL 证书。如果有，你的网站现在可能已经在用户的浏览器里报错瘫痪了，需立即更换为 Let’s Encrypt、DigiCert 或 Cloudflare 等其他机构的证书。</li></ul></li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;strong&gt;当你打开浏览器访问网上银行时，你怎么知道眼前这个页面是真的银行，而不是黑客精仿的钓鱼网站？&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;答案藏在浏览器地址栏旁边的安全认证机制里。最近爆发的 &lt;strong&gt;eMudhra（印度知名数字证书颁发机构，旗下品牌为 emSi</summary>
      
    
    
    
    <category term="笔记" scheme="https://ooo.run/categories/%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="HTTPS" scheme="https://ooo.run/tags/HTTPS/"/>
    
    <category term="网络安全" scheme="https://ooo.run/tags/%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8/"/>
    
    <category term="eMudhra" scheme="https://ooo.run/tags/eMudhra/"/>
    
    <category term="SSL证书" scheme="https://ooo.run/tags/SSL%E8%AF%81%E4%B9%A6/"/>
    
    <category term="漏洞分析" scheme="https://ooo.run/tags/%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/"/>
    
  </entry>
  
  <entry>
    <title>告别“抽卡”：为什么 p5.js + p5.brush 在 Claude 动态手绘视频圈彻底火了？</title>
    <link href="https://ooo.run/post/claude-p5js-p5brush-hand-painted-animation.html"/>
    <id>https://ooo.run/post/claude-p5js-p5brush-hand-painted-animation.html</id>
    <published>2026-10-19T07:50:57.000Z</published>
    <updated>2026-10-19T08:38:51.505Z</updated>
    
    <content type="html"><![CDATA[<p>当大多数人还在和文生视频模型较劲，为了控制角色动作和手绘笔触的一致性反复“抽卡”时，创意编程与 AI Agent 社区已经换了一条赛道：<strong>不靠扩散模型“猜”像素，而是让 Claude 直接写代码，“画”出每一帧手绘动画。</strong></p><p>近期，围绕 <strong>p5.js + p5.brush + Claude Code</strong> 的动态手绘视频工作流（以开源项目 <code>ClaudeAnimationBase</code> 及其衍生 Skills 为代表）在开发者与创作者圈子里迅速走红。只需对 Claude 说一句“做一支 15 秒小角色抓蝴蝶的手绘短片”，它就能包揽分镜设计、逐镜头代码绘制、自我审片，最终直接渲染输出一支带有水彩晕染、纸张肌理和抖动墨线的 MP4 视频。</p><p>这套组合究竟有什么魔力？它又是如何把冷冰冰的几何代码变成充满呼吸感的手绘动画的？</p><hr><h2 id="一、-黄金铁三角：它们各自扮演什么角色？"><a href="#一、-黄金铁三角：它们各自扮演什么角色？" class="headerlink" title="一、 黄金铁三角：它们各自扮演什么角色？"></a>一、 黄金铁三角：它们各自扮演什么角色？</h2><p>这套工作流的惊艳效果，源于三个核心组件的天作之合：</p><ul><li><strong>p5.js（创意编程的骨架）：</strong> 经典的 JavaScript 创意编程库，建立在 HTML5 Canvas 与 WebGL 之上。它负责管理画布、时间轴、物理运动、摄像机推拉以及每一帧的数学计算，让动画里的每一个元素都成为<strong>时间的纯函数（Pure function of time）</strong>。</li><li><strong>p5.brush（注入灵魂的手绘皮肤）：</strong> 由 Alejandro Campos Uribe（<code>@acamposuribe</code>）开发的 p5.js 扩展库。标准的 Canvas 绘图往往带着一股“矢量塑料感”，而 <code>p5.brush</code> 在 WebGL 底层模拟了真实物理笔触——<strong>水彩的多层晕染与出血（bleed）、炭笔的颗粒感、马克笔的叠加、钢笔的墨线以及画布本身的纸张纹理</strong>。</li><li><strong>Claude Code（懂视听语言的“总导演”）：</strong> 以 Claude（尤其是高推理能力的 Opus 模型）为核心的 Coding Agent。相比于让人头秃的 WebGL 坐标转换和参数调试，Claude 极其擅长理解结构化的 API 与空间几何关系。给它一套审美规范与动画法则，它就能直接用代码把分镜翻译成画面。</li></ul><hr><h2 id="二、-为什么“代码生成手绘动画”能吊打传统-AI-抽卡？"><a href="#二、-为什么“代码生成手绘动画”能吊打传统-AI-抽卡？" class="headerlink" title="二、 为什么“代码生成手绘动画”能吊打传统 AI 抽卡？"></a>二、 为什么“代码生成手绘动画”能吊打传统 AI 抽卡？</h2><p>传统文生视频模型在制作 2D 手绘风格时，常常面临线条闪烁失真、角色跨镜头崩坏、局部细节无法微调等痛点。而 <code>p5.js + p5.brush</code> 的代码渲染管线，精准命中了创作者的核心诉求：</p><table><thead><tr><th align="left">对比维度</th><th align="left">传统文生视频模型（扩散模型）</th><th align="left">Claude + p5.js + p5.brush 工作流</th></tr></thead><tbody><tr><td align="left"><strong>风格与角色一致性</strong></td><td align="left">跨镜头容易“变脸”，水彩肌理容易糊成色块</td><td align="left"><strong>100% 绝对一致</strong>，角色结构与笔触参数由代码锁定</td></tr><tr><td align="left"><strong>动作与节奏控制</strong></td><td align="left">很难精准卡点，动作物理逻辑常有违和感</td><td align="left"><strong>精确到毫秒&#x2F;帧</strong>，完美对齐音乐节拍（BPM）与歌词</td></tr><tr><td align="left"><strong>可修改性（迭代成本）</strong></td><td align="left">不满意只能改 Prompt 重新抽卡，全凭运气</td><td align="left"><strong>指哪打哪</strong>，直接改某一行代码的坐标、颜色或表情参数</td></tr><tr><td align="left"><strong>手绘质感（生命力）</strong></td><td align="left">往往是平滑但僵硬的滤镜感</td><td align="left">原生支持<strong>每秒 12 次重绘抖动线（Boiling lines）</strong>，还原赛璐珞逐帧手绘感</td></tr></tbody></table><hr><h2 id="三、-揭秘爆火背后的核心机制：如何让代码“有手绘的生命力”？"><a href="#三、-揭秘爆火背后的核心机制：如何让代码“有手绘的生命力”？" class="headerlink" title="三、 揭秘爆火背后的核心机制：如何让代码“有手绘的生命力”？"></a>三、 揭秘爆火背后的核心机制：如何让代码“有手绘的生命力”？</h2><p>这股风潮的引爆点，很大程度上归功于开源项目 <strong>ClaudeAnimationBase</strong>（由 John Heibel 发起）以及社区随后衍生出的各类 <code>painted-animation</code> Claude Skills。拆解这套工作流的底层设计，会发现它之所以好看，是因为把传统手绘动画的“行业黑话”写进了代码规则里：</p><h3 id="1-灵魂抖动线（Boiling-Linework）"><a href="#1-灵魂抖动线（Boiling-Linework）" class="headerlink" title="1. 灵魂抖动线（Boiling Linework）"></a>1. 灵魂抖动线（Boiling Linework）</h3><p>传统手绘动画为什么看起来“活”？因为画师每一帧重描轮廓时，手部都会有细微的偏差。在这套引擎中，虽然主画面按高帧率流畅运行，但 <code>p5.brush</code> 的外轮廓墨线被设定为<strong>每秒重新随机采样绘制 12 次</strong>（利用受控的随机数种子 Seed）。这种微小的笔触抖动，瞬间抹去了计算机图形的冰冷感。</p><h3 id="2-把迪士尼动画法则写进-Prompt-指南"><a href="#2-把迪士尼动画法则写进-Prompt-指南" class="headerlink" title="2. 把迪士尼动画法则写进 Prompt 指南"></a>2. 把迪士尼动画法则写进 Prompt 指南</h3><p>在项目的核心大脑 <code>ANIMATION_GUIDE.md</code> 中，并没有堆砌复杂的算法，而是给 Claude 制定了严格的动画师铁律：</p><ul><li><strong>角色会演戏：</strong> 任何动作不能是匀速平移，必须包含<strong>预备动作（Anticipation）、反应（Reaction）和回弹（Overshoot&#x2F;Settle）</strong>。</li><li><strong>拒绝空镜：</strong> 每个镜头都必须有事件发生，镜头切换采用极具手绘感的“画笔刷过（Brush-wipe）”转场。</li><li><strong>情绪组件化：</strong> 比如内置的吉祥物角色 Clawd，提前封装了多角度视图与 31 种生动的戏剧化情绪（眼神、嘴型、肢体微动作），Claude 像搭积木一样调用即可完成细腻的表演。</li></ul><h3 id="3-“渲染-看片-自检”的闭环（Render-and-Look-Loop）"><a href="#3-“渲染-看片-自检”的闭环（Render-and-Look-Loop）" class="headerlink" title="3. “渲染-看片-自检”的闭环（Render-and-Look Loop）"></a>3. “渲染-看片-自检”的闭环（Render-and-Look Loop）</h3><p>以前让大模型写前端画图，最大的痛点是模型“看不见”自己画了什么，经常出现元素重叠或跑出画布。<br>现在的 Claude Code 动画工作流配备了基于无头浏览器（Headless Chrome）的渲染脚本 <code>render.mjs</code>。Claude 写完一个镜头的代码后，会先自动渲染出一张<strong>缩略图印样（Contact Sheet &#x2F; Frame Strip）</strong>，用自己的多模态视觉能力“看一眼”画面构图和动作连贯性，发现穿模或构图不佳就自己改代码，全部审核通过后，才调用 <code>ffmpeg</code> 合成最终的 MP4 视频。</p><hr><h2 id="四、-从零体验：如何用-Claude-跑通你的第一支手绘短片？"><a href="#四、-从零体验：如何用-Claude-跑通你的第一支手绘短片？" class="headerlink" title="四、 从零体验：如何用 Claude 跑通你的第一支手绘短片？"></a>四、 从零体验：如何用 Claude 跑通你的第一支手绘短片？</h2><p>如果你想立刻上手体验这套丝滑的工作流，只需要准备好本地环境（<strong>Node.js、Google Chrome、ffmpeg</strong> 以及 <strong>Claude Code</strong>）。</p><p><strong>第一步：拉取开源脚手架或安装 Skill</strong><br>你可以直接克隆原版基础库：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/JohnHeibel/ClaudeAnimationBase.git</span><br><span class="line"><span class="built_in">cd</span> ClaudeAnimationBase</span><br></pre></td></tr></table></figure><p>或者在支持插件生态的环境中，直接安装社区封装好的手绘动画 Skill（如 <code>opus-video-skills</code> 中的 <code>painted-animation</code> 或支持配乐对齐的 <code>hiapi-hand-painted-animation-skill</code>）。</p><p><strong>第二步：用自然语言向 Claude 下达导演指令</strong><br>在项目目录下启动 <code>claude</code>，直接输入你的创意：</p><blockquote><p><em>“先阅读 <code>ANIMATION_GUIDE.md</code>，然后帮我制作一支 15 秒的手绘短片：Clawd 在开满野花的草地上试图抓一只蝴蝶，结果扑了个空摔倒，蝴蝶最后停在了它的鼻尖上。”</em></p></blockquote><p><strong>第三步：见证全自动片场运转</strong><br>接下来你只需要喝杯咖啡，看着终端里的 Claude 自动完成以下流水线：</p><ol><li><strong>编写分镜脚本（Storyboard）：</strong> 规划 3~4 个镜头的景别、时长与情绪转折。</li><li><strong>编写镜头代码：</strong> 调用 <code>p5.brush</code> 的水彩笔刷涂抹背景与天空，用墨线勾勒角色与草地。</li><li><strong>自检与微调：</strong> 生成分镜预览图，自我检查色彩层次与角色位置。</li><li><strong>渲染输出：</strong> 将序列帧编码输出为 <code>out/video.mp4</code>。</li></ol><p>测试效果，使用 Claude Code 耗时 33 分钟，模型为 Claude Opus 5.5 xhigh，等价 API 费用 $6.78，成品：</p><video controls width="100%">  <source src="https://img.nep.me/ooo/p5-opus-butterfly.mp4" type="video/mp4">  您的浏览器不支持视频播放。</video><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Total cost:            $6.78</span><br><span class="line">Total duration (API):  22m 47s</span><br><span class="line">Total duration (wall): 33m 15s</span><br></pre></td></tr></table></figure><blockquote><p><strong>硬件小贴士：</strong> <code>p5.brush</code> 的水彩晕染（Watercolour fills）在底层需要进行大量的多边形与混合计算。如果没有独立显卡（使用核显渲染），单帧渲染可能会需要几秒钟。你可以在 Prompt 里提醒 Claude：“在核显上运行，请尽量用平涂加排线（Hatching）替代大面积重度水彩晕染以加快渲染速度。”</p></blockquote><hr><h2 id="五、-写在最后：程序化生成艺术的文艺复兴"><a href="#五、-写在最后：程序化生成艺术的文艺复兴" class="headerlink" title="五、 写在最后：程序化生成艺术的文艺复兴"></a>五、 写在最后：程序化生成艺术的文艺复兴</h2><p><code>p5.js</code> 与 <code>p5.brush</code> 并不是今天才出现的新技术，但 Claude Code 的成熟，彻底抹平了创意编程那道陡峭的数学与 API 门槛。</p><p>它向我们展示了一种全新的 AI 创作范式：<strong>AI 不一定非要直接接管最终的像素生成；当 AI 成为连接人类审美意图与确定性图形引擎（Procedural Engine）的桥梁时，我们既拥有了大模型的无限创意，又夺回了作为创作者对每一根线条、每一帧节奏的绝对控制权。</strong></p><p>无论你是想做独立音乐的卡点歌词 MV、科普视频的趣味手绘插画，还是单纯想把脑海里的小故事变成动画，现在，你的代码编辑器就是最棒的水彩画板。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;当大多数人还在和文生视频模型较劲，为了控制角色动作和手绘笔触的一致性反复“抽卡”时，创意编程与 AI Agent 社区已经换了一条赛道：&lt;strong&gt;不靠扩散模型“猜”像素，而是让 Claude 直接写代码，“画”出每一帧手绘动画。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;近期，</summary>
      
    
    
    
    <category term="笔记" scheme="https://ooo.run/categories/%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="Claude Code" scheme="https://ooo.run/tags/Claude-Code/"/>
    
    <category term="p5.js" scheme="https://ooo.run/tags/p5-js/"/>
    
    <category term="p5.brush" scheme="https://ooo.run/tags/p5-brush/"/>
    
    <category term="AI Video" scheme="https://ooo.run/tags/AI-Video/"/>
    
    <category term="动态视频" scheme="https://ooo.run/tags/%E5%8A%A8%E6%80%81%E8%A7%86%E9%A2%91/"/>
    
  </entry>
  
  <entry>
    <title>AI 动画制作 Skill 分享：用代码生成动态视频与手绘动画</title>
    <link href="https://ooo.run/post/ai-animation-skills-code-generated-motion-videos.html"/>
    <id>https://ooo.run/post/ai-animation-skills-code-generated-motion-videos.html</id>
    <published>2026-10-18T06:56:26.000Z</published>
    <updated>2026-10-19T04:01:04.165Z</updated>
    
    <content type="html"><![CDATA[<h1 id="告别逐帧渲染：当大模型用代码直接“写”出动态视频与手绘动画"><a href="#告别逐帧渲染：当大模型用代码直接“写”出动态视频与手绘动画" class="headerlink" title="告别逐帧渲染：当大模型用代码直接“写”出动态视频与手绘动画"></a>告别逐帧渲染：当大模型用代码直接“写”出动态视频与手绘动画</h1><p>提到 AI 生成视频，大多数人的第一反应是基于扩散模型（Diffusion）的像素级渲染——输入一段提示词，等待几分钟，然后祈祷生成的画面里人物手指数量正常、文字没有扭曲成乱码。在影视特效或实景空镜领域，像素生成确实惊艳；但在<strong>动态图形设计（Motion Graphics, MG）</strong>、<strong>技术科普动画</strong>以及<strong>叙事型绘本视频</strong>中，设计师和创作者真正需要的是精准的排版、丝滑的缓动曲线（Easing）、清晰的矢量线条，以及随时可微调的分镜结构。</p><p>近期在 GitHub 上走红的两个开源项目——<a href="https://github.com/Vincentwei1021/mg-styles-15"><strong>mg-styles-15</strong></a> 与 <a href="https://github.com/lhlGitHub/hand-drawn-storybook-animation-skill"><strong>hand-drawn-storybook-animation-skill</strong></a>——展示了一条截然不同的技术路线：<strong>可编程动态视频（Programmable Motion Video）</strong>。它们不再让大模型去“猜”每一帧的像素，而是通过封装完善的 Agent Skill 与提示词工程，让大模型直接编写前端与图形代码，在浏览器中实时渲染出达到商用和叙事水准的完整动画。</p><blockquote><p>这些 Skill 除了 Opus 5.5 ，其他模型也可以使用，不过效果将因模型而产生差异，可以用于对比不同模型的能力。</p></blockquote><hr><h2 id="一、-为什么“代码生成视频”正在成为新范式？"><a href="#一、-为什么“代码生成视频”正在成为新范式？" class="headerlink" title="一、 为什么“代码生成视频”正在成为新范式？"></a>一、 为什么“代码生成视频”正在成为新范式？</h2><p>在传统的动画制作流程中，哪怕是一个 10 秒的片头或几分钟的科普绘本，也需要经历写脚本、画分镜、矢量绘图、AE 关键帧绑定、配音对齐和合成剪辑。而用传统文生视频大模型来做这类内容，往往会遇到三大痛点：</p><ol><li><strong>文字与排版失控</strong>：无法精准渲染中英文标题、数据图表或 UI 界面。</li><li><strong>黑盒不可编辑</strong>：如果客户或自己觉得第 3 秒的某个元素颜色不对、节奏慢了半拍，只能重新抽卡，无法像改代码一样精准微调。</li><li><strong>音画脱节</strong>：生成的画面没有底层时间轴逻辑，配乐、音效与动效卡点全靠后期手动硬凑。</li></ol><p>而 <strong>LLM + Agent Skill（技能包）</strong> 的思路，则是将专业动画师的审美规范、物理运动规律、分镜逻辑和音频合成 API 封装成标准化的上下文规则。大模型化身全栈动画工程师，直接调用 Canvas、SVG、WebGL 以及 Web Audio API，把“想法”编译成可交互、可录制、可二次修改的动态视频。</p><hr><h2 id="三、-两大标杆开源项目深度解析"><a href="#三、-两大标杆开源项目深度解析" class="headerlink" title="三、 两大标杆开源项目深度解析"></a>三、 两大标杆开源项目深度解析</h2><p>这三个项目恰好代表了“代码生成视频”从<strong>高燃视觉片段</strong>到<strong>垂直绘本工作流</strong>，再到<strong>全能型微电影制片厂</strong>的完整生态演进：</p><table><thead><tr><th align="left">维度</th><th align="left"><code>mg-styles-15</code> (Vincentwei1021)</th><th align="left"><code>hand-drawn-storybook-animation-skill</code> (lhlGitHub)</th><th align="left"><code>lemo-opuscar</code> (lemomo-ai)</th></tr></thead><tbody><tr><td align="left"><strong>核心定位</strong></td><td align="left">商用水准的 15 种 MG 动态设计风格库与提示词基准</td><td align="left">全流程手绘水彩绘本动画 Claude Skill 制作工作流</td><td align="left">纯代码驱动的本地微电影制片厂 Skill（含 43+ 核心风格与 OPUSCAR 98 画廊）</td></tr><tr><td align="left"><strong>视觉呈现</strong></td><td align="left">扁平矢量、等轴 2.5D、3D 渲染、赛博朋克 HUD 等 15 种风格</td><td align="left">笔触级动态手绘、水彩晕染、真实纸张翻页与电影运镜</td><td align="left">涵盖油画厚涂、水彩、东亚传统美学等数十种 2D&#x2F;3D 艺术电影风格</td></tr><tr><td align="left"><strong>音频与混音</strong></td><td align="left">纯代码程序化生成配乐（BGM）与动作同步音效（SFX）</td><td align="left">自动生成配乐 + 接入 TTS（如豆包语音）实现逐句旁白对齐</td><td align="left">完整的声音指导体系：支持语音旁白、原创配乐与多轨混音（Mixing）</td></tr><tr><td align="left"><strong>工程架构</strong></td><td align="left">单文件&#x2F;纯前端源码 + 结构化高审美 Prompt 模板</td><td align="left">浏览器实时笔触绘制 + 分镜脚本驱动</td><td align="left">三层工业级架构：<code>DIRECTOR.md</code>（导演）+ <code>TECHNIQUE.md</code>（工程）+ <code>STYLE.md</code>（美术）</td></tr></tbody></table><hr><h3 id="1-mg-styles-15：15-种商用水准-MG-风格的“提示词与源码字典”"><a href="#1-mg-styles-15：15-种商用水准-MG-风格的“提示词与源码字典”" class="headerlink" title="1. mg-styles-15：15 种商用水准 MG 风格的“提示词与源码字典”"></a>1. <code>mg-styles-15</code>：15 种商用水准 MG 风格的“提示词与源码字典”</h3><blockquote><p>15 种 MG 动态设计风格，每种一支 10 秒成片，全部由 Claude Opus 5.5 写代码做出来。</p></blockquote><p><a href="https://github.com/Vincentwei1021/mg-styles-15"><strong>Vincentwei1021&#x2F;mg-styles-15</strong></a> 是一个极具视觉冲击力的展示与开源库（配套在线预览站：<code>vincentwei1021.github.io/mg-styles-15</code>）。作者盘点了 <strong>15 种达到准商用水准的 MG 动画风格</strong>，每支 10 秒的成片完完全全由 AI 根据一段提示词编写代码生成。</p><p>视频预览地址：<a href="https://vincentwei1021.github.io/mg-styles-15/">https://vincentwei1021.github.io/mg-styles-15/</a></p><p><img src="https://img.nep.me/ooo/mg15.webp" alt="mg15.png"></p><p>更硬核的是，这些片子不仅<strong>画面与动画</strong>由代码驱动，连<strong>背景配乐和卡点音效（SFX）也全部由代码合成</strong>，没有任何外部素材拼接。项目完整公开了每种风格的成片预览、风格设计说明、完整 Prompt 以及全部源码：</p><ul><li><strong>多元视觉美学全覆盖</strong>：项目中包含<strong>逐帧手绘（Frame-by-Frame）</strong>、<strong>等轴 2.5D（Isometric 2.5D）</strong>、<strong>扁平矢量（Flat Vector）</strong>、<strong>线条动画（Line Art）</strong>、<strong>3D 渲染（3D Render）</strong>、<strong>形变动画（Shape Morph）</strong>、<strong>贴纸风科普（Sticker Explainer）</strong>以及<strong>赛博朋克 HUD（Cyberpunk HUD）</strong>等 15 种截然不同的动态视觉语言。</li><li><strong>提示词即生产力</strong>：以往我们让大模型写动画代码，出来的往往是生硬的 <code>linear</code> 位移和单调的色块。<code>mg-styles-15</code> 的核心贡献在于，它展示了如何用精准的设计语言（色彩系统、运动节奏、图层叠加关系、物理回弹约束）去编写 Prompt。你可以直接复制项目中的提示词模板，替换自己的主题文案，立刻复刻出同等质感的宣传片头或产品演示动画。</li></ul><hr><h3 id="2-hand-drawn-storybook-animation-skill：在浏览器里“现场作画”的叙事动画工作流"><a href="#2-hand-drawn-storybook-animation-skill：在浏览器里“现场作画”的叙事动画工作流" class="headerlink" title="2. hand-drawn-storybook-animation-skill：在浏览器里“现场作画”的叙事动画工作流"></a>2. <code>hand-drawn-storybook-animation-skill</code>：在浏览器里“现场作画”的叙事动画工作流</h3><p>如果说 <code>mg-styles-15</code> 解决了“10 秒高燃视觉怎么写”的问题，那么 <a href="https://github.com/lhlGitHub/hand-drawn-storybook-animation-skill"><strong>lhlGitHub&#x2F;hand-drawn-storybook-animation-skill</strong></a> 则解决了一个更宏大的命题：<strong>如何让一个不会画画、不会剪辑的普通创作者，把一篇故事或科普长文变成一部长达数分钟、有声有色的完整动画片？</strong></p><p><img src="https://img.nep.me/ooo/hand-style.webp" alt="hand-style.png"></p><p>这是一个专为 Claude Code 等智能体环境打造的开源 Skill。当你把它挂载到你的大模型工作流中时，AI 不再只是吐出一段静态代码，而是接管了从编剧、原画、分镜导演到后期录音合成的完整管线：</p><ul><li><strong>真正的“动”——笔触级实时绘制</strong>：它不是把一张静态图做简单的平移缩放（Ken Burns 效应），而是在浏览器里<strong>一笔一笔把画面实时画出来</strong>。结合水彩上色渲染，观众能看到线条生长、色彩浮现的真实手绘过程。</li><li><strong>电影级分镜与物理翻页</strong>：Skill 内部定义了严谨的镜头调度逻辑（推拉摇移、局部特写）以及逼真的<strong>拟物翻页效果</strong>，转场就像在翻阅一本真正放在桌上的实体水彩绘本。</li><li><strong>配音配乐一条龙合成</strong>：动画的灵魂在于声音。该 Skill 支持自动生成契合故事氛围的背景音乐，并集成了自然流畅的语音合成（如豆包 TTS 旁白）。系统会自动根据每一句台词的时长计算动画节拍，做到旁白念到哪里、画笔就画到哪里，实现严丝合缝的音画同步。</li><li><strong>极简的集成方式</strong>：对于习惯使用 Claude Code 的开发者或创作者，只需将仓库克隆下来，把技能目录复制到本地的 <code>.claude/skills/</code> 目录下即可一键激活。输入一段故事构想，剩下的分镜拆解、代码编写、音频对齐全部由 Agent 自动闭环。</li></ul><h3 id="3-lemo-opuscar：把大模型变成你的“私人微电影制片厂”"><a href="#3-lemo-opuscar：把大模型变成你的“私人微电影制片厂”" class="headerlink" title="3. lemo-opuscar：把大模型变成你的“私人微电影制片厂”"></a>3. <code>lemo-opuscar</code>：把大模型变成你的“私人微电影制片厂”</h3><p>如果既想要 <code>mg-styles-15</code> 丰富的风格库，又想要 <code>storybook-skill</code> 的完整叙事与成片管线，那么 <a href="https://github.com/lemomo-ai/lemo-opuscar"><strong>lemomo-ai&#x2F;lemo-opuscar</strong></a> 就是将这两者推向极致的集大成者。</p><p><img src="https://img.nep.me/ooo/lemo-opuscar-cover.webp" alt="lemo-opuscar-cover.jpg"></p><p><code>lemo-opuscar</code> 是一个专为 Claude Code、Codex CLI 等编程智能体打造的开源微电影制作 Skill。它在完全不使用任何视频生成大模型的前提下，仅凭代码就构建了 <strong>43+ 种可直接复用的电影风格库（更包含扩展的 OPUSCAR 98 全景风格画廊）</strong>。“选一个风格，带上你自己的故事，让你的编程 Agent 来当导演”是它的核心设计哲学：</p><ul><li><strong>三层解耦的“制片厂”架构</strong>：为什么 <code>lemo-opuscar</code> 拍出来的代码短片没有“PPT 感”，反而充满电影质感？因为它让 Agent 在动手写代码前，先阅读三份核心指导手册：<ol><li><strong><code>DIRECTOR.md</code>（导演手册）</strong>：指导 Agent 如何讲故事、把控声音与画面节奏、设计摄影机运动（Camera）、调度角色表演（Performance）以及进行自我质量检查。</li><li><strong><code>TECHNIQUE.md</code>（技术工程手册）</strong>：解决底层构建问题，涵盖逐帧渲染（Frame-by-frame rendering）、人声合成、配乐生成与多轨混音（Mixing），最终通过 Node.js、Python 与 FFmpeg 直接在本地输出 1920×1080、24fps 的标准电影级视频文件。</li><li><strong><code>styles/&lt;style&gt;/STYLE.md</code>（美术与听觉设定集）</strong>：定义特定风格的视觉笔触与听觉氛围（涵盖油画厚涂 Impasto Oil Painting、手绘水彩、东亚传统美学等 2D&#x2F;3D 风格），实现“视觉风格高度固定，故事内容完全自由”。</li></ol></li><li><strong>交互式导演工作流（Storyboard First）</strong>：你只需用自然语言下达指令（例如：<em>“用水彩风格拍一部 45 秒关于我家咖啡庄园的短片，温暖的女声旁白”</em>）。Agent 会在开拍前主动向你确认一次细节与素材偏好，并询问是否需要先看分镜（Storyboard）。如果你选择“是”，它会先用真实的目标风格渲染出关键帧分镜供你审阅，确认无误后再自动耗时 30–60 分钟完成整部成片的逐帧渲染与混音合成。</li><li><strong>一键插件化安装</strong>：支持直接通过 Claude 插件市场安装（<code>claude plugin marketplace add lemomo-ai/lemo-opuscar</code>），也可以直接将 <code>plugin/skills/lemo-opuscar/</code> 复制到其他编程 Agent 的技能目录中即插即用。</li></ul><p>视频风格预览： <a href="https://lemomo-ai.github.io/lemo-opuscar/">https://lemomo-ai.github.io/lemo-opuscar/</a></p><hr><h2 id="三、-解剖底层逻辑：一个优秀的“动态视频-Skill”是如何工作的？"><a href="#三、-解剖底层逻辑：一个优秀的“动态视频-Skill”是如何工作的？" class="headerlink" title="三、 解剖底层逻辑：一个优秀的“动态视频 Skill”是如何工作的？"></a>三、 解剖底层逻辑：一个优秀的“动态视频 Skill”是如何工作的？</h2><p>把这两个项目放在一起看，我们会发现“大模型制作动态视频 Skill”背后有一套非常清晰的工程架构。如果你也想基于这些项目定制自己的视频生成 Skill，核心在于抓准以下四个层面：</p><h3 id="1-视觉与动效的原语抽象（Motion-Primitives）"><a href="#1-视觉与动效的原语抽象（Motion-Primitives）" class="headerlink" title="1. 视觉与动效的原语抽象（Motion Primitives）"></a>1. 视觉与动效的原语抽象（Motion Primitives）</h3><p>大模型直接写底层图形代码容易陷入细节泥潭。优秀的动画 Skill 会在指令或脚手架中规范好动效原语——比如强制规定使用特定的三次贝塞尔曲线（Cubic Bezier）而非默认线性过渡；定义好 SVG <code>stroke-dashoffset</code> 的路径生长计算公式；或者预设好噪点纹理滤镜（SVG Filter）来模拟纸张颗粒感与手绘抖动。</p><h3 id="2-时间轴与状态机驱动（Timeline-State-Machine）"><a href="#2-时间轴与状态机驱动（Timeline-State-Machine）" class="headerlink" title="2. 时间轴与状态机驱动（Timeline &amp; State Machine）"></a>2. 时间轴与状态机驱动（Timeline &amp; State Machine）</h3><p>视频本质上是时间的艺术。在 <code>hand-drawn-storybook-animation-skill</code> 这类长视频技能中，核心架构往往围绕一个<strong>主时间轴（Master Timeline）</strong>展开。Skill 会指导大模型先将文本拆解为结构化的分镜脚本（Scene JSON），每个 Scene 包含台词、预计时长、镜头运动参数和绘制元素序列，再由前端渲染引擎按状态机顺序驱动播放。</p><h3 id="3-程序化音频合成（Procedural-Audio-TTS-Alignment）"><a href="#3-程序化音频合成（Procedural-Audio-TTS-Alignment）" class="headerlink" title="3. 程序化音频合成（Procedural Audio &amp; TTS Alignment）"></a>3. 程序化音频合成（Procedural Audio &amp; TTS Alignment）</h3><p>为什么这两个项目都能摆脱外部剪辑软件？秘密在于将音频也纳入了代码控制：</p><ul><li><strong>音效与配乐</strong>：利用浏览器的 <code>Web Audio API</code>（或 Tone.js 等合成器库），大模型可以通过调节振荡器（Oscillator）、包络（ADSR）和滤波器，用纯代码写出转场嗖嗖声、按键音甚至环境极简旋律。</li><li><strong>语音驱动时间轴</strong>：通过脚本调用 TTS 接口生成音频文件后，先读取音频的精确毫秒数，再反推当前分镜内 SVG 笔触绘制的持续时间（Duration），从而在代码层面彻底消灭“音画不同步”的顽疾。</li></ul><h3 id="4-确定性录制与导出（Deterministic-Rendering）"><a href="#4-确定性录制与导出（Deterministic-Rendering）" class="headerlink" title="4. 确定性录制与导出（Deterministic Rendering）"></a>4. 确定性录制与导出（Deterministic Rendering）</h3><p>当浏览器里的画面和声音都准备就绪后，配合无头浏览器（如 Playwright &#x2F; Puppeteer）或画布捕获工具，即可将实时运行的网页捕获并编码输出为高帧率的 MP4 视频文件，直接用于社交媒体发布。</p><hr><h2 id="四、-结语：知识传播与个人表达的“动画时代”"><a href="#四、-结语：知识传播与个人表达的“动画时代”" class="headerlink" title="四、 结语：知识传播与个人表达的“动画时代”"></a>四、 结语：知识传播与个人表达的“动画时代”</h2><p>过去，把一个复杂的知识点、一段睡前童话或一个产品创意做成动画，是一支专业团队忙活好几周的专利；因此，绝大多数好内容最终只能停留在枯燥的文字里。</p><p><code>mg-styles-15</code> 和 <code>hand-drawn-storybook-animation-skill</code> 的出现向我们证明了：<strong>当大模型的能力被结构化的 Skill 驯服后，代码就成了最强大的画笔和摄影机。</strong> <code>mg-styles-15</code> 为我们提供了商业级动态设计的提示词美学标准，而 <code>hand-drawn-storybook-animation-skill</code> 则跑通了从文本到叙事成片的自动化工业管线。</p><p>无论你是想为自己的独立产品制作一段抓人眼球的 Promo 短片，还是想把深奥的技术博客转化为通俗易懂的手绘科普视频，都不妨把这两个仓库 Clone 下来，亲手体验一下用 Prompt 和 Skill “编译”出一部动画电影的乐趣。</p><hr><p><strong>相关链接：</strong></p><ul><li><strong>mg-styles-15 仓库</strong>：<a href="https://github.com/Vincentwei1021/mg-styles-15">https://github.com/Vincentwei1021/mg-styles-15</a></li><li><strong>hand-drawn-storybook-animation-skill 仓库</strong>：<a href="https://github.com/lhlGitHub/hand-drawn-storybook-animation-skill">https://github.com/lhlGitHub/hand-drawn-storybook-animation-skill</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;告别逐帧渲染：当大模型用代码直接“写”出动态视频与手绘动画&quot;&gt;&lt;a href=&quot;#告别逐帧渲染：当大模型用代码直接“写”出动态视频与手绘动画&quot; class=&quot;headerlink&quot; title=&quot;告别逐帧渲染：当大模型用代码直接“写”出动态视频与手绘动画&quot;&gt;&lt;/a</summary>
      
    
    
    
    <category term="工具资源" scheme="https://ooo.run/categories/%E5%B7%A5%E5%85%B7%E8%B5%84%E6%BA%90/"/>
    
    
    <category term="AI" scheme="https://ooo.run/tags/AI/"/>
    
    <category term="Claude" scheme="https://ooo.run/tags/Claude/"/>
    
    <category term="Opus 5.5" scheme="https://ooo.run/tags/Opus-5-5/"/>
    
    <category term="动画制作" scheme="https://ooo.run/tags/%E5%8A%A8%E7%94%BB%E5%88%B6%E4%BD%9C/"/>
    
  </entry>
  
  <entry>
    <title>Claude Opus 5.5 视频生成指南：从底层原理、技术栈选型到工程化 Prompt 实践</title>
    <link href="https://ooo.run/post/use-opus-make-videos.html"/>
    <id>https://ooo.run/post/use-opus-make-videos.html</id>
    <published>2026-10-18T04:54:23.000Z</published>
    <updated>2026-10-18T05:24:12.876Z</updated>
    
    <content type="html"><![CDATA[<p>当提到使用 Claude Opus 5.5 制作视频时，一个常见的误区是将其等同于 Sora 或 Runway 等端到端的扩散视频生成模型（Diffusion Video Models）。实际上，Opus 5.5 作为多模态大语言模型，具备文本与图像理解能力，但其输出模态依然严格受限于<strong>文本（代码）</strong>。</p><p>那么，Opus 5.5 生成的高水准动态设计（Motion Design）视频从何而来？答案是<strong>程序化生成（Procedural Generation）与无头渲染管线（Headless Rendering Pipeline）</strong>。</p><p>本文将系统拆解 Opus 5.5 制作视频的底层工程逻辑、7 大核心渲染技术栈、5 个代表性实战案例的架构与 Prompt，并提供一套可直接复用的工业级 XML 提示词框架与自动化工作流。</p><hr><h2 id="一、-底层原理：基于时间函数的确定性渲染"><a href="#一、-底层原理：基于时间函数的确定性渲染" class="headerlink" title="一、 底层原理：基于时间函数的确定性渲染"></a>一、 底层原理：基于时间函数的确定性渲染</h2><p>传统手翻书动画（Flipbook）的原理是在每一页绘制微小的姿态变化，通过快速翻动形成视觉暂留。代码生成视频在工程上遵循完全一致的逻辑，核心在于构建一个<strong>确定性的时间渲染函数（Deterministic Time-step Function）</strong>。</p><p>整个自动化生成管线分为三个阶段：</p><ol><li><strong>状态函数构建</strong>：Opus 5.5 编写前端或图形代码，并在全局暴露一个基于时间的纯函数（如 <code>window.render(t)</code> 或 <code>seek(t)</code>）。向该函数传入任意时间戳 $t$（或帧序号），程序即可实时计算出该时刻所有视觉元素的精确状态（坐标、形变、色彩、光影）并完成单帧绘制。</li><li><strong>无头浏览器逐帧采样</strong>：使用 <strong>Playwright</strong> 等自动化测试工具在后台启动无头浏览器（Headless Browser），按照目标帧率（如 24 FPS 或 60 FPS）步进调用渲染函数，并将每一帧画面截取为无损图像序列。</li><li><strong>音画合成与编码</strong>：在音频侧，可通过 Python 的 <code>NumPy</code> 和 <code>SciPy</code> 直接进行数字信号处理（DSP），计算正弦波、方波及包络线来程序化合成鼓点、贝斯、合成器配乐与 UI 音效；最后调用 <strong>FFmpeg</strong> 将数千张图像序列与音频流混流编码，输出标准 MP4 文件。</li></ol><hr><h2 id="二、-视觉渲染技术栈：7-类核心方案选型"><a href="#二、-视觉渲染技术栈：7-类核心方案选型" class="headerlink" title="二、 视觉渲染技术栈：7 类核心方案选型"></a>二、 视觉渲染技术栈：7 类核心方案选型</h2><p>无论是原生代码构建还是调用成熟框架，程序化视频的核心都在于渲染引擎的选择。根据目标视觉风格，可将主流方案划分为以下 7 类：</p><table><thead><tr><th align="left">方案名称</th><th align="left">核心技术定位</th><th align="left">适用视觉风格与场景</th><th align="left">工程优势与局限</th></tr></thead><tbody><tr><td align="left"><strong>1. JS + Canvas 2D</strong></td><td align="left">2D 位图画布 API</td><td align="left">像素艺术（Pixel Art）、扁平插画、基础几何动效、2D 粒子</td><td align="left">零依赖、渲染极快；适合精细控制单个像素，但缺乏原生的 3D 与复杂光影支持。</td></tr><tr><td align="left"><strong>2. HTML &#x2F; CSS &#x2F; SVG</strong></td><td align="left">DOM 排版与矢量图形</td><td align="left">SaaS 产品宣传片、高保真 UI 交互演示、动态排版（Kinetic Typography）</td><td align="left">天然支持现代网页的圆角、阴影、弹性布局与无损矢量曲线，丝滑度极高。</td></tr><tr><td align="left"><strong>3. WebGL Shader</strong></td><td align="left">GPU 逐像素着色器</td><td align="left">复古 CRT 扫描线与曲面畸变、胶片颗粒、流体反光、赛博发光粒子</td><td align="left">直接调用显卡算力计算单像素颜色，质感极佳；常作为后处理层叠加在 Canvas 之上。</td></tr><tr><td align="left"><strong>4. Three.js</strong></td><td align="left">WebGL 3D 引擎封装</td><td align="left">3D 空间运镜、产品 360° 环绕、三维粒子云、体素（Voxel）小镇</td><td align="left">支持完整的网格、材质、灯光与摄像机推拉摇移；纯代码仅适合基础几何体拼接，高精度实物需导入外部 3D 模型（如 <code>.gltf</code>）。</td></tr><tr><td align="left"><strong>5. p5.js + p5.brush</strong></td><td align="left">创意编程与自然笔刷</td><td align="left">彩铅、水彩、蜡笔、手绘艺术短片</td><td align="left">能够高度还原真实物理笔刷的运笔方向、笔触粗细与纸张纹理。</td></tr><tr><td align="left"><strong>6. Remotion &#x2F; HyperFrames</strong></td><td align="left">声明式代码视频框架</td><td align="left">多镜头叙事长片、复杂转场编排、工程化批量视频生产</td><td align="left">封装了底层时间轴与渲染管线。<strong>HyperFrames</strong> 基于时间线控制，<strong>Remotion</strong>（React 生态）基于帧控制，后者在工程可控性上更胜一筹。</td></tr><tr><td align="left"><strong>7. Manim</strong></td><td align="left">Python 数学动画引擎</td><td align="left">严谨的数学推导、算法可视化、物理与几何科普（3Blue1Brown 风格）</td><td align="left">采用声明式对象变换逻辑，自动插值计算过渡过程，公式与图形精度极高；但视觉风格偏极简学术，缺乏商业设计质感。</td></tr></tbody></table><hr><h2 id="三、-架构拆解与实战：5-大代表性案例剖析"><a href="#三、-架构拆解与实战：5-大代表性案例剖析" class="headerlink" title="三、 架构拆解与实战：5 大代表性案例剖析"></a>三、 架构拆解与实战：5 大代表性案例剖析</h2><p>单一技术栈可以独立成片，多技术栈混合则能突破视觉上限。以下通过 5 个典型社区案例，拆解不同风格视频的技术组合与 Prompt 设计工程。</p><h3 id="案例-1：16-bit-像素巫师（纯-Canvas-2D-渲染）"><a href="#案例-1：16-bit-像素巫师（纯-Canvas-2D-渲染）" class="headerlink" title="案例 1：16-bit 像素巫师（纯 Canvas 2D 渲染）"></a>案例 1：16-bit 像素巫师（纯 Canvas 2D 渲染）</h3><ul><li><strong>原作者</strong>：<a href="https://x.com/majidmanzarpour/status/2102476258948927543">@majidmanzarpour</a></li><li><strong>成片规格</strong>：11 秒无缝循环（单次循环约 5.5 秒），从 Claude 网页端对话生成，耗时约 30 分钟，零外部素材。</li><li><strong>画面拆解</strong>：巫师处于待机呼吸状态 -&gt; 举起法杖，杖头宝石聚拢蓝色螺旋火花 -&gt; 挥杖释放光圈与飞弹（伴随屏幕震动） -&gt; 收招复位。</li></ul><p><img src="https://img.nep.me/ooo/opus-video-01.webp" alt="opus-video-01.png">  </p><p><img src="https://img.nep.me/ooo/HTYbeNlbYAAbMQQ.webp" alt="HTYbeNlbYAAbMQQ.png"></p><h4 id="核心技术实现"><a href="#核心技术实现" class="headerlink" title="核心技术实现"></a>核心技术实现</h4><ol><li><strong>低分辨率离屏渲染</strong>：所有元素先绘制在逻辑分辨率仅为 <code>128×96</code> 的离屏画布（Offscreen Canvas）上，随后按最大整数倍缩放至全屏，并强制关闭图像平滑（<code>imageSmoothingEnabled = false</code>），确保每个逻辑像素呈现出边缘锐利的方块感。</li><li><strong>帧率解耦与网格量化</strong>：将角色的法杖角度、手臂高度抽象为参数。主循环以 60Hz 运行，但角色姿态参数通过网格量化限制在每秒更新 8–12 次，还原复古游戏的抽帧动画感；与此同时，粒子与飞弹特效保持 60 FPS 更新，保证视觉流畅度。</li></ol><h4 id="复刻提示词（Prompt）"><a href="#复刻提示词（Prompt）" class="headerlink" title="复刻提示词（Prompt）"></a>复刻提示词（Prompt）</h4><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">创建一个独立的单 HTML 文件，用原生 JavaScript 和 Canvas 2D 渲染一个正在施法的像素风巫师动画。不使用任何外部素材、库或网络请求。</span><br><span class="line"></span><br><span class="line">渲染</span><br><span class="line">- 所有内容先画在一块逻辑分辨率固定为 128×96 的离屏画布上，再按能放进窗口的最大整数倍放大，画到全屏的显示画布上，居中，设置 imageSmoothingEnabled = false 和 CSS image-rendering: pixelated。</span><br><span class="line">- 所有绘制都对齐到逻辑画布的整数坐标。不要亚像素位置、抗锯齿、渐变和 shadowBlur。</span><br><span class="line">- 固定调色板，大约 24 个颜色：夜空用深蓝和深紫，长袍用暖色，再加 3–4 个明亮的魔法色。每一个像素都必须来自这个调色板。</span><br><span class="line"></span><br><span class="line">角色</span><br><span class="line">- 用填充矩形和一串串像素程序化地搭出巫师，大约 24×32 个逻辑像素：带弯折的尖顶帽、长胡子、双色长袍加深色描边、杖头有宝石的法杖。</span><br><span class="line">- 把姿势做成参数（法杖角度、手臂抬起高度、头部倾斜、长袍摆动）。参数平滑变化，但每一帧都量化到像素网格上，这样虽然循环以 60fps 运行，动作看起来却像每秒 8–12 张的像素动画。</span><br><span class="line"></span><br><span class="line">动画</span><br><span class="line">- 循环状态机：待机（两帧上下晃动、胡子摆动）→ 蓄力（法杖举起、宝石闪烁、火花螺旋着向内聚拢）→ 施法（一道强光爆发，飞弹横穿画面，屏幕震动 1–2 像素）→ 收招（回到原位）。关键帧之间的姿势参数用缓动过渡。</span><br><span class="line">- 粒子系统预先分配好、循环复用，不产生新对象。蓄力时火花围着宝石转，施法时向外炸开，每个粒子消失前从白色经过魔法色变成深色。画粒子时位置对齐到像素网格。</span><br><span class="line">- 用固定的 60Hz 时间步长更新，用 requestAnimationFrame 渲染。循环里不产生任何新对象。</span><br><span class="line"></span><br><span class="line">场景</span><br><span class="line">- 极简背景：深色夜空、几颗闪烁的 1 像素星星、月亮、石头地面。角色的剪影必须清晰可辨。</span><br><span class="line">- 宝石给巫师打一圈 1 像素的轮廓光，蓄力和施法时变亮。</span><br><span class="line"></span><br><span class="line">质量标准</span><br><span class="line">- 任何窗口大小下像素都清晰，无缝循环，稳定 60fps，剪影清楚。看起来要像一段精致的 16-bit 游戏角色动画，而不是缩小了的矢量图形。</span><br></pre></td></tr></table></figure><hr><h3 id="案例-2：丝滑-UI-连续形变（HTML-CSS-SVG-物理弹簧-节拍同步）"><a href="#案例-2：丝滑-UI-连续形变（HTML-CSS-SVG-物理弹簧-节拍同步）" class="headerlink" title="案例 2：丝滑 UI 连续形变（HTML&#x2F;CSS&#x2F;SVG + 物理弹簧 + 节拍同步）"></a>案例 2：丝滑 UI 连续形变（HTML&#x2F;CSS&#x2F;SVG + 物理弹簧 + 节拍同步）</h3><ul><li><strong>原作者</strong>：<a href="https://x.com/twoclipping/status/2103273003555402193">@twoclipping</a></li><li><strong>成片特征</strong>：零 After Effects 介入，纯代码实现 Dribbble 级交互动效。全片一镜到底，单一黑白组件在鼠标光标的真实点击与拖拽下，连续变形为按钮、播放器、滑块、图表、命令面板等 10 余种状态。</li></ul><p><img src="https://img.nep.me/ooo/opus-video-02.webp" alt="opus-video-02.png"></p><h4 id="核心技术实现-1"><a href="#核心技术实现-1" class="headerlink" title="核心技术实现"></a>核心技术实现</h4><ol><li><strong>解析式弹簧物理（Analytical Spring Physics）</strong>：摒弃生硬的线性过渡与 CSS <code>transition</code>，所有尺寸、圆角变化均由纯时间函数 <code>seek(t)</code> 结合弹簧动力学公式实时计算，甚至将组件的前沿与后沿绑定不同刚度的弹簧，实现移动时的拉伸形变（Stretch &amp; Squash）。</li><li><strong>音频节拍网格对齐（Beat-Grid Synchronization）</strong>：预先通过 Python（<code>NumPy</code>）对音频进行节拍检测，提取精确的时间戳网格，确保每一次 UI 状态切换与交互音效严格卡在 120 BPM 的节拍点上。</li><li><strong>子帧采样运动模糊（Sub-frame Motion Blur）</strong>：使用 Playwright 渲染时，针对每一帧进行 4 次高密度子帧截图，再通过 FFmpeg 混合叠加，生成自然的动态模糊拖影。</li></ol><h4 id="复刻提示词（Prompt）-1"><a href="#复刻提示词（Prompt）-1" class="headerlink" title="复刻提示词（Prompt）"></a>复刻提示词（Prompt）</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">inputs</span>&gt;</span></span><br><span class="line">开工前先问我：8–12 个界面状态（按钮、加载、播放器、滑块、开关、标签页、图表、命令面板、通知这些），纯黑白还是加一个强调色，以及一首 120 BPM 左右、可以商用的免版税音乐。</span><br><span class="line"><span class="tag">&lt;/<span class="name">inputs</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">direction</span>&gt;</span></span><br><span class="line">Dribbble 级别的界面动效。从头到尾只有一个形状，永远不切镜头：每一个状态都是同一个元素改变尺寸、圆角和颜色变过去，里面的内容在一下短暂的模糊里切换。</span><br><span class="line">一个鼠标光标用真实的点击和拖拽驱动每一次变化。浅暖灰背景，黑白组件，一种干净的界面字体（Geist）。所有动画都用弹簧，最多带一点点回弹。镜头跟着缩放，让每个状态都占满画面。最后一帧和第一帧一样，可以无缝循环。</span><br><span class="line">禁止：弹跳缓动、粒子爆炸、发光、组件上的渐变、粗细不统一的图标、没有动作的空档、任何看起来像模板的东西。</span><br><span class="line"><span class="tag">&lt;/<span class="name">direction</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">structure</span>&gt;</span></span><br><span class="line">120 BPM，7 个小节，每一拍都有事情发生。</span><br><span class="line">按钮 → 加载 → 对勾 → 灵动岛 → 音乐播放器（播放和暂停图标互相变形）→ 拖动进度条 → 变成音量滑块，拖过最大值时被拉长 → 开关踩着节拍翻转 → 开关的圆点变成标签页的指示条 → 标签页展开成一张自己画出来的图表，悬停时出现提示 → 收成 ⌘K 命令面板 → 输入筛选 → 回车 → 通知 → 回到按钮。</span><br><span class="line"><span class="tag">&lt;/<span class="name">structure</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">1. 一个 HTML 文件，1440×1440。所有样式都在 seek(t) 里由时间算出来：不用 CSS 过渡，不用计时器，帧和帧之间不保存状态。</span><br><span class="line">2. 弹簧用公式直接算。一个值要多次改变目标时，把每一次变化的弹簧叠加起来，这样它始终只由时间决定。</span><br><span class="line">3. 标签页指示条的左右两条边用两个不同的弹簧，前沿先走、后沿后跟，移动的时候会被拉长。开关的圆点也这样做。</span><br><span class="line">4. 拖拽要像真的在拖：光标按住时，数值由光标的位置算出来；松手后从当前位置弹回去。</span><br><span class="line">5. 用 numpy 分析音乐，找出节拍网格，从重拍开始。每一个界面音效都放在对应动作的那一拍上。</span><br><span class="line">6. 用 Playwright 渲染，每帧截 4 张，用 ffmpeg 混合出运动模糊，输出 60 帧的视频。</span><br><span class="line">7. 渲整片之前，每一拍先渲一帧检查，偏离节拍、太挤、看不清的地方先修掉。</span><br><span class="line"><span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">gotchas</span>&gt;</span></span><br><span class="line">被镜头缩放的元素、会渲染文字的元素，都不要加 will-change，否则文字会糊。在变形容器里切换的文字，要有自己的进场和出场时间，不然新旧文字会叠在一起。最后一帧要和第一帧完全一样，包括光标的位置和速度，否则循环的时候会卡一下。</span><br><span class="line"><span class="tag">&lt;/<span class="name">gotchas</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">start</span>&gt;</span></span><br><span class="line">先问我要输入的内容，写任何代码之前，先把状态列表排在节拍网格上给我看。</span><br><span class="line"><span class="tag">&lt;/<span class="name">start</span>&gt;</span></span><br></pre></td></tr></table></figure><hr><h3 id="案例-3：电子游戏发展史（Canvas-WebGL-着色器-Three-js-混合管线）"><a href="#案例-3：电子游戏发展史（Canvas-WebGL-着色器-Three-js-混合管线）" class="headerlink" title="案例 3：电子游戏发展史（Canvas + WebGL 着色器 + Three.js 混合管线）"></a>案例 3：电子游戏发展史（Canvas + WebGL 着色器 + Three.js 混合管线）</h3><ul><li><strong>原作者</strong>：<a href="https://x.com/prasenx/status/2103851939457093635">@prasenx</a>（于 Cursor 中调用 Claude 完成）</li><li><strong>成片特征</strong>：2 分钟史诗级短片，跨越多个游戏世代，全片零外部素材、零音频采样。</li></ul><p><img src="https://img.nep.me/ooo/opus-video-03.webp?v1" alt="opus-video-03.png"></p><h4 id="核心技术实现-2"><a href="#核心技术实现-2" class="headerlink" title="核心技术实现"></a>核心技术实现</h4><p>该项目展示了多渲染管线分阶段协同与叠加的能力：</p><ul><li><strong>Canvas 2D</strong>：负责绘制早期 8-bit &#x2F; 16-bit 像素世代的游戏画面。</li><li><strong>WebGL 着色器（Shader）</strong>：作为后处理层叠加在 Canvas 之上，实现老式 CRT 电视的屏幕弧面畸变、扫描线（Scanlines）与荧光辉光（Bloom）。<em>（注：实测对比 3 秒 90 帧的同一像素片段，纯 Canvas 渲染耗时 7 秒，叠加 WebGL 着色器后渲染耗时增至 48 秒，以算力换取了极高的物理质感。）</em></li><li><strong>Three.js（3D）</strong>：负责渲染 1993 年之后的 3D 游戏世代（如走廊射击、立体城堡、体素方块世界）。</li><li><strong>Python 音频合成</strong>：纯代码编写合成器配乐，并驱动画面剪辑节奏。</li></ul><h4 id="复刻提示词（Prompt）-2"><a href="#复刻提示词（Prompt）-2" class="headerlink" title="复刻提示词（Prompt）"></a>复刻提示词（Prompt）</h4><p>该案例证明了在 Agent 编程环境（如 Cursor &#x2F; Claude Code）中，极简的高层意图指令同样能激发 Opus 5.5 的自主工程规划能力：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">做一条 2 分钟的电影感视频，讲电子游戏的历史，要史诗、要动人，像一部纪录片预告片，全力以赴。</span><br><span class="line">配乐你自己写，完全用代码合成，不要采样，不要音频文件，不要虚拟乐器。画面要跟着音乐剪。</span><br><span class="line"></span><br><span class="line">1920x1080，60 帧。不要下载任何图片或素材，每一帧都用代码生成。最后把画面和音乐混在一起，渲染成 MP4，保存到【你指定的位置】。</span><br></pre></td></tr></table></figure><hr><h3 id="案例-4：甜酷舞蹈混剪（AI-视频模型生成主体-代码合成特效）"><a href="#案例-4：甜酷舞蹈混剪（AI-视频模型生成主体-代码合成特效）" class="headerlink" title="案例 4：甜酷舞蹈混剪（AI 视频模型生成主体 + 代码合成特效）"></a>案例 4：甜酷舞蹈混剪（AI 视频模型生成主体 + 代码合成特效）</h3><ul><li><strong>原作者</strong>：<a href="">@Gorden_Sun</a></li><li><strong>核心痛点与破局</strong>：纯代码擅长几何、排版与特效，但难以直接绘制写实人物与复杂舞蹈动作。最佳实践是采用<strong>混合管线（Hybrid Pipeline）</strong>——将写实人物交给生成式视频模型（如 Grok、Flova 等），将后期包装、场景搭建与卡点动效交给 Opus 5.5。</li></ul><p><img src="https://img.nep.me/ooo/HTYc1VSaEAIj-37.webp" alt="HTYc1VSaEAIj-37.jpg"></p><h4 id="核心技术实现-3"><a href="#核心技术实现-3" class="headerlink" title="核心技术实现"></a>核心技术实现</h4><p>以一段 15 秒的绿幕女孩跳舞视频（由 Grok 生成）为输入源，Opus 5.5 通过代码自动化完成了原本需要剪映或 After Effects 处理的三大后期工程：</p><ol><li><strong>色度键控抠像（Chroma Keying）</strong>：通过像素级颜色阈值算法剥离绿色背景，提取纯净的人物前景图层。</li><li><strong>多维场景与包装合成</strong>：使用前端代码在人物底层与顶层绘制动态背景、巨型排版文字、警戒胶带装饰、多画面分屏以及 3D 环绕字幕。</li><li><strong>音乐节拍驱动剪辑</strong>：人物原片保持连贯播放，背景色彩切换、大字冲击与分屏动效严格对齐音乐节拍。</li></ol><hr><h3 id="案例-5：从-Transformer-到-AGI（基于-Remotion-的-3-分钟叙事长片）"><a href="#案例-5：从-Transformer-到-AGI（基于-Remotion-的-3-分钟叙事长片）" class="headerlink" title="案例 5：从 Transformer 到 AGI（基于 Remotion 的 3 分钟叙事长片）"></a>案例 5：从 Transformer 到 AGI（基于 Remotion 的 3 分钟叙事长片）</h3><ul><li><strong>原作者</strong>：<a href="https://x.com/kimmonismus/status/2102844654169575547">@kimmonismus</a></li><li><strong>成片特征</strong>：在 Claude Code 中使用约 7400 行 React &#x2F; TypeScript 代码（基于 Remotion 框架）构建的 3 分钟科普短片。融合了 SVG、Canvas、开源 TTS 语音模型与 Python 合成配乐，具备 Kurzgesagt 式的视觉叙事水准。</li></ul><h4 id="复刻提示词（Prompt）-3"><a href="#复刻提示词（Prompt）-3" class="headerlink" title="复刻提示词（Prompt）"></a>复刻提示词（Prompt）</h4><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">你是一位动态设计师兼创意总监，正在制作一部 3 分钟的动画短片，完全用代码搭建，最后渲染成 MP4。</span><br><span class="line"></span><br><span class="line">这部片子</span><br><span class="line">标题：「Attention Is All You Need → AGI」</span><br><span class="line">讲的是 2017 年的一篇论文，怎样一步一步引出了大语言模型、推理、会用工具的 AI 智能体，以及 AGI 这个还没有答案的问题。它应该像一篇有电影感的影像随笔，而不是幻灯片或者时间线信息图。可以想象成 Kurzgesagt 遇上皮克斯电影的开场：有情绪、聪明、精准。</span><br><span class="line"></span><br><span class="line">技术设置</span><br><span class="line">用 Remotion（React）。新建一个项目，1920×1080，30fps，时长正好 180 秒（5400 帧）。</span><br><span class="line">每个场景一个 composition，在一个主 composition 里按顺序排好。</span><br><span class="line">不用任何外部图片素材或现成视频：所有东西都用 SVG、Canvas、CSS 和代码生成的粒子、形状来画。可以用 Google Fonts。</span><br><span class="line">动手之前，先写一份 STORYBOARD.md，写清楚每个场景的时间、画面、屏幕上的文字和转场。然后一个场景一个场景地做。</span><br><span class="line">每做完一个场景，渲染 3–4 张静帧（npx remotion still），用挑剔的眼光看一遍。先修好排版、重叠、可读性和节奏，再做下一个。</span><br><span class="line">最后用 npx remotion render 输出到 out/film.mp4。给音乐留一个可选的 &lt;Audio&gt; 位置（public/music.mp3），我之后再加；如果文件不存在，就渲染无声版。</span><br><span class="line"></span><br><span class="line">叙事主线 / 贯穿全片的母题</span><br><span class="line">主角是一个会发光的词元，也就是单词「the」，它穿过每一个时代。2017 年，它是一个孤独的光点，突然通过注意力连线「看见」了所有其他单词。随着时间推移，它有了声音、感官（多模态）、推理能力、双手（工具），最后，有了一个问题。</span><br><span class="line"></span><br><span class="line">场景（时间是大概的，你可以重新分配）</span><br><span class="line">0:00–0:15 冷开场。一片黑暗。单词像星星一样散落，彼此不相连。RNN 式的逐个处理：单词一个接一个亮起，慢慢忘掉前面的。</span><br><span class="line">0:15–0:35 2017 年 6 月，「Attention Is All You Need」（Vaswani 等人，Google）。每个单词同时连到其他所有单词。注意力连线绽放成一张网。论文标题像排版印刷一样出现。</span><br><span class="line">0:35–0:55 2018–2020：大语言模型崛起，GPT-1、BERT、GPT-2、GPT-3。规模定律：这张网指数级增长，镜头往后拉。模型开始补全句子，流畅得有点诡异。</span><br><span class="line">0:55–1:20 2022：指令微调和 RLHF，然后是 ChatGPT（2022 年 11 月 30 日）。词元有了一个聊天气泡。用户数计数器爆炸式增长。世界开始跟它对话。</span><br><span class="line">1:20–1:40 2023：多模态。图像、音频和代码从四面八方流进同一张网，词元有了「感官」。每一种模态都变成词元，流过同一个注意力机制。</span><br><span class="line">1:40–2:05 2024–2025：推理模型。一条看得见的思维链展开，分叉、剪枝、回溯。模型「先想再说」，时间变慢。</span><br><span class="line">2:05–2:30 工具使用和智能体。词元长出了双手：它调用搜索、运行代码、打开文件，调度子智能体。很多条线程同时工作，屏幕变成一个忙碌又漂亮的工作室。</span><br><span class="line">2:30–2:50 走向 AGI。所有母题汇合。2017 年的那张网重新出现，但现在是星球尺度。保持开放：不要乌托邦，也不要末日。屏幕上写：「Attention was all we needed. What comes next is up to us.」（如果你能写得更好，就改进这句话。）</span><br><span class="line">2:50–3:00 回到黑暗中一个发光的词元。片名卡，结束。</span><br><span class="line"></span><br><span class="line">制作规则</span><br><span class="line">准确性很重要：年份、人名、论文标题都要正确。对某个具体事实没把握时，宁可不写也不要猜，并把所有不确定的说法列在 NOTES.md 里。</span><br><span class="line">文字排版：屏幕上同时最多约 8 个单词，每段文字停留时间要够读完（至少 2.5 秒）。用一种展示字体，再用一种等宽字体表示「模型输出」。</span><br><span class="line">动效：用弹簧和缓动曲线，不要线性运动。场景之间的转场要从内容里长出来（网络变形、镜头穿过一个节点），不用通用的淡入淡出。</span><br><span class="line">颜色：深色背景，加一个暖色强调色，这个强调色随着时代慢慢变化。</span><br><span class="line">细节和彩蛋留给认真看的人（比如真实的论文片段、小小的界面细节、看起来可信的模型输出），像高水准的动态设计作品那样。</span><br><span class="line">节奏：密集和平静的时刻交替，给推理那一场和 AGI 那一拍留出呼吸的空间。</span><br><span class="line"></span><br><span class="line">全程自主完成整条流程。做完以后，告诉我 MP4 的路径、一段简短的创作决策总结，以及 NOTES.md。</span><br></pre></td></tr></table></figure><hr><h2 id="四、-提示词工程：如何用-XML-结构实现工业级稳定出片"><a href="#四、-提示词工程：如何用-XML-结构实现工业级稳定出片" class="headerlink" title="四、 提示词工程：如何用 XML 结构实现工业级稳定出片"></a>四、 提示词工程：如何用 XML 结构实现工业级稳定出片</h2><p>在社交媒体上，常见一种“炫技式”的一句话提示词（例如：<em>“做一条 15 秒的动态图形视频，展示你作为动效设计师的最高水平，全力以赴”</em>）。这类提示词适合测试模型的创作上限，但缺乏可控性，无法直接应用于自媒体生产、产品商业广告或特定叙事短片。</p><p>对比社区内的高质量可控作品可以发现，最稳定的工程实践是遵循 Anthropic 官方推荐的 <strong>XML 标签结构化提示词</strong>。将角色设定、输入参数、艺术指导、分镜结构与构建规范封装在独立的 XML 标签中，能够彻底消除上下文混淆。</p><h3 id="核心方法论：通过-的“负面清单”打破模型默认惰性"><a href="#核心方法论：通过-的“负面清单”打破模型默认惰性" class="headerlink" title="核心方法论：通过 &lt;direction&gt; 的“负面清单”打破模型默认惰性"></a>核心方法论：通过 <code>&lt;direction&gt;</code> 的“负面清单”打破模型默认惰性</h3><p>在缺乏明确约束时，Opus 5.5 极易退化回其训练分布中最常见的“平庸默认风格”：<strong>深色渐变背景、居中大字标题、全局统一淡入淡出（Fade-in&#x2F;out）、线性匀速运动</strong>。</p><p>要获得具备高级设计感的成片，必须在 <code>&lt;direction&gt;</code> 标签中明确列出<strong>负面约束（Negative Constraints）</strong>，例如明确禁止：弹跳缓动、廉价粒子爆炸、组件发光（Glow）、渐变填充以及模板化的布局。</p><h3 id="通用工业级视频生成-Prompt-模板"><a href="#通用工业级视频生成-Prompt-模板" class="headerlink" title="通用工业级视频生成 Prompt 模板"></a>通用工业级视频生成 Prompt 模板</h3><p>以下模板整合了分镜确认、静帧自检、纯函数渲染与波形防爆音检查，可直接复制用于商业或自媒体视频生产：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">role</span>&gt;</span></span><br><span class="line">你是一位动态设计师，也是一位创意程序员，擅长用代码做出有设计感的视频。</span><br><span class="line"><span class="tag">&lt;/<span class="name">role</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">inputs</span>&gt;</span></span><br><span class="line">开工前先问我这几件事，我没给的不要自己编：</span><br><span class="line">1. 主题，以及看完以后希望观众记住的一句话：【你的主题】</span><br><span class="line">2. 时长和画幅：【30】秒，【1920×1080 / 1080×1920 / 1080×1080】，【30 / 60】帧</span><br><span class="line">3. 风格：【像素 / 扁平插画 / 界面动效 / 彩铅手绘 / 复古电视 / 3D】，有参考视频或截图就发给你</span><br><span class="line">4. 配色和字体：【主色 #颜色】，【字体】</span><br><span class="line">5. 声音：【我提供的音乐文件 / 用代码合成配乐】，要不要配音：【要 / 不要】</span><br><span class="line"><span class="tag">&lt;/<span class="name">inputs</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">direction</span>&gt;</span></span><br><span class="line">整片只用一套风格、一套配色，同一个角色或元素在每个镜头里的样子都要一致。</span><br><span class="line">每个镜头只讲一件事，画面上的字少而大，每段文字至少停留 2.5 秒。</span><br><span class="line">动画用缓动或弹簧，不用匀速运动。转场从画面内容里长出来，比如一条线变成下一个场景的地平线，不用默认的淡入淡出。</span><br><span class="line">镜头要跟着内容动，推近、拉远、跟随，让主体在画面里足够大。</span><br><span class="line">禁止：【居中大字加渐变背景的默认风格、所有元素同时淡入、满屏小字、任何看起来像模板的东西，按你的情况补充】</span><br><span class="line"><span class="tag">&lt;/<span class="name">direction</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">structure</span>&gt;</span></span><br><span class="line">先写分镜表，每个镜头写清楚：</span><br><span class="line">镜头 [N]｜[开始–结束秒]</span><br><span class="line">画面：构图、元素、文字</span><br><span class="line">动作：进场、主要动作、出场</span><br><span class="line">镜头：推、拉、跟随还是固定</span><br><span class="line">声音：这一段的音乐和音效</span><br><span class="line">转场：怎么过渡到下一个镜头</span><br><span class="line">如果有音乐，先分析节拍，镜头切换和关键动作都落在拍子上。</span><br><span class="line"><span class="tag">&lt;/<span class="name">structure</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">1. 画面用【Canvas 2D / HTML+CSS+SVG / WebGL 着色器 / Three.js / Remotion / HyperFrames】来做，不用外部图片和素材。</span><br><span class="line">2. 页面暴露 window.render(t)，画出第 t 秒。所有画面只由 t 算出来，随机数带固定种子，不用计时器，帧和帧之间不保存状态。</span><br><span class="line">3. 用 Playwright 逐帧调用 render(t) 并截图，再用 ffmpeg 合成 MP4。</span><br><span class="line">4. 配乐和音效用 Python（numpy、scipy）从零合成，每个音效放在画面动作发生的那一帧上；有配音的话，整段合成，不要一句一句拼。</span><br><span class="line">5. 每做完一个镜头，先渲 3 张静帧自己检查：文字有没有溢出、元素有没有重叠、画面够不够满，修好了再做下一个。</span><br><span class="line"><span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">gotchas</span>&gt;</span></span><br><span class="line">- 字体加载完再开始截图，不然前几帧会用默认字体。</span><br><span class="line">- 用了 WebGL 的话，先渲一帧确认着色器真的生效了，再渲整片。</span><br><span class="line">- 你听不到声音，所以要把音频的波形画成图自己检查，确认没有爆音。</span><br><span class="line"><span class="tag">&lt;/<span class="name">gotchas</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">start</span>&gt;</span></span><br><span class="line">先问我 inputs 里的问题，然后给我分镜表，等我确认。再渲 3 张关键帧让我看风格，确认后再渲整片。</span><br><span class="line"><span class="tag">&lt;/<span class="name">start</span>&gt;</span></span><br></pre></td></tr></table></figure><hr><h2 id="五、-工程化进阶：Agent-Skill-自动化与质量控制（QA）"><a href="#五、-工程化进阶：Agent-Skill-自动化与质量控制（QA）" class="headerlink" title="五、 工程化进阶：Agent Skill 自动化与质量控制（QA）"></a>五、 工程化进阶：Agent Skill 自动化与质量控制（QA）</h2><p>在高频生产场景中，手动维护长提示词依然存在效率瓶颈。通过引入 Claude Code 的 <strong>Skill 机制</strong>、<strong>全局规范文件（<code>CLAUDE.md</code>）</strong>与<strong>多模态视觉自检闭环</strong>，可将工作流升级为全自动管线。</p><h3 id="1-部署开源自动化工作流：xilo-opus-video"><a href="#1-部署开源自动化工作流：xilo-opus-video" class="headerlink" title="1. 部署开源自动化工作流：xilo-opus-video"></a>1. 部署开源自动化工作流：<code>xilo-opus-video</code></h3><p>社区已将上述完整的制作规范封装为开源 Agent Skill。在支持 Skill 的终端或客户端中，直接向 AI 发送以下指令即可完成部署：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我安装这个 Skill：[https://github.com/Kianzzz/xilo-opus-video](https://github.com/Kianzzz/xilo-opus-video)</span><br></pre></td></tr></table></figure><p>该 Skill 激活后将自动接管以下标准作业程序（SOP）：</p><ol><li><strong>多源需求解析</strong>：支持输入文本创意、文章链接、产品 URL 或参考视频。若提供参考视频，Agent 会自动抽帧分析其分镜与剪辑节奏；若提供背景音乐，则先行运行节拍检测算法。</li><li><strong>差异化提案生成</strong>：输出 3 套在视觉风格、底层代码技术栈、分镜设计与预估渲染耗时上显著区分的方案。</li><li><strong>关键帧&#x2F;小样预览</strong>：为每个方案渲染静态关键帧（或数秒的动效小样），实现“所见即所得”的方案决策。</li><li><strong>分步实施与自检交付</strong>：方案确认后自动生成包含 7 大 XML 模块的 <code>brief.md</code>，逐镜头编码并抽帧自检，最终完成多维度打分迭代（全项达 8 分以上）后交付成片。</li></ol><h3 id="2-提升出片质量的-3-个工程技巧"><a href="#2-提升出片质量的-3-个工程技巧" class="headerlink" title="2. 提升出片质量的 3 个工程技巧"></a>2. 提升出片质量的 3 个工程技巧</h3><h4 id="技巧一：拉满推理思考强度（Thinking-Effort）"><a href="#技巧一：拉满推理思考强度（Thinking-Effort）" class="headerlink" title="技巧一：拉满推理思考强度（Thinking Effort）"></a>技巧一：拉满推理思考强度（Thinking Effort）</h4><p>程序化动画涉及复杂的空间坐标计算、缓动函数推导与时间轴对齐。在生成效果不理想时，优先在配置中将模型的推理预算（Thinking Budget &#x2F; Effort）调至最高档位。</p><h4 id="技巧二：配置项目级持久化规范（CLAUDE-md）"><a href="#技巧二：配置项目级持久化规范（CLAUDE-md）" class="headerlink" title="技巧二：配置项目级持久化规范（CLAUDE.md）"></a>技巧二：配置项目级持久化规范（<code>CLAUDE.md</code>）</h4><p>在工作区根目录下创建 <code>CLAUDE.md</code> 文件。Claude Code 每次启动会话时会自动加载该文件作为全局系统上下文，无需在单次对话中重复强调基础规范：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 视频制作规矩</span></span><br><span class="line"><span class="section">## 渲染</span></span><br><span class="line"><span class="bullet">-</span> 每一条视频都只由时间决定：window.render(t) 画出第 t 秒。</span><br><span class="line"><span class="bullet">-</span> 不用 CSS 动画、不用计时器，帧和帧之间不保存状态，随机数带固定种子。</span><br><span class="line"></span><br><span class="line"><span class="section">## 画面</span></span><br><span class="line"><span class="bullet">-</span> 禁用的默认风格：居中大字加渐变背景、所有元素一起淡入、角落里的标签和边框、界面上的发光。</span><br><span class="line"><span class="bullet">-</span> 一种标题字体、一种正文字体，除非我另外说明，只用一个强调色。</span><br><span class="line"><span class="bullet">-</span> 每 2–4 秒画面上要有新东西出现。</span><br><span class="line"></span><br><span class="line"><span class="section">## 声音</span></span><br><span class="line"><span class="bullet">-</span> 没有给音乐的话，配乐和音效都用代码合成，放在节拍上，响度 -14 LUFS。</span><br><span class="line"></span><br><span class="line"><span class="section">## 给我看之前</span></span><br><span class="line"><span class="bullet">-</span> 先出抽帧图，自己打分，把最严重的 3 个问题改掉，每一项都到 8 分以上再给我看。</span><br></pre></td></tr></table></figure><h4 id="技巧三：建立多模态抽帧自查闭环（Self-Correction-Loop）"><a href="#技巧三：建立多模态抽帧自查闭环（Self-Correction-Loop）" class="headerlink" title="技巧三：建立多模态抽帧自查闭环（Self-Correction Loop）"></a>技巧三：建立多模态抽帧自查闭环（Self-Correction Loop）</h4><p>利用 Opus 5.5 强大的视觉理解能力，让其在完成初步渲染后，将视频拆解为网格静帧图并切换至“严苛的动效导演”视角进行自我审查。可直接复用以下自检 Prompt：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">检查视频，先完成抽帧处理，然后站在严格的动效导演视角，专门挑毛病，别替自己说好话。</span><br><span class="line">按下面几项各打 1–10 分：前 2 秒抓不抓人、缩到手机屏幕大小还看不看得清、动作是否自然（有没有匀速滑动、有没有卡住不动的空拍）、画面变化是否足够（每 2–4 秒要有新东西）、构图、声音和画面是否对得上。</span><br><span class="line"></span><br><span class="line">列出最严重的 3 个问题，标上时间点。重点找这几类：切换时文字叠在一起、居中大字加渐变背景的默认画面、角落里多余的标签和边框、缩放以后变糊的字、循环接缝处的卡顿。</span><br><span class="line"></span><br><span class="line">列出以后重新渲染有问题的部分，再出一张新的抽帧图和新的分数。</span><br><span class="line"></span><br><span class="line">重复这个过程，直到每一项都在 8 分以上。</span><br></pre></td></tr></table></figure><hr><h2 id="六、-延伸阅读与开源生态参考"><a href="#六、-延伸阅读与开源生态参考" class="headerlink" title="六、 延伸阅读与开源生态参考"></a>六、 延伸阅读与开源生态参考</h2><p>Opus 5.5 并非视频生成模型，但其顶尖的代码架构能力与视觉审美先验，使其成为了极具潜力的“程序化动态设计引擎”。如需进一步探索底层源码与提示词范式，推荐参考以下开源仓库：</p><ul><li>**<a href="https://github.com/athemeroy/awesome-opus-5-5-videos">athemeroy&#x2F;awesome-opus-5-5-videos</a>**：收录了 1000+ 条由 Opus 5.5 生成的视频案例，并详细标注了每条作品对应的渲染技术栈与实现路径。</li><li>**<a href="https://github.com/guanmo-ai/awesome-ai-motion">guanmo-ai&#x2F;awesome-ai-motion</a>**：中文 AI 动效案例精选集，附带原作者完整 Prompt 与原始出处链接。</li><li>**<a href="https://github.com/JohnHeibel/ClaudeAnimationBase">JohnHeibel&#x2F;ClaudeAnimationBase</a>**：基于 <code>p5.js</code> 与 <code>p5.brush</code> 构建手绘卡通动画的标准化工程脚手架。</li><li>**<a href="https://github.com/JohnHeibel/PDoomVideo">JohnHeibel&#x2F;PDoomVideo</a>**：一支完整音乐 MV 的全量工程源码，适合深入研究长视频的代码目录组织与状态管理模式。</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;当提到使用 Claude Opus 5.5 制作视频时，一个常见的误区是将其等同于 Sora 或 Runway 等端到端的扩散视频生成模型（Diffusion Video Models）。实际上，Opus 5.5 作为多模态大语言模型，具备文本与图像理解能力，但其输出模态依</summary>
      
    
    
    
    <category term="教程" scheme="https://ooo.run/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="AI" scheme="https://ooo.run/tags/AI/"/>
    
    <category term="Claude" scheme="https://ooo.run/tags/Claude/"/>
    
    <category term="Opus 5.5" scheme="https://ooo.run/tags/Opus-5-5/"/>
    
    <category term="制作视频" scheme="https://ooo.run/tags/%E5%88%B6%E4%BD%9C%E8%A7%86%E9%A2%91/"/>
    
  </entry>
  
  <entry>
    <title>Opus 5.5 动态设计全解析：那些刷屏的“一句话生成”视频背后隐藏了什么？</title>
    <link href="https://ooo.run/post/opus-5-5-motion-design.html"/>
    <id>https://ooo.run/post/opus-5-5-motion-design.html</id>
    <published>2026-10-17T00:22:29.000Z</published>
    <updated>2026-10-17T00:31:55.797Z</updated>
    
    <content type="html"><![CDATA[<p>9 月 22 日 Opus 5.5 发布后不到几小时，社交网络上就铺天盖地出现了各种产品宣传片、个人作品集（Showreel）甚至完整的音乐 MV——<strong>全部由代码渲染生成，而且配文无一例外都是“One Prompt（仅需一句提示词）”。</strong></p><p>X 博主 <a href="https://x.com/seeconvm">Seeco</a> 花了一整周时间把这些爆款视频逐一拆解。其中确实有几个是从 30 个词的简单提示词开始的；<strong>但真正惊艳的作品，背后往往是一份 9,500 字符的详尽需求文档（Brief）、一个 Skills 文件夹、两个 API 密钥，以及在作者睡觉时连续跑了 12 个小时的自动化流水线。</strong></p><p>这篇文章将把这套工业级工程底座拆解开来，一步步带你搭建完整工作流，让你做出的第一个作品就摆脱“满大街同款 Demo”的廉价感。</p><hr><h2 id="核心速览-At-a-Glance"><a href="#核心速览-At-a-Glance" class="headerlink" title="核心速览 (At a Glance)"></a>核心速览 (At a Glance)</h2><ol><li><strong>帧函数（Frame Function）</strong>：Opus 只写代码，由无头浏览器将其转化为视频帧。</li><li><strong>工程底座（The Rig）</strong>：10 分钟搭好 Claude Code + FFmpeg + 无头浏览器。</li><li><strong>需求文档（The Brief）</strong>：用严谨的制片规范代替模糊的“感觉（Vibe）”。</li><li><strong>视觉参考（The Reference）</strong>：借用成熟的视觉语法，跳出模型的默认审美。</li><li><strong>状态列表（State Lists）</strong>：用单一容器的连续丝滑形变，干掉生硬的十几个特效转场。</li><li><strong>弹簧与音效（Springs &amp; Sound）</strong>：赋予运动物理质量感，让音频与画面共享同一个时钟。</li><li><strong>视觉质检（The Critic）</strong>：让 Opus 审视自己生成的分镜缩略图（Contact Sheet），打分并修复最差的 3 处。</li><li><strong>封装技能（The Skill）</strong>：将整套管线打包，让下一支视频真正变成“一行命令”。</li></ol><hr><h2 id="1-帧函数：为什么-Opus-写的是程序而不是直接输出视频？"><a href="#1-帧函数：为什么-Opus-写的是程序而不是直接输出视频？" class="headerlink" title="1. 帧函数：为什么 Opus 写的是程序而不是直接输出视频？"></a>1. 帧函数：为什么 Opus 写的是程序而不是直接输出视频？</h2><p>Opus 5.5 本身并不能直接输出 <code>.mp4</code> 文件。你在信息流里看到的每一段视频，本质上都是它写出的一个前端程序，再由外部工具把程序运行画面截成图片序列、最后合成视频。</p><p>整个体系的核心机密，在于一个只回答单一问题的纯函数：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">seek(t) -&gt; 精确绘制屏幕在第 t 秒时应该呈现的画面</span><br></pre></td></tr></table></figure><p>对于一段 15 秒、60 fps 的视频，无头浏览器会调用这个函数 <strong>900 次</strong>，逐帧截图，最后交给 FFmpeg 拼接成视频文件。</p><ul><li><strong>无定时器驱动（Nothing runs on a timer）</strong>：正因为不依赖实时定时器，第 240 帧可以直接独立绘制，而无需从第 0 帧回放到第 239 帧。如果某个标题入场太早，只需改一个数字并局部重渲染即可。</li><li><strong>默认技术栈倾向</strong>：如果不加干预，Opus 默认会走“零依赖路线”——单个 <code>index.html</code> + Playwright 逐帧截屏 + FFmpeg 编码。Tommy Rossi 发现，即便环境里安装了 Remotion 或 HyperFrames，Opus 默认也会跳过它们。因此，<strong>如果你想用特定框架，必须在提示词中明确点名</strong>。</li><li><strong>代码渲染的边界</strong>：<ul><li><strong>劣势领域</strong>：真实感摄影场景、复杂角色动画、自然的有机运动（这些依然需要实拍素材或传统视频生成模型）。</li><li><strong>统治级优势</strong>：产品宣传片、UI 动态交互、数据可视化故事、动态排版（Kinetic Typography）以及发布解读视频。</li></ul></li></ul><hr><h2 id="2-工程底座：为什么只用网页版聊天窗口只能做出“平庸之作”？"><a href="#2-工程底座：为什么只用网页版聊天窗口只能做出“平庸之作”？" class="headerlink" title="2. 工程底座：为什么只用网页版聊天窗口只能做出“平庸之作”？"></a>2. 工程底座：为什么只用网页版聊天窗口只能做出“平庸之作”？</h2><p>网页版聊天应用能写出动画代码，但<strong>只有具备 Shell 权限的 Agent（如 Claude Code），才能真正把视频渲染出来、“听”到音频，并亲眼“看”到自己渲染出的画面帧。</strong></p><p>有没有这个<strong>自我反馈闭环（Feedback Loop）</strong>，就是全网爆款视频与普通玩家口中“感觉也就那样（a bit mid）”之间的根本分水岭。</p><h3 id="10-分钟环境搭建"><a href="#10-分钟环境搭建" class="headerlink" title="10 分钟环境搭建"></a>10 分钟环境搭建</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># macOS 使用 brew，Linux 请使用 apt</span></span><br><span class="line">brew install node ffmpeg python</span><br><span class="line">pip install numpy librosa soundfile</span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> motion-studio &amp;&amp; <span class="built_in">cd</span> motion-studio &amp;&amp; npm init -y</span><br><span class="line">npm i -D playwright &amp;&amp; npx playwright install chromium</span><br><span class="line"></span><br><span class="line"><span class="comment"># 可选：引入专业框架 Skills</span></span><br><span class="line">npx skills add remotion-dev/skills</span><br><span class="line">npx skills add heygen-com/hyperframes</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动 Claude Code</span></span><br><span class="line">claude --model claude-opus-5-5</span><br></pre></td></tr></table></figure><p>接着，在项目根目录下放一个 <code>CLAUDE.md</code>。Claude Code 每次运行时都会自动读取它，你的“制片厂铁律”就无需在每次对话中重复：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">## Render contract (渲染契约)</span></span><br><span class="line"><span class="bullet">-</span> window.seek(t) 唯一负责绘制第 t 帧画面，严禁任何其他机制驱动画面变化</span><br><span class="line"><span class="bullet">-</span> 渲染模式下严禁使用 CSS transitions、setTimeout 或 requestAnimationFrame</span><br><span class="line"><span class="bullet">-</span> 只能使用带种子（seeded）的噪声函数，严禁使用 Math.random()</span><br><span class="line"></span><br><span class="line"><span class="section">## Look (视觉规范)</span></span><br><span class="line"><span class="bullet">-</span> 严禁出现：渐变背景上的居中大标题、所有元素无脑淡入（fade in）、角落小标签、UI 泛光特效（glow）</span><br><span class="line"><span class="bullet">-</span> 字体限制：严格限制一种展示字体（Display Face）、一种界面字体（UI Face）、一种强调色（Accent）</span><br><span class="line"><span class="bullet">-</span> 节奏要求：每 2 到 4 秒屏幕上必须出现新的视觉信息</span><br><span class="line"></span><br><span class="line"><span class="section">## Sound (音频规范)</span></span><br><span class="line"><span class="bullet">-</span> 除非提供了外部音轨，否则配乐与音效（SFX）必须通过代码合成，响度统一标准化为 -14 LUFS</span><br><span class="line"></span><br><span class="line"><span class="section">## Before you show me anything (交付前自检)</span></span><br><span class="line"><span class="bullet">-</span> 每个节拍（beat）抽一帧拼成缩略图样片（Contact Sheet），自我打分，并自动修复得分最低的 3 处问题</span><br></pre></td></tr></table></figure><blockquote><p><strong>算力档位（Effort Settings）</strong>：Opus 5.5 默认运行在 <code>medium</code> 档。<strong>所有出圈的“一镜到底”神作，跑的都是 <code>xhigh</code> 或 <code>max</code> 档。</strong> 经验法则是：局部小修小补用 <code>medium</code>，制作新片用 <code>xhigh</code>，而当视频前 3 秒直接决定产品发布生死时，果断拉满到 <code>max</code>。</p></blockquote><hr><h2 id="3-需求文档（The-Brief）：为什么“凭感觉写提示词”等于把决定权交给平庸？"><a href="#3-需求文档（The-Brief）：为什么“凭感觉写提示词”等于把决定权交给平庸？" class="headerlink" title="3. 需求文档（The Brief）：为什么“凭感觉写提示词”等于把决定权交给平庸？"></a>3. 需求文档（The Brief）：为什么“凭感觉写提示词”等于把决定权交给平庸？</h2><p>如果你只告诉模型：“帮我做一个炸裂的产品视频”，模型就会用它所知道的最安全、最平庸的默认选项填满每一个未知的空白——<strong>那个让人审美疲劳的“渐变背景居中大标题”就是这么来的。</strong></p><p>当然，那句著名的“一句话提示词”依然有它的测试价值：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">make a dynamic 15-second motion graphics video that shows what an incredible motion designer you are, like it&#x27;s your showreel for a résumé. go all out.</span><br><span class="line">(制作一段充满活力的 15 秒动态图形视频，展示你作为一名顶尖动态设计师的实力，就像你简历里的个人作品集一样。全力以赴。)</span><br></pre></td></tr></table></figure><ul><li><strong>为什么这句话有效？</strong> “Showreel（作品集）”直接给 Opus 限定了一个规则成熟的影片类型；让模型展示“它自己”，意味着不存在理解错产品业务逻辑的风险；15 秒刚好容纳 6 到 8 个镜头；而“go all out”则在 <code>xhigh</code> 之上进一步压榨了模型的表现欲。</li><li><strong>但仅限于跑通测试</strong>：跑一次验证完你的环境就够了。成百上千人发送了这句一模一样的话，结果得到了几百个高度雷同的视频——<code>athemeroy</code> 数据集将这种现象称为<strong>“需求传染（Brief Contagion）”</strong>。</li></ul><p>当你真正要推广一款产品时，在执行任何渲染任务前，Opus 需要一份真正的<strong>制片文档（Production Document）</strong>。Claude Code 团队的 Thariq 说得很直接：<strong>推文上写着“One-shot”，背后的提示词足足有 10,000 字符，还挂载了 Skills、参考示例和 API 密钥。</strong></p><h3 id="标准制片文档结构"><a href="#标准制片文档结构" class="headerlink" title="标准制片文档结构"></a>标准制片文档结构</h3><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">FILM      观众看完后记住的一句话核心信息、目标受众、时长、输出画幅格式</span><br><span class="line">ASSETS    真实 Logo、真实 UI 截图、品牌标准字体与色值、音频文件</span><br><span class="line">VISUAL    从参考片中汲取什么元素、绝对要避开哪些陈词滥调（Clichés）</span><br><span class="line">HARD LINE 底线红线：严禁捏造虚假的产品界面或业务数据指标</span><br><span class="line">DELIVER   交付物清单：故事板、分镜缩略图（Contact Sheet）、最终成片、封面帧、完整源码</span><br></pre></td></tr></table></figure><ul><li><strong>Tony Dinh 的 TypingMind 宣传片</strong>：他只多加了三行关键信息——产品网址、要求使用真实截图&#x2F;Logo&#x2F;品牌资产、以及“必须有配乐”。Opus 自己访问了网站，自动抓取了所有素材，不到 30 分钟就完成了整支视频。而在一年前，找外包机构做一支类似的发布视频花了他大约 <strong>1,200 美元</strong>。</li><li><strong>Rob Hallam 的连续创作经验</strong>：在做完第一支作品集后，他在<strong>同一个会话窗口</strong>里要求制作一支产品广告，结果生成速度快得多——因为渲染器、音频合成器和导出管线都已经存在于上下文中了。<strong>建议：每个品牌固定维护一个专属会话（Session）。</strong></li><li><strong>密钥安全</strong>：把 API Keys 放在 <code>.env</code> 文件中，在提示词里只通过变量名引用（<code>achxvi</code> 在公开他的 Pocketsflow 提示词时，就专门用了一个搞笑占位符来隐藏真实密钥）。</li></ul><hr><h2 id="4-视觉参考（The-Reference）：如何打破“千篇一律”的模型味？"><a href="#4-视觉参考（The-Reference）：如何打破“千篇一律”的模型味？" class="headerlink" title="4. 视觉参考（The Reference）：如何打破“千篇一律”的模型味？"></a>4. 视觉参考（The Reference）：如何打破“千篇一律”的模型味？</h2><p>如果不提供视觉语法（Visual Grammar），Opus 就会套用它自带的默认语法，导致完全不相干的产品视频看起来像失散多年的亲兄弟。</p><p>Rexan Wong 在研究了数十个爆款切片后发现了一个规律：<strong>直接点名某种风格，远比用形容词描述一种风格有效；而直接给出一张参考帧或一段参考视频，则能瞬间把节奏、字体排版和转场逻辑全盘托出。</strong></p><p>最管用的三种参考素材：</p><ol><li>你钟爱的某支视频里的<strong>单张静帧</strong>；</li><li>一段由 Opus 调用 FFmpeg 自动抽帧分析的<strong>短视频切片</strong>；</li><li>你自己过往作品的<strong>本地文件夹</strong>（例如 Pleometric 的 TikTok 风格短片就是从另一个爆款动画的单帧衍生出来的；而他的 Donald 风格短片则直接指向了他私人的 PC-98 艺术画廊——这是一个别人绝对无法复刻的独门素材库）。</li></ol><h3 id="视觉参考提取工作流提示词"><a href="#视觉参考提取工作流提示词" class="headerlink" title="视觉参考提取工作流提示词"></a>视觉参考提取工作流提示词</h3><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Reference: ./refs/launch.mp4</span><br><span class="line">1. 使用 ffmpeg 每 0.5 秒提取一帧画面，并仔细研究它们</span><br><span class="line">2. 编写 docs/style_guide.md：包含十六进制色板（Hex）、字体排版、镜头时长分布、转场方式、运镜逻辑、颗粒感（Grain）</span><br><span class="line">3. 编写 docs/shotlist.md：按照上述风格，为关于 [SUBJECT] 的 [DURATION] 秒视频编写分镜表</span><br><span class="line">4. 只提取视觉语法，严禁照搬参考片中的具体主体、Logo 或文案</span><br><span class="line">5. 将这两个文件展示给我，在我确认 OK 之前，不要编写任何代码</span><br></pre></td></tr></table></figure><ul><li><strong>真实资产核验</strong>：制作产品视频时，可以让 Opus 直接从线上网站抓取真实界面，但<strong>你必须亲自审核这份资产清单</strong>。如果缺少某张关键截图，Agent 应该停下来向你索要，而不是自己画一个看着很像的假界面。</li><li><strong>把技术选型留给模型</strong>：Pleometric 曾建议模型使用 <code>p5.js</code>，结果 Opus 自己手写了一个专属的纸张质感渲染器，效果反而更好。<strong>你只需明确视觉效果和边界限制，具体的技术实现让模型自己决定。</strong></li><li><strong>去哪里找优质参考片？</strong>：<code>whatships.com</code>（专门收集优质产品发布视频）、Dribbble Motion 板块、以及你竞争对手的发布会视频。</li></ul><hr><h2 id="5-状态列表（State-Lists）：为什么“一镜到底的连续形变”秒杀十个花哨特效？"><a href="#5-状态列表（State-Lists）：为什么“一镜到底的连续形变”秒杀十个花哨特效？" class="headerlink" title="5. 状态列表（State Lists）：为什么“一镜到底的连续形变”秒杀十个花哨特效？"></a>5. 状态列表（State Lists）：为什么“一镜到底的连续形变”秒杀十个花哨特效？</h2><p>“放大、变形、加粒子特效”——这叫动作清单（List of Activity），不叫故事。真正的故事板（Storyboard）定义的是<strong>观众在每一秒建立的认知</strong>：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">00-02s  HOOK (钩子)     一个瞬间抓人眼球的画面，赢得注意力</span><br><span class="line">02-05s  PROBLEM (痛点)  把用户遇到的阻碍与摩擦直观呈现在屏幕上</span><br><span class="line">05-09s  REVEAL (揭晓)   通过一次真实的交互操作，自然引出产品</span><br><span class="line">09-13s  PROOF (证实)    用一个真实界面或核心数据支撑你的主张</span><br><span class="line">13-16s  CLOSE (收尾)    干净利落的定格状态 + 清晰可读的行动号召（CTA）</span><br></pre></td></tr></table></figure><p>发布周被收藏次数最多的提示词，是一份 <strong>XML 规范文档</strong>。<code>@twoclipping</code> 的 UI 连续形变视频借此斩获了 90.7 万播放和 1.9 万收藏，而 <code>@verbove</code> 的 MakerMap 产品片也复用了完全相同的结构。</p><p>这两支神作背后的核心思想高度一致：<strong>全片只有一个主容器，通过不断改变尺寸、圆角半径和颜色，从一个状态丝滑演进到下一个状态；一个鼠标光标通过真实的点击驱动每一次变化；且最后一帧与第一帧完美重合，实现无缝循环播放（Loop）。</strong></p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Logo → CTA 按钮 → 邮箱输入框（伴随打字动画） → 加载动画（Loader） → 成功对勾 → 数据看板（Dashboard） → 图表自动绘制 → 悬浮提示框（Tooltip） → ⌘K 命令面板 → 弹窗提示（Toast） → 回到 Logo</span><br></pre></td></tr></table></figure><ul><li><strong>每个节拍（Beat）都必须具备三要素</strong>：起始状态（Entry State）、结束状态（Exit State）以及<strong>它存在的理由</strong>。如果 Agent 说不出第 4 个镜头为什么存在，那就直接砍掉第 4 个镜头。</li><li><strong>剧中剧模式（The Story Version）</strong>：<code>NFT_Chen</code> 让 Opus 先用代码写了一个带时间轴、音频波形和导出按钮的“卡通版视频剪辑软件界面”，然后把整支宣传片放在这个虚拟剪辑软件的预览窗里演绎。<strong>一个虚拟的 UI 外壳就像一个天然的摄影棚，里面每个元素的状态都清晰可控。</strong></li></ul><hr><h2 id="6-弹簧与音效：为什么廉价的动画一眼就能看出来？"><a href="#6-弹簧与音效：为什么廉价的动画一眼就能看出来？" class="headerlink" title="6. 弹簧与音效：为什么廉价的动画一眼就能看出来？"></a>6. 弹簧与音效：为什么廉价的动画一眼就能看出来？</h2><p>固定缓动曲线（Easing Curve，如简单的 <code>ease-in-out</code>）只是机械地从 A 点滑到 B 点；而<strong>具备物理质量感（Mass）的运动，会先加速、越过终点产生微妙的回弹（Overshoot），最后稳稳落定。</strong></p><p>解析解弹簧函数（Closed-form Springs）既能提供这种真实的物理质感，又能保持作为时间 $t$ 的纯函数特性，从而确保 <code>seek(t)</code> 的绝对确定性。当一个属性（比如光标位置或容器宽度）需要连续多次改变目标值时，<strong>不要重置弹簧，而是为每一次变化叠加一个独立的弹簧脉冲</strong>：</p><p>$$\text{track}(t) &#x3D; v_0 + \sum (v_i - v_{i-1}) \times \text{spring}(t - t_i)$$</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">track(t) = v0 + Σ (v_i − v_(i−<span class="number">1</span>)) × spring(t − t_i)</span><br></pre></td></tr></table></figure><p>靠这个公式，哪怕直接跳到第 812 帧，也能瞬间算出精确位置，完全不需要从第 0 帧一路物理模拟到第 811 帧。</p><ul><li><strong>分级赋予物理规则</strong>：<ul><li><strong>小型 UI 控件</strong>：干脆利落地吸附，几乎不留回弹；</li><li><strong>大面板（Panels）</strong>：沉稳落定；</li><li><strong>摄像机运镜</strong>：极度平滑，让人几乎察觉不到镜头在动；</li><li><strong>核心大标题</strong>：重重砸下，并保持足够长的静止时间供人阅读；</li><li><strong>品牌吉祥物（Mascots）</strong>：故意设计明显的Q弹跳跃感。</li><li><em>记住：如果画面里所有东西都在回弹，那就没有任何东西显得精准。</em></li></ul></li></ul><h3 id="音画同源（Sound-on-the-Same-Clock）"><a href="#音画同源（Sound-on-the-Same-Clock）" class="headerlink" title="音画同源（Sound on the Same Clock）"></a>音画同源（Sound on the Same Clock）</h3><p>声音与画面运行在同一个时间轴时钟上。Rob Hallam 起初以为他视频里的音效是后期加的，结果发现那是直接由代码生成的；<code>@oozn</code> 的乔布斯传记短片更是直接用 Node.js 合成了整条配乐，23 个转场严丝合缝地卡在 120 BPM 的节拍上。</p><p>如果你使用的是外部现成音乐，<strong>在写动画代码前，先用脚本测量音轨数据</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 使用 librosa 提取 BPM、节拍点、重拍（Downbeats）和打击点（Hits）</span></span><br><span class="line">python beats.py song.wav &gt; beats.json</span><br></pre></td></tr></table></figure><ul><li><strong>卡点铁律</strong>：常规状态切换卡在普通节拍（Beats）上；重磅画面揭示卡在强拍&#x2F;小节首拍（Downbeats）上；鼠标点击和呼啸转场声（Whooshes）卡在打击音效点（Hits）上。</li><li><strong>盲听测试（The Blindfold Test）</strong>：闭上眼睛只听视频的声音。如果脱离了画面，声音听起来毫无起伏与结构感，说明你的声音设计还没做完。</li></ul><hr><h2 id="7-视觉质检（The-Critic）：为什么必须逼-Opus-亲眼检查它渲染的每一帧？"><a href="#7-视觉质检（The-Critic）：为什么必须逼-Opus-亲眼检查它渲染的每一帧？" class="headerlink" title="7. 视觉质检（The Critic）：为什么必须逼 Opus 亲眼检查它渲染的每一帧？"></a>7. 视觉质检（The Critic）：为什么必须逼 Opus 亲眼检查它渲染的每一帧？</h2><p>Opus 5.5 具备强大的多模态视觉阅读能力，这意味着<strong>它可以亲自检查自己刚刚渲染出来的画面。</strong> 几乎所有引爆社交网络的短片，背后都有这个关键动作。</p><p><code>@mablesjoseph</code> 曾坦诚公开过他那支水彩风格短片的幕后数据：<strong>总共调用了 163 次模型，耗时近 7 个小时。</strong> Drew 在发布日当天斩获 170 万播放的作品，在成片前也经历了多轮肉眼可见的修正清洗。</p><p>不要傻傻地把完整视频导出十遍、从头到尾看十遍。<strong>让 FFmpeg 自动生成质检证据包：</strong></p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">contact sheet (分镜缩略图)  每秒抽 2 帧，每行排 6 张拼成大图</span><br><span class="line">strip (高速运动切片)        在运动最剧烈的片段前后，连续截取 12 帧</span><br><span class="line">phone test (移动端可读性)   将画面缩放到 360px 宽度，检查小屏阅读体验</span><br><span class="line">loop check (循环衔接检查)   将视频首尾相连播放两遍，检查接缝是否顺畅</span><br><span class="line">determinism (确定性校验)    将第 300 帧独立渲染两次，校验文件 Hash 必须完全一致</span><br></pre></td></tr></table></figure><p>接着，给 Opus 下达一份<strong>带牙齿的严厉质检任务（Critique Task）</strong>：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">只根据实际渲染出的画面帧进行评判，完全忽略你原本“打算”做出什么效果。</span><br><span class="line">按 1-10 分对以下维度打分：前 2 秒吸引力（Hook）、手机端可读性、运动质感、视觉丰富度、音画同步率、品牌还原度。</span><br><span class="line">列出最严重的 3 处缺陷，必须附带精确时间戳、画面证据以及局部修复方案。</span><br><span class="line">仅针对有问题的这几秒打补丁、局部重渲染，循环往复，直到所有维度的得分都达到 8 分以上。</span><br></pre></td></tr></table></figure><p><strong>重点抓捕的典型 Bug</strong>：文字重叠、该用缓动的地方变成了生硬平移、残留的角落小标签、缩放后模糊发虚的字体、画面毫无动静的“死拍（Dead Beat）”，以及循环衔接处的卡顿跳帧。</p><hr><h2 id="8-封装技能（The-Skill）：让你的下一支视频真正只需“一句话”"><a href="#8-封装技能（The-Skill）：让你的下一支视频真正只需“一句话”" class="headerlink" title="8. 封装技能（The Skill）：让你的下一支视频真正只需“一句话”"></a>8. 封装技能（The Skill）：让你的下一支视频真正只需“一句话”</h2><p>如果整支视频的决策过程只留在聊天记录里，那你只是撞大运打出了一次好局。<strong>把所有工程决策沉淀为本地文件，让下一次运行可以直接读取复用：</strong></p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">motion-studio/</span><br><span class="line">├── brief.md         # 核心目标与产品事实信息</span><br><span class="line">├── style_guide.md   # 色板、字体、运动规范、严禁使用的默认套路</span><br><span class="line">├── shotlist.md      # 节拍点、状态演进、时间戳、镜头目的</span><br><span class="line">├── assets/          # 经审核确认的 Logo、真实界面截图、音频文件</span><br><span class="line">├── src/             # 支持 seek(t) 的动画组合与核心渲染代码</span><br><span class="line">├── reviews/         # 历次生成的 Contact Sheets 缩略图与缺陷修复记录</span><br><span class="line">└── out/             # 按不同画幅比例导出的最终成片</span><br></pre></td></tr></table></figure><h3 id="通宵挂机必备：质量门禁（Gates）"><a href="#通宵挂机必备：质量门禁（Gates）" class="headerlink" title="通宵挂机必备：质量门禁（Gates）"></a>通宵挂机必备：质量门禁（Gates）</h3><p>Donald 只口述了五分钟需求就去睡觉了，一觉醒来得到了一支 142 秒的音乐 MV，随后狂揽 210 万播放（他的完整提示词长达约 9,500 字符；而 <code>@pradeepXkapoor</code> 的“Pip”机器人短片更是用了 19,000 字符的巨型 Brief）。</p><p>想要放心让 Agent 长时间自主运行，必须设置<strong>阶段门禁（Gates）</strong>：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">GATE 1  参考片与产品真实资产审核通过</span><br><span class="line">GATE 2  视觉规范（style_guide.md）与分镜表（shotlist.md）审核通过</span><br><span class="line">GATE 3  每个镜头的静态关键帧渲染完成，并通过视觉质检</span><br><span class="line">GATE 4  输出 960x540 分辨率的动态分镜预览（Animatic），带上占位音频</span><br><span class="line">GATE 5  全尺寸完整渲染、细节打磨、正式合成音效与配乐</span><br><span class="line">GATE 6  多画幅版本导出、无缝循环检查、提取封面帧、生成 README 文档</span><br></pre></td></tr></table></figure><p>在两个门禁之间，Agent 可以连续自主工作数小时。遇到缺失的界面截图会自动作为阻塞项停下提问；遇到不明确的参考风格，会先询问或渲染单张测试帧，而不是闷头渲染出 900 帧精美但方向全错的废片。</p><ul><li><strong>生成后描摹（Generate-then-trace）</strong>：这是 Donald 的核心杀招——先用 Seedance 2.5 生成带有复杂角色和物理规律的基础视频片段，然后让 Opus 用 JavaScript 在其之上逐帧重绘整部影片，最终观众看到的完全是由代码绘制的风格化图层。John Heibel 在 GitHub 上斩获 1.1K Star 的 <code>PDoom</code> 仓库则展示了<strong>多子智能体（Subagent）版本</strong>：由主 Opus 编写 <code>ANIMATION_GUIDE.md</code>，然后同时指挥多个并行 Worker 分头制作九个章节。</li><li><strong>多画幅原生适配</strong>：每一个宽高比（横屏、竖屏、方屏）都应该从同一条时间轴代码中原生计算得出，<strong>绝不能靠简单粗暴的画面裁剪（Crop）</strong>。竖屏版自动放大字号、减少同屏元素；方屏版收紧停顿节奏；宽屏版则展示更多空间上下文。</li></ul><p>当你把以上所有流程打包封装成一个 Claude Skill 后，制作下一支视频的整个过程就会真正浓缩为一行命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/motion-reel <span class="keyword">for</span> [URL], 20s, vertical, reference ./refs/frame.png</span><br></pre></td></tr></table></figure><ul><li><strong>商业变现潜力</strong>：<code>achxvi</code> 现在已经把这套流水线直接包装成商业服务对外接单——包含配乐、任意风格的定制吉祥物、产品功能展示、片尾促销信息、支持任意语言并包含最多 3 次修改。他制作一支 38 秒的竖屏产品宣传片，<strong>全程仅需 45 分钟</strong>。</li><li><strong>推荐直接 Clone 的开源仓库</strong>：<ul><li><code>PDoomVideo</code>（学习大型音乐 MV 的多智能体协作管线）</li><li><code>ClaudeAnimationBase</code>（最适合作为你自己的工程脚手架起点）</li></ul></li></ul><hr><h2 id="全景对照表：一套完整的动态设计工作室"><a href="#全景对照表：一套完整的动态设计工作室" class="headerlink" title="全景对照表：一套完整的动态设计工作室"></a>全景对照表：一套完整的动态设计工作室</h2><table><thead><tr><th align="left">核心模块 (Piece)</th><th align="left">缺失时的典型翻车症状 (What goes wrong)</th><th align="left">工程解法 (What fixes it)</th></tr></thead><tbody><tr><td align="left"><strong>1. 帧函数 (Frame Function)</strong></td><td align="left">渲染画面发生时间漂移，每次微调都意味着推倒重来</td><td align="left"><code>seek(t)</code> 纯函数、固定随机种子（Seeded Noise）、禁用定时器</td></tr><tr><td align="left"><strong>2. 工程底座 (The Rig)</strong></td><td align="left">模型是个“瞎子”和“聋子”，看不到也听不到自己的产出</td><td align="left">Claude Code + Playwright + FFmpeg + <code>CLAUDE.md</code></td></tr><tr><td align="left"><strong>3. 需求文档 (The Brief)</strong></td><td align="left">模型用最平庸安全的默认套路填满所有未明确的设计细节</td><td align="left">一句话核心信息、真实产品资产、明确的底线红线</td></tr><tr><td align="left"><strong>4. 视觉参考 (The Reference)</strong></td><td align="left">你的视频和网上其他人的“一句话 Demo”长得一模一样</td><td align="left">从单帧或参考切片中提炼生成 <code>style_guide.md</code></td></tr><tr><td align="left"><strong>5. 状态列表 (State Lists)</strong></td><td align="left">只有炫技的特效堆砌，完全没有叙事逻辑</td><td align="left">定义带有明确起始状态、结束状态与存在目的的节拍（Beats）</td></tr><tr><td align="left"><strong>6. 弹簧与音效 (Springs &amp; Sound)</strong></td><td align="left">运动呆板廉价，音乐像后期随便贴上去的背景音</td><td align="left">解析解弹簧叠加公式、<code>beats.json</code> 节拍分析、代码合成音效</td></tr><tr><td align="left"><strong>7. 视觉质检 (The Critic)</strong></td><td align="left">第一版粗糙的渲染结果被直接当成最终成片发布</td><td align="left">分镜缩略图（Contact Sheet）、多维打分、强制修复最差的 3 处</td></tr><tr><td align="left"><strong>8. 封装技能 (The Skill)</strong></td><td align="left">每次做新视频都要从零开始折腾一遍</td><td align="left">标准化工程目录、门禁机制（Gates）、<code>/motion-reel</code> 技能封装</td></tr></tbody></table><hr><h2 id="为什么这件事真正值得关注？"><a href="#为什么这件事真正值得关注？" class="headerlink" title="为什么这件事真正值得关注？"></a>为什么这件事真正值得关注？</h2><p>一年前需要花 1,200 美元找外包机构制作的产品发布宣传片，如今借助一个封装好的 Skill 和自动质检闭环，<strong>一个下午就能在本地跑完。</strong></p><p>第一个“一句话生成”的结果出得极快，这也是为什么它能瞬间引爆社交网络的时间线。但真正具有颠覆意义的在于：<strong>你的第 10 支视频会比第 1 支好得多</strong>——因为你的制片规范、确定性渲染引擎以及严苛的审片清单，会在每一次运行中不断复利积累。</p><p>等到下一次新产品发布时，你只需要替换掉产品 Brief 和界面截图资产，剩下的整座“动画制片厂”都可以原封不动地为你全速运转。</p><hr><h2 id="写在最后：真正的核心机密"><a href="#写在最后：真正的核心机密" class="headerlink" title="写在最后：真正的核心机密"></a>写在最后：真正的核心机密</h2><ol><li><strong>提示词本身只占最终效果的 10% 左右</strong>，真正决定上限的，是包裹在提示词外面的那套工程脚手架（Harness）。</li><li><strong>可寻址性（Seekability）是唯一绝对不能妥协的铁律</strong>：任何一帧都必须能够随时独立渲染，且每次渲染的结果必须分毫不差。</li><li><strong>坚持只用真实的产品资产</strong>：Opus 可以极具创意地发明一个运镜轨迹，但它绝不应该去“发明”你的产品数据看板。</li><li><strong>自我审片闭环（Critique Loop）是大多数人最容易跳过的一步</strong>——因为第一遍渲染成功往往会给人一种“大功告成”的错觉；但恰恰是这一步，构成了所有百万播放爆款视频的共同基因。</li></ol><p>那么，如果现在对你的工作流做一次分镜缩略图测试（Contact Sheet Test），你觉得哪一个环节会第一个暴露问题？</p><p><em>(原文作者：@seeconvm | 整理与编译优化版)</em></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;9 月 22 日 Opus 5.5 发布后不到几小时，社交网络上就铺天盖地出现了各种产品宣传片、个人作品集（Showreel）甚至完整的音乐 MV——&lt;strong&gt;全部由代码渲染生成，而且配文无一例外都是“One Prompt（仅需一句提示词）”。&lt;/strong&gt;&lt;/p</summary>
      
    
    
    
    <category term="笔记" scheme="https://ooo.run/categories/%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="AI" scheme="https://ooo.run/tags/AI/"/>
    
    <category term="Claude" scheme="https://ooo.run/tags/Claude/"/>
    
    <category term="Opus 5.5" scheme="https://ooo.run/tags/Opus-5-5/"/>
    
  </entry>
  
  <entry>
    <title>快速把 Hexo 博客部署到 VPS 教程指南</title>
    <link href="https://ooo.run/post/deploy-hexo-blog-to-vps.html"/>
    <id>https://ooo.run/post/deploy-hexo-blog-to-vps.html</id>
    <published>2026-10-16T05:42:26.000Z</published>
    <updated>2026-10-16T06:24:11.736Z</updated>
    
    <content type="html"><![CDATA[<p>虽然 Hexo 的博客可以部署到 GitHub 、Cloudflare Pages 等免费服务上，但是如果你有一台访问超快的 VPS，也可以选择直接部署到自己的 VPS 上。 </p><p>将 Hexo 博客部署到自己的 VPS 上，核心原理是在服务器上创建一个Git 裸仓库（Bare Repository），并通过 Git 的 post-receive 钩子（Hook），在每次本地执行 hexo d 推送静态文件时，自动将最新代码检出（Checkout）到 Web 服务器的网站根目录下。</p><p>以下是完整的手动配置流程，文末附带一键自动化部署脚本。</p><h2 id="一、-手动配置步骤"><a href="#一、-手动配置步骤" class="headerlink" title="一、 手动配置步骤"></a>一、 手动配置步骤</h2><p>假设你的服务器系统为 <code>Debian / Ubuntu</code>，目标是将博客源码推送到 <code>/var/repo/hexo.git</code>，并将生成的静态网页自动同步到 <code>/var/www/hexo</code>。</p><h3 id="1-安装-Git-并创建专用用户"><a href="#1-安装-Git-并创建专用用户" class="headerlink" title="1. 安装 Git 并创建专用用户"></a>1. 安装 Git 并创建专用用户</h3><p><em>在 VPS 上执行，出于安全考虑，限制 git 用户通过 SSH 登录交互式 Shell。</em></p><p>首先确保服务器已安装 Git，然后创建一个名为 git 的系统用户，并将其默认 Shell 修改为 git-shell（仅允许执行 Git 推送&#x2F;拉取操作，禁止常规命令行登录）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 安装 Git</span></span><br><span class="line"><span class="built_in">sudo</span> apt update &amp;&amp; <span class="built_in">sudo</span> apt install -y git</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 将 git-shell 加入系统合法 shell 列表</span></span><br><span class="line"><span class="built_in">which</span> git-shell | <span class="built_in">sudo</span> <span class="built_in">tee</span> -a /etc/shells</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 创建 git 用户并指定 shell 为 git-shell</span></span><br><span class="line"><span class="built_in">sudo</span> adduser --disabled-password --gecos <span class="string">&quot;&quot;</span> --shell <span class="string">&quot;<span class="subst">$(which git-shell)</span>&quot;</span> git</span><br></pre></td></tr></table></figure><h3 id="2-配置-SSH-公钥免密登录"><a href="#2-配置-SSH-公钥免密登录" class="headerlink" title="2. 配置 SSH 公钥免密登录"></a>2. 配置 SSH 公钥免密登录</h3><p><em>避免每次 hexo d 都需要输入服务器密码</em></p><p>在本地电脑上获取你的 SSH 公钥（如果还没有，先在本地运行 ssh-keygen 生成）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cat</span> ~/.ssh/id_ed25519.pub</span><br></pre></td></tr></table></figure><details class="flatpaper-note flatpaper-note--default"><summary class="flatpaper-note__title"><span class="flatpaper-note__icon" aria-hidden="true"></span><span class="flatpaper-note__label">生成 SSH 私钥命令</span><span class="flatpaper-note__chevron" aria-hidden="true"></span></summary><div class="flatpaper-note__body"><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t ed25519 -C <span class="string">&quot;hexo-deploy&quot;</span></span><br></pre></td></tr></table></figure></div></details><p>回到 <strong>VPS 服务器</strong>，将复制的公钥写入 git 用户的授权列表中，并严格设置目录权限（权限不对会导致 SSH 验证失败）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> -u git <span class="built_in">mkdir</span> -p /home/git/.ssh</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;粘贴你本地的公钥内容&quot;</span> | <span class="built_in">sudo</span> -u git <span class="built_in">tee</span> -a /home/git/.ssh/authorized_keys</span><br><span class="line"></span><br><span class="line"><span class="comment"># 严格限制权限</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">chmod</span> 700 /home/git/.ssh</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">chmod</span> 600 /home/git/.ssh/authorized_keys</span><br></pre></td></tr></table></figure><h3 id="3-初始化-Git-裸仓库与网站目录"><a href="#3-初始化-Git-裸仓库与网站目录" class="headerlink" title="3. 初始化 Git 裸仓库与网站目录"></a>3. 初始化 Git 裸仓库与网站目录</h3><p><em>裸仓库只保存 Git 版本历史，不保存工作区源文件</em></p><p>创建用于存放 Git 仓库的目录 <code>/var/repo</code> 和存放网页文件的目录 <code>/var/www/hexo</code>，并将所有权交给 git 用户， 钩子脚本有权限写入文件。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 创建并初始化裸仓库</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mkdir</span> -p /var/repo</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">chown</span> git:git /var/repo</span><br><span class="line"><span class="built_in">sudo</span> -u git git init --bare /var/repo/hexo.git</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 创建静态网页部署目录</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mkdir</span> -p /var/www/hexo</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">chown</span> git:git /var/www/hexo</span><br></pre></td></tr></table></figure><h3 id="4-编写-post-receive-自动同步钩子"><a href="#4-编写-post-receive-自动同步钩子" class="headerlink" title="4. 编写 post-receive 自动同步钩子"></a>4. 编写 post-receive 自动同步钩子</h3><p><em>实现推送即部署的核心步骤</em></p><p>当本地向裸仓库推送代码完成后，Git 会自动触发 <code>hooks/post-receive</code> 脚本。我们利用它将文件强制部署到 <code>/var/www/hexo</code>。 </p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建并写入钩子内容</span></span><br><span class="line"><span class="built_in">sudo</span> -u git <span class="built_in">tee</span> /var/repo/hexo.git/hooks/post-receive &gt;/dev/null &lt;&lt; <span class="string">&#x27;EOF&#x27;</span></span><br><span class="line"><span class="comment">#!/bin/sh</span></span><br><span class="line">git --work-tree=/var/www/hexo --git-dir=/var/repo/hexo.git checkout -f</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line"><span class="comment"># 赋予可执行权限（极其重要，否则钩子不会生效）</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">chmod</span> +x /var/repo/hexo.git/hooks/post-receive</span><br></pre></td></tr></table></figure><h3 id="5-配置本地-Hexo-并推送测试"><a href="#5-配置本地-Hexo-并推送测试" class="headerlink" title="5. 配置本地 Hexo 并推送测试"></a>5. 配置本地 Hexo 并推送测试</h3><p><em>在你的本地电脑博客根目录下操作</em></p><p>首先确保本地安装了 Git 部署插件：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-deployer-git --save</span><br></pre></td></tr></table></figure><p>打开本地 Hexo 根目录下的 <code>_config.yml</code> 文件，修改文末的 deploy 配置项：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deploy:</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">git</span></span><br><span class="line">  <span class="attr">repo:</span> <span class="string">git@你的服务器IP或域名:/var/repo/hexo.git</span></span><br><span class="line">  <span class="attr">branch:</span> <span class="string">master</span></span><br></pre></td></tr></table></figure><p>保存后，在本地终端执行三连命令即可完成发布：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo clean &amp;&amp; hexo g &amp;&amp; hexo d</span><br></pre></td></tr></table></figure><p>推送成功后，去服务器的 <code>/var/www/hexo</code> 目录下查看，你会发现静态网页文件已经全部自动生成好了。随后只需用 Nginx 或 Caddy 将网站根目录指向 <code>/var/www/hexo</code> 即可访问。</p><h2 id="进阶：一键自动化部署脚本"><a href="#进阶：一键自动化部署脚本" class="headerlink" title="进阶：一键自动化部署脚本"></a>进阶：一键自动化部署脚本</h2><p>如果你觉得上述手动步骤太繁琐，或者后续还想在同一台 VPS 上快速部署其他静态站点（如 VitePress、Hugo、纯静态主页等），可以直接在服务器上使用下面整理好的自动化脚本。</p><h3 id="脚本亮点"><a href="#脚本亮点" class="headerlink" title="脚本亮点"></a>脚本亮点</h3><ul><li><strong>幂等性设计</strong>：可重复执行，已存在的用户、公钥或目录会自动跳过，方便随时新增第二个、第三个静态站点仓库。</li><li><strong>安全隔离</strong>：自动配置 <code>git-shell</code> 与严格的 <code>.ssh</code> 权限，无需手动切换用户调整 <code>chown</code> &#x2F; <code>chmod。</code></li><li><strong>灵活传参</strong>：既支持命令行直接传参（如 <code>./git-deploy-repo.sh hexo /var/www/hexo</code>），也支持不带参数交互式运行。</li></ul><h3 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h3><ol><li><p>登录 VPS，创建脚本文件 <code>git-deploy-repo.sh</code>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim git-deploy-repo.sh</span><br></pre></td></tr></table></figure></li><li><p>将下方完整代码粘贴进去（注意将第 12 行的 <code>PUBKEY</code> 替换为你本地电脑的真实 SSH 公钥）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 用 git + post-receive hook 部署静态站点（如 Hexo）</span></span><br><span class="line"><span class="comment"># 用法：git-deploy-repo.sh [repo 名] [部署目录]</span></span><br><span class="line"><span class="comment">#   例：git-deploy-repo.sh hexo /var/www/hexo</span></span><br><span class="line"><span class="comment"># 不带参数时交互输入。可重复执行，用于快速新增不同的 repo。</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">set</span> -u</span><br><span class="line"></span><br><span class="line">GIT_USER=<span class="string">&quot;git&quot;</span></span><br><span class="line">REPO_ROOT=<span class="string">&quot;/var/repo&quot;</span></span><br><span class="line">PUBKEY=<span class="string">&quot;PUBKEY&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ── sudo 包装：非 root 自动加 sudo ────────────────────────────────</span></span><br><span class="line"><span class="keyword">if</span> [ <span class="string">&quot;<span class="subst">$(id -u)</span>&quot;</span> -eq 0 ]; <span class="keyword">then</span></span><br><span class="line">    SUDO=<span class="string">&quot;&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">command</span> -v <span class="built_in">sudo</span> &gt;/dev/null 2&gt;&amp;1; <span class="keyword">then</span></span><br><span class="line">        SUDO=<span class="string">&quot;sudo&quot;</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;需要 root 权限，但未找到 sudo。请以 root 身份执行。&quot;</span> &gt;&amp;2</span><br><span class="line">        <span class="built_in">exit</span> 1</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 以 git 用户身份执行命令（root 下用 runuser，否则用 sudo -u）</span></span><br><span class="line"><span class="function"><span class="title">as_git</span></span>() &#123;</span><br><span class="line">    <span class="keyword">if</span> [ <span class="string">&quot;<span class="subst">$(id -u)</span>&quot;</span> -eq 0 ]; <span class="keyword">then</span></span><br><span class="line">        runuser -u <span class="string">&quot;<span class="variable">$GIT_USER</span>&quot;</span> -- <span class="string">&quot;<span class="variable">$@</span>&quot;</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="built_in">sudo</span> -u <span class="string">&quot;<span class="variable">$GIT_USER</span>&quot;</span> <span class="string">&quot;<span class="variable">$@</span>&quot;</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> ! <span class="built_in">command</span> -v git &gt;/dev/null 2&gt;&amp;1; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;未找到 git，正在安装...&quot;</span></span><br><span class="line">    <span class="variable">$SUDO</span> apt update &amp;&amp; <span class="variable">$SUDO</span> apt install -y git || <span class="built_in">exit</span> 1</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ── 参数 ──────────────────────────────────────────────────────────</span></span><br><span class="line">REPO_NAME=<span class="string">&quot;<span class="variable">$&#123;1:-&#125;</span>&quot;</span></span><br><span class="line"><span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$REPO_NAME</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">read</span> -r -p <span class="string">&quot;repo 名称（如 hexo）: &quot;</span> REPO_NAME &lt;/dev/tty</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line">REPO_NAME=<span class="string">&quot;<span class="variable">$&#123;REPO_NAME%.git&#125;</span>&quot;</span></span><br><span class="line"><span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$REPO_NAME</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;repo 名称不能为空。&quot;</span> &gt;&amp;2</span><br><span class="line">    <span class="built_in">exit</span> 1</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">WORK_TREE=<span class="string">&quot;<span class="variable">$&#123;2:-&#125;</span>&quot;</span></span><br><span class="line"><span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$WORK_TREE</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">read</span> -r -p <span class="string">&quot;部署目录 [默认 /var/www/<span class="variable">$REPO_NAME</span>]: &quot;</span> WORK_TREE &lt;/dev/tty</span><br><span class="line">    WORK_TREE=<span class="string">&quot;<span class="variable">$&#123;WORK_TREE:-/var/www/$REPO_NAME&#125;</span>&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">REPO_DIR=<span class="string">&quot;<span class="variable">$REPO_ROOT</span>/<span class="variable">$REPO_NAME</span>.git&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ── 1. git 用户 ───────────────────────────────────────────────────</span></span><br><span class="line">GIT_SHELL=<span class="string">&quot;<span class="subst">$(command -v git-shell)</span>&quot;</span></span><br><span class="line"><span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$GIT_SHELL</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;未找到 git-shell。&quot;</span> &gt;&amp;2</span><br><span class="line">    <span class="built_in">exit</span> 1</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"><span class="keyword">if</span> ! grep -qx <span class="string">&quot;<span class="variable">$GIT_SHELL</span>&quot;</span> /etc/shells; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$GIT_SHELL</span>&quot;</span> | <span class="variable">$SUDO</span> <span class="built_in">tee</span> -a /etc/shells &gt;/dev/null</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">id</span> <span class="string">&quot;<span class="variable">$GIT_USER</span>&quot;</span> &gt;/dev/null 2&gt;&amp;1; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;用户 <span class="variable">$GIT_USER</span> 已存在，跳过创建。&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    <span class="variable">$SUDO</span> adduser --disabled-password --gecos <span class="string">&quot;&quot;</span> --shell <span class="string">&quot;<span class="variable">$GIT_SHELL</span>&quot;</span> <span class="string">&quot;<span class="variable">$GIT_USER</span>&quot;</span> || <span class="built_in">exit</span> 1</span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;已创建用户 <span class="variable">$GIT_USER</span>。&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ <span class="string">&quot;<span class="subst">$(getent passwd <span class="string">&quot;<span class="variable">$GIT_USER</span>&quot;</span> | cut -d: -f7)</span>&quot;</span> != <span class="string">&quot;<span class="variable">$GIT_SHELL</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="variable">$SUDO</span> usermod -s <span class="string">&quot;<span class="variable">$GIT_SHELL</span>&quot;</span> <span class="string">&quot;<span class="variable">$GIT_USER</span>&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;已将 <span class="variable">$GIT_USER</span> 的 shell 设为 <span class="variable">$GIT_SHELL</span>。&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ── 2. SSH 公钥 ───────────────────────────────────────────────────</span></span><br><span class="line">GIT_HOME=<span class="string">&quot;<span class="subst">$(getent passwd <span class="string">&quot;<span class="variable">$GIT_USER</span>&quot;</span> | cut -d: -f6)</span>&quot;</span></span><br><span class="line">AUTH_KEYS=<span class="string">&quot;<span class="variable">$GIT_HOME</span>/.ssh/authorized_keys&quot;</span></span><br><span class="line"></span><br><span class="line">as_git <span class="built_in">mkdir</span> -p <span class="string">&quot;<span class="variable">$GIT_HOME</span>/.ssh&quot;</span></span><br><span class="line">as_git <span class="built_in">touch</span> <span class="string">&quot;<span class="variable">$AUTH_KEYS</span>&quot;</span></span><br><span class="line"><span class="keyword">if</span> <span class="variable">$SUDO</span> grep -qF <span class="string">&quot;<span class="variable">$PUBKEY</span>&quot;</span> <span class="string">&quot;<span class="variable">$AUTH_KEYS</span>&quot;</span>; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;公钥已存在，跳过。&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$PUBKEY</span>&quot;</span> | as_git <span class="built_in">tee</span> -a <span class="string">&quot;<span class="variable">$AUTH_KEYS</span>&quot;</span> &gt;/dev/null || <span class="built_in">exit</span> 1</span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;已添加公钥。&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"><span class="variable">$SUDO</span> <span class="built_in">chmod</span> 700 <span class="string">&quot;<span class="variable">$GIT_HOME</span>/.ssh&quot;</span></span><br><span class="line"><span class="variable">$SUDO</span> <span class="built_in">chmod</span> 600 <span class="string">&quot;<span class="variable">$AUTH_KEYS</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ── 3. 裸仓库 ─────────────────────────────────────────────────────</span></span><br><span class="line"><span class="variable">$SUDO</span> <span class="built_in">mkdir</span> -p <span class="string">&quot;<span class="variable">$REPO_ROOT</span>&quot;</span></span><br><span class="line"><span class="variable">$SUDO</span> <span class="built_in">chown</span> <span class="string">&quot;<span class="variable">$GIT_USER</span>:<span class="variable">$GIT_USER</span>&quot;</span> <span class="string">&quot;<span class="variable">$REPO_ROOT</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ -d <span class="string">&quot;<span class="variable">$REPO_DIR</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;仓库 <span class="variable">$REPO_DIR</span> 已存在，跳过 init。&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    as_git git init --bare <span class="string">&quot;<span class="variable">$REPO_DIR</span>&quot;</span> || <span class="built_in">exit</span> 1</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ── 4. 部署目录 ───────────────────────────────────────────────────</span></span><br><span class="line"><span class="variable">$SUDO</span> <span class="built_in">mkdir</span> -p <span class="string">&quot;<span class="variable">$WORK_TREE</span>&quot;</span></span><br><span class="line"><span class="variable">$SUDO</span> <span class="built_in">chown</span> <span class="string">&quot;<span class="variable">$GIT_USER</span>:<span class="variable">$GIT_USER</span>&quot;</span> <span class="string">&quot;<span class="variable">$WORK_TREE</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ── 5. post-receive hook ──────────────────────────────────────────</span></span><br><span class="line">HOOK=<span class="string">&quot;<span class="variable">$REPO_DIR</span>/hooks/post-receive&quot;</span></span><br><span class="line">as_git <span class="built_in">tee</span> <span class="string">&quot;<span class="variable">$HOOK</span>&quot;</span> &gt;/dev/null &lt;&lt; <span class="string">EOF</span></span><br><span class="line"><span class="string">#!/bin/sh</span></span><br><span class="line"><span class="string">git --work-tree=&quot;$WORK_TREE&quot; --git-dir=&quot;$REPO_DIR&quot; checkout -f</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"><span class="variable">$SUDO</span> <span class="built_in">chmod</span> +x <span class="string">&quot;<span class="variable">$HOOK</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;完成：&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;  仓库：<span class="variable">$REPO_DIR</span>&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;  部署：<span class="variable">$WORK_TREE</span>&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;  远程地址：<span class="variable">$GIT_USER</span>@<span class="subst">$(hostname -f 2&gt;/dev/null || hostname)</span>:<span class="variable">$REPO_DIR</span>&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;  Hexo _config.yml 中 deploy.repo 填上面的远程地址即可。&quot;</span></span><br></pre></td></tr></table></figure></li><li><p>赋予执行权限并运行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">chmod</span> +x git-deploy-repo.sh</span><br><span class="line">./git-deploy-repo.sh hexo /var/www/hexo</span><br></pre></td></tr></table></figure></li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;虽然 Hexo 的博客可以部署到 GitHub 、Cloudflare Pages 等免费服务上，但是如果你有一台访问超快的 VPS，也可以选择直接部署到自己的 VPS 上。 &lt;/p&gt;
&lt;p&gt;将 Hexo 博客部署到自己的 VPS 上，核心原理是在服务器上创建一个Git 裸</summary>
      
    
    
    
    <category term="教程" scheme="https://ooo.run/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="Debian" scheme="https://ooo.run/tags/Debian/"/>
    
    <category term="Hexo" scheme="https://ooo.run/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>用 AI 制作 3D 游戏：Opus 5.5 / Astra + Tripo 全流程实战指南</title>
    <link href="https://ooo.run/post/how-to-use-ai-build-3d-games.html"/>
    <id>https://ooo.run/post/how-to-use-ai-build-3d-games.html</id>
    <published>2026-10-16T02:32:16.000Z</published>
    <updated>2026-10-16T09:14:14.729Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p><strong>原作者</strong>：X 博主 <a href="https://x.com/Saccc_c">@Sac</a><br><strong>演示作品</strong>：<a href="https://littleprince.dev/">点击查看《小王子》3D 可探索星球演示</a><br><strong>核心看点</strong>：结合 Tripo + Blender + Unity，利用 Opus 5.5 将《小王子》故事中的每一个星球变成可探索的 3D 场景。从场景搭建、人物制作，到代码开发与调试，核心工作流全部交由 AI 完成。</p></blockquote><p>本文将完整公开这套 AI 3D 游戏制作的工作流，结合《小王子》实际案例与可复用的提示词（Prompts），手把手带你入门 AI 3D 游戏开发，搭建属于你想象中的世界。</p><p>全文主要分为三个部分：</p><ol><li><strong>游戏开发流程与工具配置</strong></li><li><strong>3D 场景构建全流程</strong></li><li><strong>3D 角色建模与动作交互</strong></li></ol><hr><h2 id="一、-游戏开发流程与工具配置"><a href="#一、-游戏开发流程与工具配置" class="headerlink" title="一、 游戏开发流程与工具配置"></a>一、 游戏开发流程与工具配置</h2><h3 id="1-核心-AI-协同工作流"><a href="#1-核心-AI-协同工作流" class="headerlink" title="1. 核心 AI 协同工作流"></a>1. 核心 AI 协同工作流</h3><p>整个游戏的开发由多个 AI 模型各司其职、串联完成：</p><ul><li><strong>需求与策划（Fable 5.1）</strong>：负责制作 PRD（产品需求文档），梳理游戏核心场景、人物设定以及剧情故事线。</li><li><strong>视觉概念设定（GPT Image 2.5）</strong>：生成高一致性的场景参考图与人物多视角设定图。</li><li><strong>核心 3D 资产生成（Tripo）</strong>：将 2D 概念图转化为高精度 3D 模型资产。</li><li><strong>场景搭建与核心代码（Opus 5.5）</strong>：通过 CLI 与 MCP 工具操控 Blender 与 Unity，完成场景组装与核心代码搭建。</li><li><strong>迭代优化与 Debug（Astra）</strong>：负责后期的细节打磨、性能优化以及 Bug 修复。</li></ul><h3 id="2-基础工具与环境配置"><a href="#2-基础工具与环境配置" class="headerlink" title="2. 基础工具与环境配置"></a>2. 基础工具与环境配置</h3><p>在开始制作前，需在本地配置好以下软件与插件接口，以便 AI 能够直接接管操作：</p><ul><li><strong>Blender 配置</strong>：<ul><li>下载并配置 <strong>Blender CLI</strong>，用于让 AI 优化 Tripo 生成的 3D 模型，并完成游戏整体的 3D 建模组装。</li><li>安装付费插件 <strong>Auto-Rig Pro</strong>，用于人物的自动绑骨与蒙皮，为后续动作交互打下基础。</li></ul></li><li><strong>Unity 配置</strong>：<ul><li>安装 <a href="https://unity.com/">Unity 客户端</a>，作为游戏引擎将场景、人物与交互动效打包成完整游戏。</li><li>安装 <strong>Unity CLI</strong>，并在项目中安装 <strong>Pipeline 包</strong>，使 Claude（Opus 5.5）能够通过官方 <strong>Unity MCP</strong> 直接操作 Unity 项目。</li></ul></li></ul><hr><h2 id="二、-3D-场景构建全流程"><a href="#二、-3D-场景构建全流程" class="headerlink" title="二、 3D 场景构建全流程"></a>二、 3D 场景构建全流程</h2><blockquote><p><strong>核心链路</strong>：<code>Image 2.5 生成场景参考图</code> ➔ <code>AI 拆解 3D 资产并在 Tripo 中生成</code> ➔ <code>Opus 5.5 操控 Blender + Unity 完成场景建模与还原</code></p></blockquote><h3 id="步骤-1：使用-GPT-Image-2-5-生成多视角场景参考图"><a href="#步骤-1：使用-GPT-Image-2-5-生成多视角场景参考图" class="headerlink" title="步骤 1：使用 GPT Image 2.5 生成多视角场景参考图"></a>步骤 1：使用 GPT Image 2.5 生成多视角场景参考图</h3><p>根据前期整理好的游戏需求，使用 Image 2.5 生成场景参考图，以此确定整体画风、配色方案以及核心物体的空间位置。</p><ul><li><p><strong>实操建议</strong>：先确定一张满意的主场景效果图，再围绕它补充其他角度（尤其是包含室内外结构的复杂场景）：</p><ul><li><strong>俯视图</strong>：用于明确场景的整体平面布局。</li><li><strong>斜侧视图</strong>：用于补充物体的高度、造型特征和前后层次关系。</li><li><strong>全景多视图</strong>：也可以直接通过提示词一次性生成包含多视角与局部细节的综合参考图。<br><img src="https://img.nep.me/ooo/HUpgX9Jb0AAZWIv.webp" alt="HUpgX9Jb0AAZWIv.jpeg"></li></ul></li><li><p><strong>💡 可复用提示词（生成多视角场景图）</strong>：</p><blockquote><p>基于上传的场景参考图，帮我生成一张该场景的全面貌参考图片，包括整体环境的多视角视图以及局部细节的展示。</p></blockquote></li></ul><h3 id="步骤-2：利用-AI-拆解场景资产，并在-Tripo-中生成独立道具"><a href="#步骤-2：利用-AI-拆解场景资产，并在-Tripo-中生成独立道具" class="headerlink" title="步骤 2：利用 AI 拆解场景资产，并在 Tripo 中生成独立道具"></a>步骤 2：利用 AI 拆解场景资产，并在 Tripo 中生成独立道具</h3><p>拿到参考图后，不要急于建模。先让 AI 分析画面，判断哪些复杂资产需要在 Tripo 中单独生成，哪些基础几何结构可以直接交给 Opus 5.5 在 Blender&#x2F;Unity 中用代码搭建。</p><ul><li><p><strong>💡 可复用提示词（资产拆解与标注）</strong>：</p><blockquote><p>我现在要进行游戏开发，我的技术栈是 Tripo + Blender + Unity。请你根据上述生成的场景参考图，帮我深入分析哪些资产适合用 Tripo 生成，哪些资产适合用 Blender 直接进行搭建。并将需要用 Tripo 生成的资产在图片中标注出来，方便我确认。<br><img src="https://img.nep.me/ooo/HUpi6bPboAAW7av.webp" alt="HUpi6bPboAAW7av.jpeg"></p></blockquote></li><li><p><strong>Tripo 模型选择技巧</strong>：在 Tripo 中制作场景道具类 3D 资产时，建议使用 <strong>H3.1 模型</strong>，该模型能最大程度保证静态资产的高精度细节。<br><img src="https://img.nep.me/ooo/HUpj0-mbIAAQUr-.webp" alt="HUpj0-mbIAAQUr-.jpeg"></p></li></ul><h3 id="步骤-3：让-Opus-5-5-操控-Blender-与-Unity-进行组装与多机位迭代"><a href="#步骤-3：让-Opus-5-5-操控-Blender-与-Unity-进行组装与多机位迭代" class="headerlink" title="步骤 3：让 Opus 5.5 操控 Blender 与 Unity 进行组装与多机位迭代"></a>步骤 3：让 Opus 5.5 操控 Blender 与 Unity 进行组装与多机位迭代</h3><p>在 Tripo 中生成并导出独立 3D 道具后，将这些资产连同第一步的场景参考图一起交给 Opus 5.5。让它操控 Blender 和 Unity 搭建整体环境，并严格按照参考图摆放道具、调整比例与空间位置。</p><ul><li><p><strong>关键核心</strong>：提供详尽的参考图，并引入<strong>独立审查 Agent 进行多机位截图盲审</strong>，通过视觉反馈闭环不断调整布局与细节。</p></li><li><p><strong>💡 可复用提示词（场景复刻与自动盲审迭代）</strong>：</p><blockquote><p>根据上传的场景内外景多视角参考图以及生成好的 Tripo 3D 资产，请你对照参考图进行完美级的复刻，要求实现和参考图一致的惊艳质感与细节还原。</p><p>在实现完成后，请派一个独立的审查 Agent 进行多机位的场景盲审。如果发现有和参考图存在差异的地方，就不断地进行迭代完善。</p></blockquote></li></ul><hr><h2 id="三、-3D-角色建模与动作交互"><a href="#三、-3D-角色建模与动作交互" class="headerlink" title="三、 3D 角色建模与动作交互"></a>三、 3D 角色建模与动作交互</h2><blockquote><p><strong>核心链路</strong>：<code>Image 2.5 生成人物四视图</code> ➔ <code>Tripo 生成 3D 角色模型</code> ➔ <code>Blender (Auto-Rig Pro) 绑骨蒙皮</code> ➔ <code>接入 Mixamo 动作库</code> ➔ <code>Blender 复杂交互二次精调（可选）</code></p></blockquote><p>以下我们以《小王子》主角的设计为例，拆解具体步骤：</p><h3 id="步骤-1：使用-Image-2-5-生成人物-T-pose-四视图"><a href="#步骤-1：使用-Image-2-5-生成人物-T-pose-四视图" class="headerlink" title="步骤 1：使用 Image 2.5 生成人物 T-pose 四视图"></a>步骤 1：使用 Image 2.5 生成人物 T-pose 四视图</h3><p>根据人物形象设定，首先使用 Image 2.5 生成小王子的标准 <strong>T-pose 四视图</strong>（正视、背视、左视、右视），务必确保各个视角下的人物服装、比例等细节高度统一。<br><img src="https://img.nep.me/ooo/HUpkpDca4AActDR.webp" alt="HUpkpDca4AActDR.jpeg"></p><h3 id="步骤-2：使用-Tripo-的-Smart-Mesh-P2-0-生成可编辑-3D-角色"><a href="#步骤-2：使用-Tripo-的-Smart-Mesh-P2-0-生成可编辑-3D-角色" class="headerlink" title="步骤 2：使用 Tripo 的 Smart Mesh P2.0 生成可编辑 3D 角色"></a>步骤 2：使用 Tripo 的 Smart Mesh P2.0 生成可编辑 3D 角色</h3><ul><li><strong>为什么选 Smart Mesh P2.0？</strong> 这是一个专门面向游戏和交互内容的 3D 生成模型，其核心优势是<strong>生成的布线面数可控、拓扑结构规整</strong>，非常便于后期的骨骼绑定和动画制作。</li><li><strong>实操流程</strong>：<ol><li>在 Tripo 中选择<strong>「多视图生成 3D」</strong>，依次上传生成的四视图。</li><li>参数设置：拓扑默认选择<strong>「四边形」</strong>，精度拉到<strong>最高</strong>，模型选择 <strong>P2.0</strong> 并开始生成。<br><img src="https://img.nep.me/ooo/HUpkyEwakAEzlkG.webp" alt="HUpkyEwakAEzlkG.jpeg"></li><li><strong>网格检查与贴图</strong>：先观察初步生成的白模。若网格整齐无误，直接点击<strong>「Texture（纹理）」</strong>生成模型贴图；若发现局部网格形状不合理，可使用<strong>「Edit Mesh」</strong>功能进行局部重绘再生成。<br><img src="https://img.nep.me/ooo/HUpk4llbAAAQGLP.webp" alt="HUpk4llbAAAQGLP.jpeg"></li></ol></li></ul><h3 id="步骤-3：在-Blender-中利用-Auto-Rig-Pro-自动绑骨与蒙皮"><a href="#步骤-3：在-Blender-中利用-Auto-Rig-Pro-自动绑骨与蒙皮" class="headerlink" title="步骤 3：在 Blender 中利用 Auto-Rig Pro 自动绑骨与蒙皮"></a>步骤 3：在 Blender 中利用 Auto-Rig Pro 自动绑骨与蒙皮</h3><p>配置好 Auto-Rig Pro 插件后，直接在 Claude 中上传人物模型，通过提示词驱动 Blender 完成自动化骨骼绑定与权重测试。</p><ul><li><strong>💡 可复用提示词（自动绑骨、蒙皮与动作测试）</strong>：<blockquote><p>使用 Auto-Rig Pro 为人物完成绑骨和蒙皮，确保骨骼位置与人物关节精准对齐。完成后测试抬手、弯腿、转身等基础动作，检查并修正明显的变形、拉扯和穿模问题。</p></blockquote></li></ul><h3 id="步骤-4：从-Mixamo-获取动作文件并由-Opus-5-5-完成重定向"><a href="#步骤-4：从-Mixamo-获取动作文件并由-Opus-5-5-完成重定向" class="headerlink" title="步骤 4：从 Mixamo 获取动作文件并由 Opus 5.5 完成重定向"></a>步骤 4：从 Mixamo 获取动作文件并由 Opus 5.5 完成重定向</h3><ol><li>根据游戏的交互设定，前往 <a href="https://www.mixamo.com/">Mixamo 官网</a> 按关键词搜索小王子所需的动作（如行走、跳跃、挥手等），并下载对应的 <code>.fbx</code> 动作文件。</li><li>将动作文件交给 Opus 5.5，让其自动检查动作数据是否匹配小王子的真实骨骼结构，并在引擎&#x2F;Blender 中完成动作接入与重定向。<br><img src="https://img.nep.me/ooo/HUpgX9Jb0AAZWIv.webp" alt="HUpgX9Jb0AAZWIv.jpeg"></li></ol><h3 id="步骤-5：在-Blender-中精调特殊动作与道具接触细节（进阶可选）"><a href="#步骤-5：在-Blender-中精调特殊动作与道具接触细节（进阶可选）" class="headerlink" title="步骤 5：在 Blender 中精调特殊动作与道具接触细节（进阶可选）"></a>步骤 5：在 Blender 中精调特殊动作与道具接触细节（进阶可选）</h3><p>对于诸如「小王子提水壶」这类涉及<strong>人物与道具发生物理接触</strong>的复杂交互，Mixamo 的通用动作库往往无法完美适配。</p><ul><li><p><strong>解决方案</strong>：先在 Mixamo 中挑选一个姿势最接近的基础动作，再让 Opus 5.5 在 Blender 里利用控制器进行局部细节的迭代修正。<br><img src="https://img.nep.me/ooo/HUpmEFUbMAADsZk.webp" alt="HUpmEFUbMAADsZk.jpeg"></p></li><li><p><strong>💡 可复用提示词（复杂交互与 IK 手部精调）</strong>：</p><blockquote><p>请参考提供的 Mixamo 基础动作，保留其中适用的部分，并使用 Auto-Rig Pro 的手臂 IK 控制器调整手臂姿势，配合手指握持姿态和水壶空间位置的细节修正，补全「提水壶」的完整动作。确保手掌与水壶把手接触稳定、提起过程自然流畅，避免出现穿模、握持脱离或水壶悬空等问题。</p></blockquote></li></ul><p>Tripo 3D 的注册地址： <a href="https://studio.tripo3d.ai/">https://studio.tripo3d.ai/</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;原作者&lt;/strong&gt;：X 博主 &lt;a href=&quot;https://x.com/Saccc_c&quot;&gt;@Sac&lt;/a&gt;&lt;br&gt;&lt;strong&gt;演示作品&lt;/strong&gt;：&lt;a href=&quot;https://littleprince.de</summary>
      
    
    
    
    <category term="教程" scheme="https://ooo.run/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="AI" scheme="https://ooo.run/tags/AI/"/>
    
    <category term="Opus 5.5" scheme="https://ooo.run/tags/Opus-5-5/"/>
    
    <category term="Tripo 3D" scheme="https://ooo.run/tags/Tripo-3D/"/>
    
    <category term="Games" scheme="https://ooo.run/tags/Games/"/>
    
  </entry>
  
  <entry>
    <title>发现一个宝藏域名注册平台 doma.in ：好看的短域名，签到就能免费拿！</title>
    <link href="https://ooo.run/post/free-domains-with-doma-in.html"/>
    <id>https://ooo.run/post/free-domains-with-doma-in.html</id>
    <published>2026-10-13T05:52:57.000Z</published>
    <updated>2026-10-13T06:26:25.086Z</updated>
    
    <content type="html"><![CDATA[<p>发现了刚上线的宝藏域名注册平台：<a href="https://doma.in/zh-CN/">doma.in</a>。</p><p>它提供 <code>.co.fo</code>、<code>.com.fo</code>、<code>.wz.io</code>、<code>.wz.org</code> 等比较少见、但看起来相当简洁的域名后缀。</p><p>比如：</p><ul><li><code>hello.co.fo</code></li><li><code>blog.com.fo</code></li><li><code>dev.wz.io</code></li><li><code>home.wz.org</code></li></ul><p>这些域名不仅适合搭建个人博客、项目主页，也很适合拿来做短链接、个人导航站或者各种小工具。</p><div class="flatpaper-note flatpaper-note--info"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p><strong>更有意思的是：这些域名最低只需要 $5&#x2F;年，而且通过烧饼论坛签到攒积分，就有机会一分钱不花地注册，甚至连后续续费都能靠签到解决。</strong></p></div></div><h2 id="一、doma-in：一个专注于特色域名的平台"><a href="#一、doma-in：一个专注于特色域名的平台" class="headerlink" title="一、doma.in：一个专注于特色域名的平台"></a>一、doma.in：一个专注于特色域名的平台</h2><p>网站地址：<a href="https://doma.in/zh-CN/">https://doma.in/zh-CN/</a></p><p>与传统域名注册商不同，doma.in 主要提供特定二级域名下的注册服务。</p><p>例如 <code>example.co.fo</code>，从 DNS 层级来看属于三级域名，但注册和管理体验更接近普通域名。</p><p>目前平台开放以下四种后缀：</p><table><thead><tr><th>域名后缀</th><th>示例</th><th>状态</th></tr></thead><tbody><tr><td><code>.co.fo</code></td><td><code>example.co.fo</code></td><td>已开放</td></tr><tr><td><code>.com.fo</code></td><td><code>example.com.fo</code></td><td>已开放</td></tr><tr><td><code>.wz.io</code></td><td><code>example.wz.io</code></td><td>已开放</td></tr><tr><td><code>.wz.org</code></td><td><code>example.wz.org</code></td><td>已开放</td></tr></tbody></table><p>另外，还有一批后缀计划陆续开放：</p><p><code>.cc.ag</code>、<code>.cc.je</code>、<code>.cc.sk</code>、<code>.cc.td</code>、<code>.co.ki</code>、<code>.co.lu</code>、<code>.co.sk</code>、<code>.co.td</code>、<code>.edu.ax</code></p><p>相比一些已经被大量注册的传统域名，这些新开放的后缀意味着你有机会找到自己喜欢的单词、缩写甚至超短前缀。</p><p>如果你一直想拥有一个简洁、好记的域名，现在倒是值得去搜索一下。</p><h3 id="域名价格：最低每年-5"><a href="#域名价格：最低每年-5" class="headerlink" title="域名价格：最低每年 $5"></a>域名价格：最低每年 $5</h3><p>以 <code>.co.fo</code> 为例，平台根据域名前缀的长度区分首次注册价格：</p><table><thead><tr><th>域名前缀长度</th><th align="right">注册价格 &#x2F; 年</th><th align="right">续费价格 &#x2F; 年</th></tr></thead><tbody><tr><td>4 个字符及以上</td><td align="right">$5</td><td align="right">$5</td></tr><tr><td>3 个字符</td><td align="right">$10</td><td align="right">$5</td></tr><tr><td>2 个字符</td><td align="right">$25</td><td align="right">$5</td></tr><tr><td>1 个字符</td><td align="right">$50</td><td align="right">$5</td></tr></tbody></table><p><strong>最吸引我的地方是，短域名虽然首次注册需要溢价，但后续续费统一为 $5&#x2F;年。</strong></p><p>例如：</p><p>假设你成功注册了 <code>ab.co.fo</code>：</p><ul><li>第一年：$25</li><li>第二年：$5</li><li>第三年：$5</li><li>第四年：$5</li></ul><p>四年合计只需要 $40。</p><p>对于喜欢短域名的人来说，这样的续费价格还是挺有吸引力的。</p><p>需要注意，部分特殊名称还可能有额外溢价，具体以平台查询结果为准。域名支持一次注册 1～10 年，也支持设置第三方 DNS 服务商的 NS 记录和 DNSSEC 的 DS 记录。</p><h2 id="二、重点来了：如何免费注册这些域名？"><a href="#二、重点来了：如何免费注册这些域名？" class="headerlink" title="二、重点来了：如何免费注册这些域名？"></a>二、重点来了：如何免费注册这些域名？</h2><p>正常情况下，注册一个四字符以上的普通域名需要支付 $5。</p><p>不过，最近<a href="https://s.sb/DRSP">烧饼论坛</a>的商城上线了 doma.in 域名代金券，可以直接使用论坛积分购买。</p><div class="flatpaper-note flatpaper-note--info"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p>注册邀请链接： <a href="https://sb.sb/invite/p8997wrx/">https://sb.sb/invite/p8997wrx/</a><br>双方都多得 10 个烧饼</p></div></div><p>也就是说：</p><p><strong>每天去论坛签到，攒够积分后兑换一张 $5 代金券，就可以用来注册一个普通的域名。</strong></p><p>论坛公告：<a href="https://sb.sb/t/8435/">【烧饼商城更新】doma.in 域名代金券</a></p><p>目前商城提供三种面额：</p><table><thead><tr><th>代金券面额</th><th align="right">所需大米</th><th align="right">折合烧饼</th></tr></thead><tbody><tr><td>$5</td><td align="right">50,000</td><td align="right">500</td></tr><tr><td>$50</td><td align="right">500,000</td><td align="right">5,000</td></tr><tr><td>$500</td><td align="right">5,000,000</td><td align="right">50,000</td></tr></tbody></table><p>这里需要解释一下论坛的两种积分：</p><ul><li><strong>烧饼</strong>：通过签到、发帖、回复、活动等方式获取。</li><li><strong>大米</strong>：烧饼商城使用的积分，100 大米相当于 1 个烧饼。</li></ul><p>购买时如果大米不足，商城还会自动使用账户中的烧饼补足，不需要手动兑换。</p><p>因此，只要积攒 <strong>500 个烧饼</strong>，就能兑换价值 <strong>$5</strong> 的域名代金券。</p><p>兑换码可以在 doma.in 登录后兑换为账户余额，再用于域名注册。</p><p><strong>这里的免费是指不需要额外支付现金，而不是域名本身永久免费。</strong></p><h2 id="三、每天签到，一年究竟能攒多少烧饼？"><a href="#三、每天签到，一年究竟能攒多少烧饼？" class="headerlink" title="三、每天签到，一年究竟能攒多少烧饼？"></a>三、每天签到，一年究竟能攒多少烧饼？</h2><div class="flatpaper-note flatpaper-note--info"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p>直接说结论每年全勤签到可以获取超过 4000 烧饼，可以续费八年或是溢价注册短字符域名。</p></div></div><p>这是我觉得最有意思的地方。</p><p>烧饼论坛的签到奖励不只是每天随机送几个积分，还提供连续签到奖励、整月全勤奖励，以及签到暴击机制。</p><p>先看看目前的签到规则：</p><table><thead><tr><th>签到项目</th><th align="right">获得烧饼</th></tr></thead><tbody><tr><td>每日签到</td><td align="right">随机 1～10</td></tr><tr><td>每连续签到 7 天</td><td align="right">额外 +10</td></tr><tr><td>每连续签到 30 天</td><td align="right">额外 +50</td></tr><tr><td>整月全勤</td><td align="right">次月额外 +30</td></tr><tr><td>新用户注册</td><td align="right">一次性 +10</td></tr></tbody></table><p>其中，连续 7 天与连续 30 天的奖励分别计算，可以同时领取，并且支持使用暴击卡 100% 暴击双倍（道具售价 5 烧饼），烧饼论坛每月可以补签 4 次，因此不需要太担心断签。</p><p>那么，如果坚持连续签到整整 365 天，会获得多少烧饼？</p><h3 id="先计算固定奖励"><a href="#先计算固定奖励" class="headerlink" title="先计算固定奖励"></a>先计算固定奖励</h3><p>假设每天都完成签到，中途没有断签，并在连续签到 7 天、30 天时使用暴击卡：</p><table><thead><tr><th>奖励项目</th><th>计算方式</th><th align="right">年度收益</th></tr></thead><tbody><tr><td>7 天连续签到</td><td>52 × 10 × 2</td><td align="right">1,040</td></tr><tr><td>30 天连续签到</td><td>12 × 50 × 2</td><td align="right">1,200</td></tr><tr><td>每月全勤</td><td>12 × 30</td><td align="right">360</td></tr><tr><td>暴击卡成本</td><td>(52 + 12) × 5</td><td align="right">-320</td></tr><tr><td><strong>固定奖励合计</strong></td><td></td><td align="right"><strong>2,280</strong></td></tr></tbody></table><p>也就是说，<strong>仅计算连续签到奖励、全勤奖励，并扣除暴击卡成本，一年就能获得约 2,280 个烧饼。</strong></p><p>与不使用暴击卡的 1,480 个烧饼相比，净收益增加了 800 个烧饼。</p><h3 id="再加上每日随机奖励"><a href="#再加上每日随机奖励" class="headerlink" title="再加上每日随机奖励"></a>再加上每日随机奖励</h3><p>每日签到可以随机获得 1～10 个烧饼，假设平均为 5 个，实际分布可以在<a href="https://sb.sb/checkin/">签到记录</a>查看。</p><p>那么一年的预期收益就是：</p><p>365 × 5 &#x3D; 1,825 个烧饼</p><p>再加上前面计算的固定奖励：</p><p><strong>2,280 + 1,825 &#x3D; 4,105 个烧饼</strong></p><p>换句话说，只要每天坚持签到，并合理使用暴击卡，一年就能获得约 <strong>4,105 个烧饼</strong>。</p><h3 id="一年能免费兑换多少域名？"><a href="#一年能免费兑换多少域名？" class="headerlink" title="一年能免费兑换多少域名？"></a>一年能免费兑换多少域名？</h3><p>烧饼商城中的 $5 域名代金券需要 500 个烧饼。</p><p>4,105 ÷ 500 &#x3D; 8.21</p><p>也就是说，<strong>一年签到获得的烧饼，就足够兑换 8 张 $5 域名代金券，总价值 $40。</strong></p><p>如果用于注册普通四字符以上、每年 $5 的域名，相当于可以免费注册 8 个域名，或者覆盖一个域名长达 8 年的注册与续费成本。</p><p>这还没有计算新用户注册奖励、论坛发帖回复、签到随机暴击，以及不定期发放的红包。</p><p>对于喜欢折腾个人网站的人来说，每天花几秒钟签到，就有机会长期免费持有自己喜欢的域名，还是相当划算的。</p><h2 id="五、不只是签到，日常逛论坛也能赚烧饼"><a href="#五、不只是签到，日常逛论坛也能赚烧饼" class="headerlink" title="五、不只是签到，日常逛论坛也能赚烧饼"></a>五、不只是签到，日常逛论坛也能赚烧饼</h2><p>如果平时就喜欢逛技术社区，那么攒积分的速度还会更快。</p><p>烧饼论坛日常参与奖励包括：</p><table><thead><tr><th>项目</th><th align="right">奖励</th></tr></thead><tbody><tr><td>发布主题</td><td align="right">+2 烧饼</td></tr><tr><td>发布回复</td><td align="right">+1 烧饼</td></tr><tr><td>发帖随机掉落</td><td align="right">额外 +1～5</td></tr><tr><td>主题被加精</td><td align="right">+50 烧饼</td></tr><tr><td>新会员注册</td><td align="right">+10 烧饼</td></tr></tbody></table><p>另外，论坛也会不定期发放红包，平时看看自己感兴趣的技术讨论，顺手参与一下，就有机会获得额外奖励。</p><p>比如，假设每天除了签到，还正常参与讨论，发表 3 条有效回复：</p><p>一年可以额外获得：</p><p>3 × 365 &#x3D; 1,095 个烧饼</p><p>加上前面计算的平均签到收益：</p><p>3,487.5 + 1,095 &#x3D; 4,582.5 个烧饼</p><p>这已经足够兑换 9 张 $5 代金券。</p><p>当然，没必要为了积分刻意灌水。论坛对无效回复、重复内容和违规行为都有限制。正常交流、分享经验才是更适合长期积累积分的方式。</p><h2 id="六、实际兑换流程"><a href="#六、实际兑换流程" class="headerlink" title="六、实际兑换流程"></a>六、实际兑换流程</h2><p>如果想体验一下，可以按照下面的流程操作。</p><p><strong>第一步：注册烧饼论坛</strong></p><p>进入 <a href="https://sb.sb/invite/p8997wrx/">烧饼论坛</a> 注册账号，并完成邮箱验证。若论坛采用邀请注册，需要先取得邀请码。</p><p><strong>第二步：每天签到积攒积分</strong></p><p>坚持每日签到，争取获得连续 7 天、30 天与整月全勤奖励。</p><p>空闲时也可以参与论坛讨论，积攒额外积分。</p><p><strong>第三步：兑换域名代金券</strong></p><p>积攒到 500 个烧饼后，打开：</p><p><a href="https://sb.sb/shop/domains/">烧饼商城 → 域名</a></p><p>选择 $5 面额的 doma.in 域名代金券，完成兑换。</p><p>购买成功后，可以在「我的兑换码」中查看对应兑换码。</p><p><strong>第四步：兑换到 doma.in 账户</strong></p><p>进入 <a href="https://doma.in/zh-CN/">doma.in</a> 登录账户，使用兑换码将 $5 充值到账户余额。</p><p><strong>第五步：注册喜欢的域名</strong></p><p>搜索自己喜欢的域名前缀，确认尚未被注册后，直接使用账户余额支付即可。</p><p>如果注册的是普通四字符以上、首年价格 $5 的域名，那么一张 $5 代金券就能覆盖一年的注册费用。</p><h2 id="七、注册前需要注意的事情"><a href="#七、注册前需要注意的事情" class="headerlink" title="七、注册前需要注意的事情"></a>七、注册前需要注意的事情</h2><p>虽然价格便宜，而且有免费获取的方式，但在正式注册之前，还有几个地方值得留意。</p><p><strong>首先，这些并不是传统意义上独立的二级域名。</strong></p><p>例如 <code>example.co.fo</code>，它依赖于上级域名 <code>co.fo</code> 的持续运营和管理。相比直接注册 <code>.com</code>、<code>.net</code> 等顶级域名下的名称，上级运营方的稳定性也是需要考虑的因素。</p><p><strong>其次，平台目前不提供 DNS 托管。</strong></p><p>注册后需要自行选择第三方 DNS 服务商并设置 NS。根据平台公告，目前能否直接接入 Cloudflare 还需要视公共后缀列表收录情况和 Cloudflare 的实际支持而定。</p><p><strong>另外，建站需要正确配置 HTTPS。</strong></p><p>平台目前开放的这些域名后缀已加入 HSTS Preload List。浏览器会强制使用 HTTPS 访问，如果没有正确部署 TLS 证书，网站可能无法正常打开。</p><p>最后，论坛积分、优惠券和域名价格都有可能发生变化。代金券还可能存在有效期，购买后也不支持退款，所以建议有实际注册需求时再兑换。</p><h2 id="总结：一个值得顺手收藏的域名羊毛"><a href="#总结：一个值得顺手收藏的域名羊毛" class="headerlink" title="总结：一个值得顺手收藏的域名羊毛"></a>总结：一个值得顺手收藏的域名羊毛</h2><p>对于喜欢折腾个人网站、博客和小项目的人来说，我觉得 doma.in 还是挺值得关注的。</p><p>一方面，<code>.co.fo</code>、<code>.com.fo</code>、<code>.wz.io</code>、<code>.wz.org</code> 这些域名后缀看起来比较简洁，有机会注册到不错的短名称。</p><p>另一方面，最低 $5&#x2F;年的价格并不算高，短域名后续统一 $5&#x2F;年的续费机制也挺有吸引力。</p><p>最重要的是，现在还能通过烧饼论坛签到获取代金券。</p><p><strong>每天签到几秒钟，按当前规则计算，一年平均能够积攒约 3,488 个烧饼，相当于接近 $35 的域名代金券面额。</strong></p><p>平时参与讨论、领取红包或者获得其他活动奖励，还能进一步加快积累速度。</p><p>虽然不能说是无条件永久免费，但如果愿意每天顺手签到，确实有机会长期不花现金地持有几个喜欢的域名。</p><p>如果你最近正好想给博客、开发项目或者个人主页找个新域名，不妨去看看。</p><p><strong>相关地址：</strong></p><ul><li>域名注册平台：<a href="https://doma.in/zh-CN/">doma.in</a></li><li>烧饼论坛：<a href="https://sb.sb/">sb.sb</a></li><li>域名代金券：<a href="https://sb.sb/shop/domains/">烧饼商城</a></li><li>兑换说明：<a href="https://sb.sb/t/8435/">官方公告</a></li><li>签到和积分规则：<a href="https://sb.sb/pages/rules/">论坛规则</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;发现了刚上线的宝藏域名注册平台：&lt;a href=&quot;https://doma.in/zh-CN/&quot;&gt;doma.in&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;它提供 &lt;code&gt;.co.fo&lt;/code&gt;、&lt;code&gt;.com.fo&lt;/code&gt;、&lt;code&gt;.wz.io&lt;/code&gt;、&lt;co</summary>
      
    
    
    
    <category term="工具资源" scheme="https://ooo.run/categories/%E5%B7%A5%E5%85%B7%E8%B5%84%E6%BA%90/"/>
    
    
    <category term="域名" scheme="https://ooo.run/tags/%E5%9F%9F%E5%90%8D/"/>
    
    <category term="烧饼论坛" scheme="https://ooo.run/tags/%E7%83%A7%E9%A5%BC%E8%AE%BA%E5%9D%9B/"/>
    
    <category term="免费域名" scheme="https://ooo.run/tags/%E5%85%8D%E8%B4%B9%E5%9F%9F%E5%90%8D/"/>
    
  </entry>
  
  <entry>
    <title>Jev - 不聊天、不写代码，只负责做决定的 AI</title>
    <link href="https://ooo.run/post/what-is-jev.html"/>
    <id>https://ooo.run/post/what-is-jev.html</id>
    <published>2026-09-18T06:58:50.000Z</published>
    <updated>2026-09-18T07:08:41.779Z</updated>
    
    <content type="html"><![CDATA[<p>如果一个程序只是想知道“这张工单应该交给哪个部门”，它真的需要大语言模型（LLM）先写一段分析、消耗成百上千个 Token，再由后端代码从生成的文字中提取答案吗？</p><p>针对这一工程痛点，由前 OpenAI 研究员 Diogo Almeida 创立的 <strong>TypeSafe AI</strong> 带来了一种截然不同的解法——推出面向结构化决策的 System One 模型 <strong>Jev</strong>：让 AI 深度理解语义，但不让它自由发挥，直接返回预定义的选项、评分与概率分布，供后端业务系统直接执行。</p><span id="more"></span><p>2026 年 9 月 15 日，TypeSafe AI 宣布完成由 DCVC 领投的 4000 万美元种子轮融资，并正式开放 Jev 的早期访问（同时已集成至 Vercel AI Gateway）。与面向普通用户的对话助手不同，Jev 的首要目标客户是<strong>软件本身</strong>：它不负责聊天，也不负责写代码，而是旨在成为开发者可以嵌入业务流程中的一个高频“语义判断组件”。</p><p>理解 Jev 的关键，不是把它看作“更便宜、缩水的聊天模型”，而是理解它为什么从底层架构上<strong>主动放弃了自由对话与文本生成</strong>。</p><h2 id="软件需要的，往往不是一段回答"><a href="#软件需要的，往往不是一段回答" class="headerlink" title="软件需要的，往往不是一段回答"></a>软件需要的，往往不是一段回答</h2><p>设想一套客服自动化系统收到这样一条用户消息：</p><blockquote><p>“昨天同一笔订单被扣了两次钱，到现在也没有退回来，麻烦尽快处理。”</p></blockquote><p>在业务逻辑层面，系统接下来需要确定的其实只有几个核心问题：</p><ol><li><strong>分类归属</strong>：这属于账单问题还是技术故障？</li><li><strong>意图判断</strong>：客户是否在明确申请退款？</li><li><strong>紧急程度</strong>：是否需要提高处理优先级？</li></ol><p>处理这些问题确实需要理解自然语言，但答案本身<strong>并不开放</strong>。软件往往不需要一封措辞得体的客套回信，也不需要长篇大论的因果剖析；它真正需要的是能直接用于业务分流、分支跳转和数据库更新的结构化数据。</p><p><strong>Jev</strong> 正是为这种场景量身定制。开发者向模型传入当前状态（如客户消息、订单记录和业务规则），并严格限定允许的问题与备选答案。模型直接返回受约束的结构化结果，而不是发散生成的自然语言。</p><div class="flatpaper-note flatpaper-note--info"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p><strong>System One Model（系统一模型）</strong>：其命名灵感源自认知心理学名著《思考，快与慢》中人类快速、直觉式的“系统 1”判断。这里强调的是<strong>快速、低延迟、高度聚焦</strong>的决策任务，而非指模型复刻了人脑结构，更不代表它适合解决所有需要深度推理的复杂问题。</p></div></div><p>一个直观的类比是：<strong>通用聊天模型就像一个可以交流的顾问助手，而 Jev 更像一个嵌入在代码内部、能够读懂语义的判断函数。</strong></p><h2 id="三种输出，覆盖三类核心判断"><a href="#三种输出，覆盖三类核心判断" class="headerlink" title="三种输出，覆盖三类核心判断"></a>三种输出，覆盖三类核心判断</h2><p>Jev 的 API 接口围绕三种基础类型展开：<strong>Choice</strong>、<strong>Score</strong> 与 <strong>Noul</strong>。开发者无需写冗长的 Prompt 笼统要求“帮我分析一下”，而是以强类型的方式明确告诉模型程序需要哪一种数据结构：</p><table><thead><tr><th align="left">类型</th><th align="left">解决的问题</th><th align="left">核心机制</th><th align="left">典型示例</th></tr></thead><tbody><tr><td align="left"><strong>Choice</strong></td><td align="left">单项选择题</td><td align="left">从预设选项（最多 255 项）中选一，返回选项分布与置信度</td><td align="left">这张工单应交给账单、技术还是销售部门？</td></tr><tr><td align="left"><strong>Score</strong></td><td align="left">标尺评分题</td><td align="left">依据预设的有序评价阶梯打分，返回加权后的连续数值（支持小数）</td><td align="left">系统故障是轻微影响、存在替代方案，还是完全阻断业务？</td></tr><tr><td align="left"><strong>Noul</strong></td><td align="left">概率真值题</td><td align="left">针对陈述判断为真的概率（0~1 浮点数），直接反映倾向程度</td><td align="left">客户是否在消息中明确提出了退款诉求？</td></tr></tbody></table><h3 id="1-Choice（单项选择）"><a href="#1-Choice（单项选择）" class="headerlink" title="1. Choice（单项选择）"></a>1. Choice（单项选择）</h3><p><strong>Choice</strong> 适用于分类与路由。它会返回被选中的选项、各个选项的完整概率分布以及一个整体置信度（Confidence）指标。目前单个 Choice 最多支持 255 个选项。由于所有选项必须由开发者事先严格枚举，模型无法凭空创造一个不存在的部门名称或工具标识。</p><h3 id="2-Score（基准评分）"><a href="#2-Score（基准评分）" class="headerlink" title="2. Score（基准评分）"></a>2. Score（基准评分）</h3><p><strong>Score</strong> 适用于带有评价标准的等级打分。开发者需要预先定义有序档位（例如将故障划分为“仅影响外观”、“功能受损但有替代方案”、“关键功能完全不可用”三个等级），而不仅是告诉模型模糊的“打个分”。最终返回的分数通常是小数，因为它是各档位编号按预测概率加权后的数学期望值，并不局限于某个离散的整数档位。</p><h3 id="3-Noul（概率判断）"><a href="#3-Noul（概率判断）" class="headerlink" title="3. Noul（概率判断）"></a>3. Noul（概率判断）</h3><p><strong>Noul</strong> 本质上是带概率输出的布尔判断题。对于“客户是否要求退款”，模型可能直接返回 <code>0.98</code>。数值越接近 <code>1.0</code> 表示断言为真的概率越高，接近 <code>0.0</code> 表示更倾向于“否”，而在 <code>0.5</code> 附近则说明处于模棱两可的不确定区间。由于自身已是直接的概率值，Noul 不再额外返回独立的 confidence 字段。</p><hr><p>这三个类型的核心价值在于：<strong>让调用方软件在发起请求前就确切掌握返回数据的形状（Data Shape）</strong>。后续程序可以直截了当地比较概率、设置阈值、排序或分支跳转，彻底告别了对非结构化文本的脆弱解析与正则匹配。</p><h2 id="为什么它能这么快？"><a href="#为什么它能这么快？" class="headerlink" title="为什么它能这么快？"></a>为什么它能这么快？</h2><p>Jev 的速度与吞吐优势，并不仅是因为“返回的内容变短了”。</p><p>在底层推理机制上，通用大语言模型普遍采用<strong>自回归（Autoregressive）机制</strong>，必须逐个 Token 串行生成字符，即便输出简单的 JSON 也要耗费多次前向传播。而据 TypeSafe 官方介绍，Jev 放弃了逐 Token 文本生成，转而采用<strong>面向结构化决策的并行输出机制</strong>。</p><p>在单次请求中，开发者可以同时声明多个独立的判断问题（例如同时评估部门分类、退款意图与紧急程度），Jev 能够在单次推理中并行完成评估并返回结果。Vercel 在官方接入 Jev 的说明中，也将这一<strong>并行评估能力</strong>列为它与传统语言模型的重要区别。</p><div class="flatpaper-note flatpaper-note--warning"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p><strong>注意事项（并行问题的独立性）</strong>：多个并行声明的问题是基于<strong>同一份输入状态</strong>独立评估的。这意味着第二个问题并不会自动感知第一个问题的决策结果。如果你的业务流程中存在严格的因果依赖关系，仍需由外部业务代码来组织阶段性流转。</p></div></div><h3 id="与传统-LLM-的“结构化输出”有何不同？"><a href="#与传统-LLM-的“结构化输出”有何不同？" class="headerlink" title="与传统 LLM 的“结构化输出”有何不同？"></a>与传统 LLM 的“结构化输出”有何不同？</h3><p>这里需要厘清一个常见的认知误区：传统的生成式模型并非只能输出杂乱的自由文本。</p><p>现有前沿模型（如 OpenAI GPT-4o、Anthropic Claude）已经支持 <strong>Structured Outputs（结构化输出）</strong>，通过强制约束 JSON Schema 来保证输出符合指定格式。</p><p>然而，传统模型的本质依然是<strong>在语法掩码约束下逐个 Token 串行生成文本</strong>，计算开销与延迟依然受制于自回归机制。同时官方也明确提醒：<strong>格式合规（Syntactically Valid）并不等于内容真实正确（Semantically Accurate）</strong>。</p><p>因此，Jev 的差异化不在于“终于让 AI 学会了返回 JSON”，而是<strong>从底层架构彻底剥离了自由文本生成的包袱</strong>，用更聚焦的有限答案空间，换取极限的吞吐效率、极低的时延与原生的校准概率。</p><h2 id="比“选什么”更重要的，是“不确定时怎么办”"><a href="#比“选什么”更重要的，是“不确定时怎么办”" class="headerlink" title="比“选什么”更重要的，是“不确定时怎么办”"></a>比“选什么”更重要的，是“不确定时怎么办”</h2><p>假设系统在两次工单分类判断中，最终都将最高概率给到了“账单部门”，但其详细的概率分布如下：</p><ul><li><strong>工单 A</strong>：账单 98%，技术 1%，销售 1%</li><li><strong>工单 B</strong>：账单 40%，技术 35%，销售 25%</li></ul><p>两次判断的最高概率选项虽然相同，但任何健壮的软件系统都<strong>绝不应该</strong>对它们采取完全一样的处理方式：工单 A 可以直接由自动化流水线秒级派单，而工单 B 显然处于高争议状态，更适合打上待确认标记或转交人工介入。</p><p>这就是 Jev 将<strong>概率分布与不确定性</strong>置于核心地位的原因。</p><h3 id="RLCD：面向校准决策的强化学习"><a href="#RLCD：面向校准决策的强化学习" class="headerlink" title="RLCD：面向校准决策的强化学习"></a>RLCD：面向校准决策的强化学习</h3><p>传统聊天模型的 RLHF（基于人类反馈的强化学习）更侧重优化回复的顺畅度与人类偏好，这有时容易导致模型在不确定时表现出盲目的过度自信。</p><p>针对这一痛点，TypeSafe 采用了专门的训练方法 <strong>RLCD（Reinforcement Learning for Calibrated Decisions，面向校准决策的强化学习）</strong>。其核心目标不仅是选出高概率答案，更在于<strong>让输出的概率分布与真实世界的统计分布相校准（Calibrated）</strong>。</p><p>所谓<strong>校准</strong>，可以用一个统计场景来说明：</p><blockquote><p>如果模型对 1000 条客服消息给出的“退款意图”概率均为 80%，那么在事后人工复核中，这 1000 条消息里实际属于退款请求的比例也应该非常接近 80%。</p></blockquote><div class="flatpaper-note flatpaper-note--info"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p><strong>正确理解 Confidence 指标</strong>：需要特别注意，Jev 在 Choice 和 Score 中返回的 <code>confidence</code> <strong>并不等同于“这次回答绝对正确的概率”</strong>。它是根据返回的概率分布计算出的集中度概括指标，用来反映判断是明确集中还是高度分散。在实际业务落地中，开发者仍需拿真实业务样本进行基准验证，以此确定自动化分流与人工复核的阈值分界线。</p></div></div><p>对自动化系统来说，真正有用的不是一个永远表现得无比自信的模型，而是一个<strong>能够准确量化自身不确定性、方便程序妥善兜底</strong>的模型。</p><h2 id="“快-193-倍、便宜-444-倍”，应该怎样理解？"><a href="#“快-193-倍、便宜-444-倍”，应该怎样理解？" class="headerlink" title="“快 193 倍、便宜 444 倍”，应该怎样理解？"></a>“快 193 倍、便宜 444 倍”，应该怎样理解？</h2><p>在 TypeSafe 官网的宣传中，一组对比数据格外吸睛：在其 System One 工作流基准测试中，Jev 相比对照前沿模型实现了约 <strong>193.6 倍的速度提升</strong> 和 <strong>444.6 倍的成本优势</strong>。</p><p>这些数字来自特定工作流比较，我们需要结合具体工程条件客观审视：</p><h3 id="1-延迟与响应时间"><a href="#1-延迟与响应时间" class="headerlink" title="1. 延迟与响应时间"></a>1. 延迟与响应时间</h3><p>官方公开介绍给出的端到端响应时间通常在 <strong>70 ~ 500 毫秒</strong> 之间。官方也坦承，上百倍的极端改善倍数往往处于特定长文本、高推理对比场景的较高端。测试网络节点、输入文本长度、对照模型的推理配置以及是否要求对照模型输出完整 Logprobs 等，都会显著影响实际对比倍率。</p><h3 id="2-准确率评估方法"><a href="#2-准确率评估方法" class="headerlink" title="2. 准确率评估方法"></a>2. 准确率评估方法</h3><p>在 TypeSafe 的工作流评测中，基准参考并非全量来自于独立专家的人工标注，而是采用其他多款前沿强模型的共识汇总。因此，它能够有力展示在特定流程中的相对表现，但不能简单等同于在所有未知垂直场景下都具备普适的准确率。</p><p>科技媒体 Every 的一项独立初测提供了直观的侧面参考：在针对 12 段合成文本进行写作问题检查时：</p><ul><li><strong>耗时对比</strong>：Jev 每段的中位耗时为 <strong>0.35 秒</strong>，对照的 Claude Fable 5.1 在高推理设置下为 <strong>8.83 秒</strong>，相差约 25 倍；</li><li><strong>检出效果</strong>：在预设的 7 处问题中，Jev 找到了 6 处，对照模型找到了全部 7 处。</li></ul><p>这一样本虽小，但清晰体现了实际工程中的核心取舍：<strong>是用极低延迟和成本换取高并发吞吐，还是用漫长的深度推理等待换取边际精度的极致提升。</strong></p><h3 id="3-定价与推理成本"><a href="#3-定价与推理成本" class="headerlink" title="3. 定价与推理成本"></a>3. 定价与推理成本</h3><p>在计费方面，截至 2026 年 9 月，官方文档公布的标准费用极低：</p><ul><li><strong>输入费用</strong>：**$0.042 &#x2F; 百万 Token**</li><li><strong>输出费用</strong>：<strong>完全免费</strong></li></ul><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[成本估算示例]</span><br><span class="line">假设每次业务请求消耗 1,000 个输入 Token：</span><br><span class="line">调用 100 万次 = 10 亿输入 Token</span><br><span class="line">纯模型调用费用仅为： 1,000 × $0.042 = $42 美元</span><br></pre></td></tr></table></figure><p>对于日均数百万次的高频小判断任务，这种成本结构极具吸引力。但在生产环境中，更全面的考量还应包括网络通信、数据清洗、重试逻辑以及异常情况的人工介入成本。</p><h2 id="“没有幻觉”，不等于“不会犯错”"><a href="#“没有幻觉”，不等于“不会犯错”" class="headerlink" title="“没有幻觉”，不等于“不会犯错”"></a>“没有幻觉”，不等于“不会犯错”</h2><p>这是理解与落地 Jev 时必须守住的一道边界。</p><p>TypeSafe 所强调的“类型安全”与“零幻觉”，其严谨含义是：<strong>输出被严格限定在预先定义的答案空间与数据结构中</strong>。<br>比如，在候选项仅有 <code>billing</code>、<code>tech</code> 与 <code>sales</code> 时，Jev 在机制上绝不会凭空捏造一个诸如“量子事务部”的不存在字段。</p><p><strong>它保证了绝不跳出答题卡，但并不保证每道题都答对。</strong></p><p>它依然可能误将技术故障判定为账单问题，也可能低估一张紧急工单的严重程度。</p><p>更进一步，在系统工程设计上：<strong>即便模型准确识别出“客户希望退款”，程序也绝不能据此直接触发支付网关退款。</strong><br>后续操作依然必须由严谨的业务规则把关：订单是否存在？交易是否重复？是否在退款时限内？操作人员是否有授权？</p><p>一种合理的系统架构设计是：</p><ul><li><strong>模型负责语义识别</strong>：处理非结构化自然语言中的主观性与模糊性；</li><li><strong>代码负责规则与执行</strong>：核验记录、执行状态机、调用业务 API；</li><li><strong>异常机制负责兜底</strong>：低置信度结果自动进入人工复核或交由高推理模型二审。</li></ul><h2 id="它适合放在哪里？"><a href="#它适合放在哪里？" class="headerlink" title="它适合放在哪里？"></a>它适合放在哪里？</h2><p>Jev 更适合成为现有软件流水线中的一个高频节点，而不是独自包揽全流程任务：</p><ul><li><strong>智能请求路由（Router）</strong>：客服系统的工单分派、社区发帖的违规预审、多 Agent 架构中决定下一步调度哪个专用工具或 Subagent。</li><li><strong>Agent 执行控制（Controller）</strong>：判断当前工具执行结果是“成功”、“需要重试”还是“陷入死循环需人工接入”，驱动决策状态机。</li><li><strong>内容与合规质检（Evaluator）</strong>：作为低成本的裁判模型（LLM-as-a-Judge），批量检查生成式模型的输出是否符合既定规范。</li></ul><p>相反，如果任务目标是<strong>写一封邮件、生成一段业务代码或向用户详细推导判断依据</strong>，这些场景依然属于生成式模型的绝对领域。同时，Jev 当前仅接收文本形态的输入（如字符串、JSON 对象或文本数组），无法直接输入图像、音频等多模态数据，多模态内容需先经过转换。</p><div class="flatpaper-note flatpaper-note--info"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p><strong>推荐的系统协作范式</strong>：</p><ul><li><strong>传统确定性代码</strong>：负责硬规则、权限校验与实际事务执行；</li><li><strong>Jev（决策模型）</strong>：负责高频、低延迟、强类型化的语义判断与状态分流；</li><li><strong>生成式 LLM</strong>：负责长程推理、内容创作与人机交互；</li><li><strong>人工专家</strong>：负责关键审批与疑难边缘案例兜底。</li></ul></div></div><h2 id="从聊天窗口，走向软件内部"><a href="#从聊天窗口，走向软件内部" class="headerlink" title="从聊天窗口，走向软件内部"></a>从聊天窗口，走向软件内部</h2><p>“Jev” 这个名字取自英国经济学家威廉·斯坦利·杰文斯（William Stanley Jevons）以及著名的<strong>杰文斯悖论（Jevons Paradox）</strong>：</p><blockquote><p>当某种资源的使用效率大幅提升、成本显著下降时，该资源的总消耗量往往不仅不会减少，反而会因为应用边界的指数级扩张而大幅激增。</p></blockquote><p>TypeSafe 借此表达了对 AI 普及路径的深刻预期：当可靠的语义判断变得足够轻巧、响应时间进入几十毫秒量级、调用成本低至几乎可以忽略不计，开发者会毫不犹豫地把它嵌入到成千上万个以往根本不舍得用 AI 的日常代码分支中。</p><p>通用对话助手能否让人满意，往往取决于它能否把长篇大论写得生动可信；而软件底层的判断组件，衡量标准则完全不同：<strong>延迟是否够低、成本是否可控、接口是否足够强类型安全，以及系统能否在其产生疑虑时平稳降级</strong>。</p><p>Jev 不需要证明自己“比会聊天的模型更高级”。它只需要在那些数以亿计、候选项明确、却必须读懂人话的后台分支里，证明自己是那个比通用模型更轻巧、更可靠的“语义判断函数”。</p><p>它真正具有启发性的地方，正是<strong>让 AI 走出人机对话的窗口，静默地沉淀为现代软件系统内部随处可调用的基础设施</strong>。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;如果一个程序只是想知道“这张工单应该交给哪个部门”，它真的需要大语言模型（LLM）先写一段分析、消耗成百上千个 Token，再由后端代码从生成的文字中提取答案吗？&lt;/p&gt;
&lt;p&gt;针对这一工程痛点，由前 OpenAI 研究员 Diogo Almeida 创立的 &lt;strong&gt;TypeSafe AI&lt;/strong&gt; 带来了一种截然不同的解法——推出面向结构化决策的 System One 模型 &lt;strong&gt;Jev&lt;/strong&gt;：让 AI 深度理解语义，但不让它自由发挥，直接返回预定义的选项、评分与概率分布，供后端业务系统直接执行。&lt;/p&gt;</summary>
    
    
    
    <category term="资讯" scheme="https://ooo.run/categories/%E8%B5%84%E8%AE%AF/"/>
    
    
    <category term="AI" scheme="https://ooo.run/tags/AI/"/>
    
    <category term="Jev" scheme="https://ooo.run/tags/Jev/"/>
    
    <category term="决策模型" scheme="https://ooo.run/tags/%E5%86%B3%E7%AD%96%E6%A8%A1%E5%9E%8B/"/>
    
  </entry>
  
  <entry>
    <title>如何选择 GPT 5.6 不同模型与推理强度？查看 OpenAI Codex 团队的推荐设置</title>
    <link href="https://ooo.run/post/how-to-select-gpt-5-6-model.html"/>
    <id>https://ooo.run/post/how-to-select-gpt-5-6-model.html</id>
    <published>2026-07-12T02:20:12.000Z</published>
    <updated>2026-07-13T07:57:31.595Z</updated>
    
    <content type="html"><![CDATA[<p>7 月 10 日，OpenAI Codex 团队在 Reddit 举办了一场 <a href="https://www.reddit.com/r/codex/comments/1us9ty9/ama_with_openais_codex_team/">AMA</a>（Ask Me Anything，在线问答活动）。</p><p>整场 AMA 的评论区一半用户认真提问 Codex、GPT-5.6 和 ChatGPT Work 的使用方法，另一半用户则集中吐槽额度消耗、桌面应用体验以及不同平台之间长期存在的功能差距。</p><p>虽然官方没有正面回答所有尖锐问题，但在模型选择、推理强度、长任务设计、MCP 工具接入和权限管理方面，还是给出了不少具有实际参考价值的信息。</p><p>其中最核心的结论可以概括为一句话：</p><blockquote><p>官方介绍了如何节省 Token 的使用 Codex，却没有解释为什么 GPT-5.6 宣称效率更高却用起来消耗更快。</p></blockquote><h2 id="不同模型与-Effort-应该怎么选"><a href="#不同模型与-Effort-应该怎么选" class="headerlink" title="不同模型与 Effort 应该怎么选"></a>不同模型与 Effort 应该怎么选</h2><p>这次 AMA 中最实用的部分，是 Codex 团队成员分享了不同模型和 Effort 推理强度的选择经验。</p><p>官方给出的日常默认组合是：</p><blockquote><p><strong>Sol + Medium Effort</strong></p></blockquote><p>这一配置适合大多数普通开发任务，在速度、质量和额度消耗之间相对均衡。</p><p>对于不同场景，则可以进一步调整。</p><h3 id="Sol：日常开发和前端任务的首选"><a href="#Sol：日常开发和前端任务的首选" class="headerlink" title="Sol：日常开发和前端任务的首选"></a>Sol：日常开发和前端任务的首选</h3><p>Sol 适合作为 Codex 中的默认主力模型，尤其适合：</p><ul><li>常规代码编写</li><li>Bug 修复</li><li>跨文件修改</li><li>UI 与前端开发</li><li>根据参考图还原界面</li></ul><p>官方特别提到，<strong>UI 和前端能力</strong> 本身就是 GPT-5.6 的重点训练方向之一。</p><p>如果任务中能够提供截图、设计稿或参考页面，Sol 的表现通常会明显优于只给出文字描述。</p><h3 id="Terra：额度敏感任务的性价比选择"><a href="#Terra：额度敏感任务的性价比选择" class="headerlink" title="Terra：额度敏感任务的性价比选择"></a>Terra：额度敏感任务的性价比选择</h3><p>如果任务相对轻量，同时比较在意额度消耗，可以优先尝试 Terra。</p><p>按照官方成员的说法，Terra 在部分任务上的表现可以接近 GPT-5.5，但资源消耗更低，比较适合：</p><ul><li>小范围代码修改</li><li>简单脚本生成</li><li>格式调整</li><li>重复性开发工作</li><li>已经明确实现路径的任务</li></ul><p>也就是说，并不是所有任务都需要直接交给最强模型。</p><p>当需求本身足够清晰时，使用更轻量的模型反而可能获得更高的整体效率。</p><h3 id="Luna：适合低成本探索"><a href="#Luna：适合低成本探索" class="headerlink" title="Luna：适合低成本探索"></a>Luna：适合低成本探索</h3><p>对于一些不确定是否值得深入的探索性任务，可以先交给 Luna。</p><p>例如：</p><ul><li>快速浏览项目结构</li><li>初步寻找相关文件</li><li>调查某个功能的实现位置</li><li>尝试生成几个可行方向</li><li>判断问题是否值得升级到更强模型</li></ul><p>Luna 更适合作为一个低成本的“侦察兵”，而不是最终负责复杂修改的主力模型。</p><h3 id="High：模糊-Bug-和跨模块修改"><a href="#High：模糊-Bug-和跨模块修改" class="headerlink" title="High：模糊 Bug 和跨模块修改"></a>High：模糊 Bug 和跨模块修改</h3><p>当问题描述比较模糊，或者修改涉及多个模块时，可以将 Effort 调整到 High。</p><p>常见场景包括：</p><ul><li>无法稳定复现的 Bug</li><li>多个模块之间的状态异常</li><li>大范围重构</li><li>跨前后端联调</li><li>涉及复杂调用链的问题</li></ul><p>这类任务往往不仅需要生成代码，还需要模型建立完整的问题假设，并逐步排除错误方向。</p><h3 id="Ultra：只用于真正不能出错的任务"><a href="#Ultra：只用于真正不能出错的任务" class="headerlink" title="Ultra：只用于真正不能出错的任务"></a>Ultra：只用于真正不能出错的任务</h3><p>官方并不建议将 Ultra 作为常规配置。</p><p>更适合使用 Ultra 的场景包括：</p><ul><li>数据库迁移</li><li>安全相关修改</li><li>生产事故修复</li><li>权限系统调整</li><li>大规模基础设施变更</li><li>一旦出错就可能造成严重损失的任务</li></ul><p>Ultra 的意义不是让所有任务都“更聪明”，而是在高风险任务中换取更多检查、推理和验证。</p><h3 id="xhigh-的收益已经开始递减"><a href="#xhigh-的收益已经开始递减" class="headerlink" title="xhigh 的收益已经开始递减"></a>xhigh 的收益已经开始递减</h3><p>对于最高级别的 xhigh，官方也明确表示，在评测中已经出现明显的收益递减。</p><p>它更适合以下情况：</p><ul><li>任务执行时间很长</li><li>修改范围非常大</li><li>错误成本极高</li><li>需要多轮验证</li><li>用户特别担心模型遗漏边缘情况</li></ul><p>对于普通任务，直接提高到 xhigh 并不一定划算，反而可能带来更慢的速度和更高的额度消耗。</p><h2 id="觉得-GPT-5-6-慢，可能是-Effort-设得太高"><a href="#觉得-GPT-5-6-慢，可能是-Effort-设得太高" class="headerlink" title="觉得 GPT-5.6 慢，可能是 Effort 设得太高"></a>觉得 GPT-5.6 慢，可能是 Effort 设得太高</h2><p>不少从 GPT-5.5 升级到 GPT-5.6 的用户，仍然沿用了之前较高的推理强度设置。</p><p>Codex 团队建议，如果觉得 GPT-5.6 运行速度过慢，可以先检查当前 Effort 是否仍然保持在 GPT-5.5 时期的配置。</p><p>GPT-5.6 在更低 Effort 下，往往已经能够完成过去需要更高推理强度才能完成的任务。</p><p>换句话说，升级模型后，不应机械地保留原有配置。</p><p>更合理的方法是从 Medium 开始，根据任务难度逐步增加，而不是一开始就使用 High、Ultra 或 xhigh。</p><p>官方还提到，Fast mode 可以进一步提升大约 1.5 倍的速度。</p><p>因此，一套比较实用的选择顺序是：</p><ol><li>先尝试 Sol Medium</li><li>简单任务切换到 Terra</li><li>模糊问题再提高到 High</li><li>高风险任务才使用 Ultra</li><li>只有极少数长任务需要 xhigh</li></ol><h2 id="长任务不要只给目标，还要给停止条件"><a href="#长任务不要只给目标，还要给停止条件" class="headerlink" title="长任务不要只给目标，还要给停止条件"></a>长任务不要只给目标，还要给停止条件</h2><p>在长时间运行的 Agent 任务方面，官方推荐使用 <code>/goal</code> 来描述任务目标。</p><p>但仅仅给出目标还不够。</p><p>如果没有清晰的边界和停止条件，Agent 很容易持续探索、反复修改，最终消耗大量 token，却未必能够产生更好的结果。</p><p>官方建议在长任务中明确加入限制条件，例如：</p><ul><li>只允许修改指定目录</li><li>不允许改变公开 API</li><li>最多验证三个假设</li><li>每个假设完成后必须运行测试</li><li>如果所有假设都失败，则停止修改并输出总结</li><li>不允许添加新的依赖</li><li>不允许修改数据库结构</li><li>达到指定时间或尝试次数后结束</li></ul><p>例如，一个比“修复登录 Bug”更合适的任务描述可以写成：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">修复用户偶尔无法登录的问题。</span><br><span class="line"></span><br><span class="line">限制条件：</span><br><span class="line">- 只修改 auth 和 session 目录</span><br><span class="line">- 不改变现有公开 API</span><br><span class="line">- 最多验证三个可能原因</span><br><span class="line">- 每验证一个原因后运行相关测试</span><br><span class="line">- 如果三个方向都失败，停止修改并总结调查结果</span><br></pre></td></tr></table></figure><p>这类停止条件能够避免 Agent 陷入无限尝试，也可以降低模型在长任务中不断扩大修改范围的风险。</p><h2 id="MCP-工具不一定要全部常驻上下文"><a href="#MCP-工具不一定要全部常驻上下文" class="headerlink" title="MCP 工具不一定要全部常驻上下文"></a>MCP 工具不一定要全部常驻上下文</h2><p>MCP 为 Codex 提供了调用外部工具和服务的能力，但如果直接挂载大量 MCP 服务，也会带来明显的上下文开销。</p><p>几十个工具定义长期驻留在上下文中，会占用 token，并增加模型选择错误工具的可能性。</p><p>Codex 团队提出了两个更节省上下文的思路。</p><h3 id="把常用操作封装成-CLI"><a href="#把常用操作封装成-CLI" class="headerlink" title="把常用操作封装成 CLI"></a>把常用操作封装成 CLI</h3><p>第一种方式，是将外部服务操作封装成命令行工具，再通过 Skill 教会 Codex 如何使用。</p><p>例如，不直接加载一整套部署平台的 MCP 工具，而是提供：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">deployctl status</span><br><span class="line">deployctl logs</span><br><span class="line">deployctl release</span><br></pre></td></tr></table></figure><p>然后在 Skill 中描述这些命令的用途和参数。</p><p>这样做的优势是：</p><ul><li>工具定义更短</li><li>上下文占用更低</li><li>调用方式更稳定</li><li>更容易进行权限控制</li><li>可以直接复用现有 Shell 工作流</li></ul><p>对于原本就支持命令行操作的服务，这通常比长期挂载完整 MCP 更高效。</p><h3 id="将专业-MCP-放到专用子-Agent"><a href="#将专业-MCP-放到专用子-Agent" class="headerlink" title="将专业 MCP 放到专用子 Agent"></a>将专业 MCP 放到专用子 Agent</h3><p>第二种方式，是创建一个专用子 Agent，并只为它配置特定 MCP。</p><p>例如可以创建：</p><ul><li>Unreal Engine 专用 Agent</li><li>数据库运维 Agent</li><li>Kubernetes Agent</li><li>浏览器自动化 Agent</li><li>内部文档检索 Agent</li></ul><p>主 Agent 平时不需要加载这些工具，只有遇到对应任务时，才将工作委托给专用 Agent。</p><p>这种模式既可以减少主上下文中的工具数量，也能降低不同工具之间的干扰。</p><h2 id="权限优先使用-Auto-Review"><a href="#权限优先使用-Auto-Review" class="headerlink" title="权限优先使用 Auto Review"></a>权限优先使用 Auto Review</h2><p>在 Codex 权限设置上，官方建议多数情况下使用 <strong>Auto review</strong>，而不是直接开启 <strong>Full access</strong>。</p><p>Full access 虽然能够减少执行过程中的确认步骤，但也意味着 Agent 可以更自由地执行命令、修改文件和访问环境。</p><p>对于日常开发任务，Auto review 通常已经能够在效率与安全之间取得较好的平衡。</p><p>官方尤其提醒 Windows 用户，应更加谨慎地使用 Full access。</p><p>Windows 环境中的 Shell、权限系统、路径处理和脚本行为更加复杂，一些看似普通的命令可能产生超出预期的影响。</p><p>因此，更稳妥的做法是：</p><ul><li>默认使用 Auto review</li><li>仅在可信项目中临时开启更高权限</li><li>限制 Agent 可修改的目录</li><li>对删除、安装和系统级命令进行人工确认</li><li>不要在包含重要个人文件的目录中直接运行高权限 Agent</li></ul><h2 id="Codex、ChatGPT-Work-和普通聊天的额度如何计算"><a href="#Codex、ChatGPT-Work-和普通聊天的额度如何计算" class="headerlink" title="Codex、ChatGPT Work 和普通聊天的额度如何计算"></a>Codex、ChatGPT Work 和普通聊天的额度如何计算</h2><p>这次 AMA 也对不同功能的额度分类做出了解释。</p><p>按照官方的划分：</p><ul><li><strong>Codex</strong> 计入 Agentic 额度</li><li><strong>ChatGPT Work</strong> 计入 Agentic 额度</li><li>普通 ChatGPT 对话不计入 Agentic 额度</li><li>图像生成有独立额度</li><li>文件上传与处理有独立额度</li><li>语音功能也有独立额度</li></ul><p>这意味着，不能简单地将 ChatGPT 中的所有功能都视为共享同一个额度池。</p><p>用户看到某一类功能额度下降，并不一定代表其他功能也会同步受到影响。</p><p>不过具体到单个 Codex 任务，其消耗并不是固定值。</p><p>任务长度、上下文规模、模型、Effort、工具调用次数、测试次数以及是否发生重试，都会影响最终消耗。</p><h2 id="为什么-Pro-mode-没有进入-Codex"><a href="#为什么-Pro-mode-没有进入-Codex" class="headerlink" title="为什么 Pro mode 没有进入 Codex"></a>为什么 Pro mode 没有进入 Codex</h2><p>不少用户询问，既然 ChatGPT 中提供了 Pro mode，为什么 Codex 中没有同样的选项。</p><p>官方给出的解释是，Pro mode 的运行机制对于 Agentic 编程任务的提升相对有限。</p><p>它通常具有以下特点：</p><ul><li>响应速度更慢</li><li>消耗额度更多</li><li>更偏向一次性深度推理</li><li>对连续工具调用和代码执行的帮助没有想象中明显</li></ul><p>因此，Pro mode 更适合：</p><ul><li>搜索</li><li>数学推理</li><li>长文写作</li><li>文档分析</li><li>复杂研究任务</li></ul><p>而 Codex 的核心场景是读取代码、执行命令、修改文件、运行测试并根据结果继续行动。</p><p>在这种 Agentic 工作流中，模型本身的单次推理强度并不是唯一决定因素，工具使用和反馈循环同样重要。</p><h2 id="AMA-没有回答的几个关键问题"><a href="#AMA-没有回答的几个关键问题" class="headerlink" title="AMA 没有回答的几个关键问题"></a>AMA 没有回答的几个关键问题</h2><p>虽然官方分享了许多使用技巧，但用户最关心的一些问题仍然没有获得明确答案。</p><h2 id="GPT-5-6-为什么比-GPT-5-5-更耗额度"><a href="#GPT-5-6-为什么比-GPT-5-5-更耗额度" class="headerlink" title="GPT-5.6 为什么比 GPT-5.5 更耗额度"></a>GPT-5.6 为什么比 GPT-5.5 更耗额度</h2><p>整个 AMA 中呼声最高的问题，仍然是 GPT-5.6 的额度消耗。</p><p>大量用户反馈，GPT-5.6 在实际使用中的额度下降速度明显快于 GPT-5.5。</p><p>这与官方此前强调的“更高 token 效率”形成了明显反差。</p><p>官方对此只解释称：</p><blockquote><p>每个任务的消耗并不是固定的。</p></blockquote><p>这句话本身并没有错。</p><p>复杂任务、更多工具调用、更长输出以及更高 Effort，确实都会增加消耗。</p><p>但它没有正面回答用户真正关心的问题：</p><ul><li>相同任务下，GPT-5.6 是否平均消耗更多额度？</li><li>是否因为内部推理 token 增加？</li><li>是否因为工具调用和验证次数更多？</li><li>Agentic 额度是否采用了不同于文本 token 的权重换算？</li><li>Fast mode 与普通模式的额度计算是否相同？</li><li>官方宣传中的 token 效率，是否不等于用户看到的额度效率？</li></ul><p>这些问题在 AMA 后依然没有答案。</p><h2 id="1M-上下文窗口仍然没有明确计划"><a href="#1M-上下文窗口仍然没有明确计划" class="headerlink" title="1M 上下文窗口仍然没有明确计划"></a>1M 上下文窗口仍然没有明确计划</h2><p>用户同样频繁询问 Codex 是否会提供 1M 上下文窗口。</p><p>官方对此仅表示会认真查看用户反馈，没有给出明确的产品计划或上线时间。</p><p>对于大型代码仓库来说，更大的上下文窗口确实具有吸引力。</p><p>但在实际 Agentic 工作流中，上下文越大，也可能意味着：</p><ul><li>更高的处理成本；</li><li>更慢的首次响应；</li><li>更多无关代码进入上下文；</li><li>更复杂的信息筛选；</li><li>更快的额度消耗。</li></ul><p>因此，1M 上下文是否能够真正改善 Codex 体验，仍然取决于检索、压缩和上下文管理能力，而不只是数字本身。</p><p>在价格方面，官方也明确表示无法承诺长期稳定。</p><h2 id="新版-ChatGPT-桌面应用遭到集中吐槽"><a href="#新版-ChatGPT-桌面应用遭到集中吐槽" class="headerlink" title="新版 ChatGPT 桌面应用遭到集中吐槽"></a>新版 ChatGPT 桌面应用遭到集中吐槽</h2><p>新版 ChatGPT 桌面应用是 AMA 中另一个争议集中的话题。</p><p>不少用户认为，新应用更偏向 ChatGPT Work 和 Agent 操作，而传统 Chat 功能则被压缩成了一个附属面板。</p><p>用户集中反馈缺失或体验退步的功能包括：</p><ul><li>Projects</li><li>完整历史记录</li><li>常用快捷键</li><li>录音功能</li><li>原有聊天工作流</li><li>Classic 应用中的部分导航体验</li></ul><p>官方承认新版应用仍在改进。</p><p>但目前给出的短期方案，基本上仍然是同时保留并使用两个应用：</p><ul><li>需要传统聊天功能时使用 Classic；</li><li>需要 Agent 和 Work 功能时使用新版应用。</li></ul><p>这显然称不上理想的解决方案。</p><h2 id="Linux-没有时间表，Windows-仍是二等公民"><a href="#Linux-没有时间表，Windows-仍是二等公民" class="headerlink" title="Linux 没有时间表，Windows 仍是二等公民"></a>Linux 没有时间表，Windows 仍是二等公民</h2><p>对于 Linux 桌面版，官方确认相关工作正在进行，但没有提供具体时间线。</p><p>而 Windows 用户长期存在的体验差距，也在 AMA 中再次被提及。</p><p>官方事实上承认，Windows 版本在过去长期处于相对次要的位置。</p><p>这种差距不仅体现在桌面应用，也体现在 Agent 开发环境中：</p><ul><li>Shell 行为与 macOS、Linux 不一致；</li><li>路径和权限处理更复杂；</li><li>部分开发工具优先适配 Unix 环境；</li><li>沙箱能力存在差异；</li><li>自动化脚本的兼容性更差；</li><li>部分功能在 Windows 上更晚推出。</li></ul><p>对于将 Codex 作为主要开发工具的 Windows 用户来说，这仍然是一个现实问题。</p><h2 id="Reward-Hacking-问题被礼貌绕开"><a href="#Reward-Hacking-问题被礼貌绕开" class="headerlink" title="Reward Hacking 问题被礼貌绕开"></a>Reward Hacking 问题被礼貌绕开</h2><p>还有用户追问了 METR 报告中提到的 reward hacking 问题。</p><p>问题主要集中在：</p><ul><li>基准成绩提升中有多少来自 reward hacking</li><li>模型是否学会针对评测环境优化行为</li><li>GPT-5.6 的训练中做了哪些针对性修改</li><li>官方如何区分真实能力提升和评测策略优化</li></ul><p>Codex 团队没有给出具体数据，也没有详细解释训练层面的改动。</p><p>这类问题涉及模型训练、内部评估方法和安全研究，官方选择谨慎回应并不意外。</p><p>但从用户角度看，这也意味着外界仍然难以判断：</p><blockquote><p>模型在基准上的提升，有多少能够稳定转化为真实开发环境中的可靠性。</p></blockquote><h2 id="怎么用更省已经讲清楚，为什么更费仍然悬而未决"><a href="#怎么用更省已经讲清楚，为什么更费仍然悬而未决" class="headerlink" title="怎么用更省已经讲清楚，为什么更费仍然悬而未决"></a>怎么用更省已经讲清楚，为什么更费仍然悬而未决</h2><p>总体来看，这次 Codex 团队 AMA 的价值主要集中在实际使用方法上。</p><p>官方给出的建议相当明确：</p><ul><li>日常默认使用 Sol Medium</li><li>轻量任务优先尝试 Terra</li><li>探索性工作可以委托给 Luna</li><li>模糊 Bug 和跨模块任务使用 High</li><li>Ultra 只留给高风险任务</li><li>xhigh 不应成为日常默认</li><li>长任务必须设置停止条件</li><li>不要让大量 MCP 工具长期常驻上下文</li><li>优先使用 Auto review，而不是 Full access</li><li>GPT-5.6 不一定需要沿用 GPT-5.5 的高 Effort 设置</li></ul><p>这些建议的共同目标都是降低不必要的模型调用、上下文占用和推理消耗。</p><p>但另一方面，用户最关心的问题依然没有获得正面回应：</p><blockquote><p>为什么 GPT-5.6 明明宣传 token 效率更高，实际使用时却更快消耗 Codex 额度？</p></blockquote><p>如果 Agentic 额度并不直接等于输入输出 token，那么官方就需要更清晰地解释其计算方式。</p><p>如果 GPT-5.6 由于更频繁的工具调用、更长的内部推理或更主动的验证而消耗更高，也应该让用户能够看到这些差异。</p><p>否则，用户最终只能通过反复试验来猜测每种模型和 Effort 的真实成本。</p><p>这场 AMA 讲清楚了 Codex 应该“怎么用更省”。</p><p>至于它为什么“变得更费”，仍然是一个没有被回答的问题。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;7 月 10 日，OpenAI Codex 团队在 Reddit 举办了一场 &lt;a href=&quot;https://www.reddit.com/r/codex/comments/1us9ty9/ama_with_openais_codex_team/&quot;&gt;AMA&lt;/a&gt;（Ask</summary>
      
    
    
    
    <category term="资讯" scheme="https://ooo.run/categories/%E8%B5%84%E8%AE%AF/"/>
    
    
    <category term="OpenAI" scheme="https://ooo.run/tags/OpenAI/"/>
    
    <category term="ChatGPT" scheme="https://ooo.run/tags/ChatGPT/"/>
    
    <category term="Codex" scheme="https://ooo.run/tags/Codex/"/>
    
    <category term="GPT-5.6" scheme="https://ooo.run/tags/GPT-5-6/"/>
    
    <category term="AI Agent" scheme="https://ooo.run/tags/AI-Agent/"/>
    
  </entry>
  
  <entry>
    <title>OpenAI 发布 GPT-5.6 与 ChatGPT Work，重塑 AI 工作模式</title>
    <link href="https://ooo.run/post/openai-release-gpt-5-6.html"/>
    <id>https://ooo.run/post/openai-release-gpt-5-6.html</id>
    <published>2026-07-09T19:47:35.000Z</published>
    <updated>2026-07-09T20:06:55.456Z</updated>
    
    <content type="html"><![CDATA[<p>北京时间 2026 年 7 月 10 日凌晨，OpenAI 正式推出 GPT-5.6 模型以及全新 ChatGPT Work 智能体，标志着 AI 从对话助手向自主工作平台的转变。</p><h2 id="GPT-5-6：性能全面跃升"><a href="#GPT-5-6：性能全面跃升" class="headerlink" title="GPT-5.6：性能全面跃升"></a>GPT-5.6：性能全面跃升</h2><p>GPT-5.6 已于今日开始在 ChatGPT、Codex 和 OpenAI API 全球逐步推出。</p><blockquote><p>PRO 用户已全面完成更新，Plus 用户可能看不到 <strong>GPT-5.6 SOL</strong> 模型的选项，预计在 24 小时内全面可用。 </p></blockquote><ul><li><strong>ChatGPT 用户</strong>：Plus、Pro、Business 和 Enterprise 用户可通过中等及以上思考等级设置访问 GPT-5.6 Sol；Pro 和 Enterprise 用户还可选择 GPT-5.6 Pro 以获得复杂任务的最高质量输出。</li><li><strong>核心能力提升</strong>：在推理复杂任务、遵循模板、参考文件和偏好风格生成材料方面达到业界领先。只需描述期望结果，无需一步步指导。 </li><li><strong>工件质量</strong>：显著提升演示文稿、文档和电子表格的质量，支持导出到专业工具并融入企业工作流。</li><li><strong>设计判断力</strong>：增强的计算机使用能力让模型能“查看并优化”渲染结果，而非仅生成代码或内容，从而自动捕捉视觉和功能问题并进行润色。 </li><li><strong>Ultra 模式</strong>：最高性能设置，通过并行协调多个智能体加速最复杂工作（以更高 token 消耗换取更强更快的结果）。</li><li><strong>基准表现</strong>： OpenAI 提供的基准测试得分情况<ul><li><a href="https://x.com/OpenAI/status/2075271425548795909">Artificial Analysis Coding Agent Index</a>：80.0（领先 Claude Fable 5 达 2.8 分），使用更少 token、更短时间且成本约三分之一。 </li><li><a href="https://x.com/OpenAI/status/2075271423992680532">Agents Last Exam</a>：53.6（领先 Claude Fable 5 达 13.1 分）；中等推理下以约四分之一成本领先 11.4 分。</li></ul></li></ul><h2 id="ChatGPT-Work：AI-自主完成整个工作流"><a href="#ChatGPT-Work：AI-自主完成整个工作流" class="headerlink" title="ChatGPT Work：AI 自主完成整个工作流"></a>ChatGPT Work：AI 自主完成整个工作流</h2><p><strong>ChatGPT Work</strong> 是基于 Codex 和 GPT-5.6 驱动的新智能体，能跨应用和文件采取行动，可长时间持续项目，将单一目标转化为完成的工作。 </p><p><strong>主要特性：</strong> </p><ul><li>理解用户目标，利用选定应用和文件上下文；</li><li>自主创建精美文档、幻灯片、分析、网站和报告；</li><li>支持整个工作流单次请求完成，用户始终保持控制权；</li><li>反映 AI 使用从“提问”向“真正完成工作”的转变。</li></ul><p><strong>可用性：</strong> </p><ul><li><strong>Web 和移动端</strong>：今日起向 Pro、Enterprise 和 Edu 计划推出；Plus 和 Business 计划未来几天内跟进。</li><li><strong>桌面应用</strong>：Chat、Work 和 Codex 在所有计划（含 Free）可用，已全球支持 Windows 和 Mac 下载。原有 Codex 应用用户更新即可切换为新 ChatGPT 桌面应用。</li></ul><p>OpenAI 表示，这一发布体现了 AI 正在成为生产力核心工具，用户只需提出目标，AI 即可自主推进并交付成果。更多细节和演示可通过 <a href="https://x.com/OpenAI/status/2075274271845404744">OpenAI 官方账号</a> 查看。 </p><p>此更新进一步巩固 OpenAI 在前沿 AI 模型和实用智能体领域的领先地位。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;北京时间 2026 年 7 月 10 日凌晨，OpenAI 正式推出 GPT-5.6 模型以及全新 ChatGPT Work 智能体，标志着 AI 从对话助手向自主工作平台的转变。&lt;/p&gt;
&lt;h2 id=&quot;GPT-5-6：性能全面跃升&quot;&gt;&lt;a href=&quot;#GPT-5-6：</summary>
      
    
    
    
    <category term="资讯" scheme="https://ooo.run/categories/%E8%B5%84%E8%AE%AF/"/>
    
    
    <category term="AI" scheme="https://ooo.run/tags/AI/"/>
    
    <category term="OpenAI" scheme="https://ooo.run/tags/OpenAI/"/>
    
    <category term="ChatGPT" scheme="https://ooo.run/tags/ChatGPT/"/>
    
    <category term="Codex" scheme="https://ooo.run/tags/Codex/"/>
    
    <category term="GPT" scheme="https://ooo.run/tags/GPT/"/>
    
  </entry>
  
  <entry>
    <title>在不设置 SMTP 的情况下修改 Vaultwarden(Bitwarden) 的账户邮箱</title>
    <link href="https://ooo.run/post/change-vaultwarden-account-email-without-set-smtp.html"/>
    <id>https://ooo.run/post/change-vaultwarden-account-email-without-set-smtp.html</id>
    <published>2026-07-09T05:47:52.000Z</published>
    <updated>2026-07-09T06:21:57.249Z</updated>
    
    <content type="html"><![CDATA[<p>Vaultwarden 更改登录邮箱时，默认需要向新邮箱发送验证码进行验证，如果没配置 SMTP，验证码不会真正发出。但在 <code>LOG_LEVEL=debug</code> 时会把验证码打印到日志里。如果你也只是个人使用，且不想设置 SMTP，可以查看下面的方法获取验证码，完成修改。</p><blockquote><p>本教程适用于使用 Docker 部署的 Vaultwarden</p></blockquote><div class="flatpaper-note flatpaper-note--danger"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p>更改账户邮箱会导致所有会话失效，需要重新登录</p></div></div><h2 id="1-临时开启-debug-日志"><a href="#1-临时开启-debug-日志" class="headerlink" title="1. 临时开启 debug 日志"></a>1. 临时开启 debug 日志</h2><p>Docker Compose 里给 <code>vaultwarden</code> 加上：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">environment:</span></span><br><span class="line">  <span class="attr">LOG_LEVEL:</span> <span class="string">debug</span></span><br><span class="line">  <span class="attr">EXTENDED_LOGGING:</span> <span class="string">&quot;true&quot;</span></span><br></pre></td></tr></table></figure><p>然后重启：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker compose up -d</span><br></pre></td></tr></table></figure><p>如果你是 <code>docker run</code> ，加：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">-e LOG_LEVEL=debug \</span><br><span class="line">-e EXTENDED_LOGGING=<span class="literal">true</span> \</span><br></pre></td></tr></table></figure><h2 id="2-重新触发一次“更改邮箱”"><a href="#2-重新触发一次“更改邮箱”" class="headerlink" title="2. 重新触发一次“更改邮箱”"></a>2. 重新触发一次“更改邮箱”</h2><p>在网页端再次提交更改邮箱，让 Vaultwarden 重新生成验证码。</p><h2 id="3-查看-Docker-日志"><a href="#3-查看-Docker-日志" class="headerlink" title="3. 查看 Docker 日志"></a>3. 查看 Docker 日志</h2><p>容器名如果叫 <code>vaultwarden</code> ：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker logs vaultwarden 2&gt;&amp;1 | grep -i <span class="string">&quot;email&quot;</span></span><br></pre></td></tr></table></figure><p>输出的日志大概会是类似：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">...[vaultwarden::api::core::accounts][DEBUG] Email change ... email (...) with token (123456)</span><br></pre></td></tr></table></figure><p>日志末尾括号中的六位数字，就是需要填写的验证码。</p><h2 id="4-完成后改回正常日志级别"><a href="#4-完成后改回正常日志级别" class="headerlink" title="4. 完成后改回正常日志级别"></a>4. 完成后改回正常日志级别</h2><p>查到验证码并完成更改后，建议改回：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">LOG_LEVEL:</span> <span class="string">info</span></span><br></pre></td></tr></table></figure><p>或：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">LOG_LEVEL:</span> <span class="string">warn</span></span><br></pre></td></tr></table></figure><p>然后重启。 <code>debug</code> 日志可能暴露敏感信息，不建议长期打开。</p><h2 id="5-长期建议：配置-SMTP"><a href="#5-长期建议：配置-SMTP" class="headerlink" title="5. 长期建议：配置 SMTP"></a>5. 长期建议：配置 SMTP</h2><p>如果以后还会用邮箱验证、邀请、2FA 邮件等功能，最好配置 SMTP。 <strong>Vaultwarden</strong> 常用的 SMTP 配置项包括：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">SMTP_HOST:</span> <span class="string">smtp.example.com</span></span><br><span class="line"><span class="attr">SMTP_FROM:</span> <span class="string">vaultwarden@example.com</span></span><br><span class="line"><span class="attr">SMTP_PORT:</span> <span class="number">587</span></span><br><span class="line"><span class="attr">SMTP_SECURITY:</span> <span class="string">starttls</span></span><br><span class="line"><span class="attr">SMTP_USERNAME:</span> <span class="string">vaultwarden@example.com</span></span><br><span class="line"><span class="attr">SMTP_PASSWORD:</span> <span class="string">your_password</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Vaultwarden 更改登录邮箱时，默认需要向新邮箱发送验证码进行验证，如果没配置 SMTP，验证码不会真正发出。但在 &lt;code&gt;LOG_LEVEL=debug&lt;/code&gt; 时会把验证码打印到日志里。如果你也只是个人使用，且不想设置 SMTP，可以查看下面的方法获取</summary>
      
    
    
    
    <category term="教程" scheme="https://ooo.run/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="Docker" scheme="https://ooo.run/tags/Docker/"/>
    
    <category term="Bitwarden" scheme="https://ooo.run/tags/Bitwarden/"/>
    
    <category term="Vaultwarden" scheme="https://ooo.run/tags/Vaultwarden/"/>
    
  </entry>
  
  <entry>
    <title>Docker Compose 新增 Init Containers：终于不用再写一堆一次性初始化服务了</title>
    <link href="https://ooo.run/post/docker-compose-init-containers.html"/>
    <id>https://ooo.run/post/docker-compose-init-containers.html</id>
    <published>2026-07-04T03:00:00.000Z</published>
    <updated>2026-07-04T04:16:51.110Z</updated>
    
    <content type="html"><![CDATA[<p>在使用 Docker Compose 部署应用时，你是否也曾为“如何在主应用启动前优雅地运行数据库迁移或修复权限”而烦恼过？</p><p>过去，我们不得不编写各种一次性服务并用复杂的 <code>depends_on</code> 串联。而现在，随着 Docker Compose 新特性的发布，我们终于迎来了官方的 <strong>Init Containers</strong> 支持。本文将带你一探究竟，看看它如何帮我们精简 <code>compose.yaml</code>！</p><span id="more"></span><p>在使用 <strong>Docker Compose</strong> 部署应用时，我们经常会遇到一种很常见的需求：在应用启动之前，先执行一些初始化任务。</p><p>例如：</p><ul><li>启动 Web 服务之前，先执行数据库迁移</li><li>容器以非 root 用户运行前，先修复挂载目录权限</li><li>应用正式启动前，先生成配置文件</li><li>先导入初始化数据，再启动主服务</li></ul><p>过去我们通常会单独定义一个 <code>migrate</code>、<code>init</code>、<code>setup</code> 之类的一次性服务，然后通过 <code>depends_on</code> 和 <code>condition: service_completed_successfully</code> 控制启动顺序。</p><p>现在，<strong>Docker Compose</strong> 正式提供了更自然的写法：<strong>Init Containers</strong>。</p><div class="flatpaper-note flatpaper-note--info"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p>根据 Docker 官方文档，该功能需要 <strong>Docker Compose 5.3.0</strong> 及以上版本。</p></div></div><p>Init Containers 本质上是 short-lived（短生命周期）容器，会在主服务容器启动之前依次执行；如果其中任何一步返回非 0 退出码，主服务就不会启动。</p><h2 id="什么是-Init-Containers？"><a href="#什么是-Init-Containers？" class="headerlink" title="什么是 Init Containers？"></a>什么是 Init Containers？</h2><p>Init Containers 可以理解为：</p><blockquote><p>绑定在某个服务启动前执行的一组初始化步骤。</p></blockquote><p>它们不是长期运行的服务，也不是后台任务，而是“跑完就退出”的临时容器。</p><p><strong>Docker Compose</strong> 中这个能力通过 <code>pre_start</code> 生命周期钩子实现。根据官方文档说明，<code>pre_start</code> 中的每个步骤都会在独立的临时容器中运行，这些容器会在服务容器创建之后、真正启动之前执行。</p><p>一个最简单的例子：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">pre_start:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">command:</span> [<span class="string">&quot;./manage.py&quot;</span>, <span class="string">&quot;migrate&quot;</span>]</span><br></pre></td></tr></table></figure><p>这段配置表示：</p><ol><li><strong>Docker Compose</strong> 先创建 <code>app</code> 服务容器；</li><li>在 <code>app</code> 真正启动之前，先运行 <code>./manage.py migrate</code>；</li><li>如果迁移命令成功退出（即返回状态码 <code>0</code>），<code>app</code> 才会启动；</li><li>如果迁移失败，<code>app</code> 不会启动。</li></ol><p>这比过去单独写一个 <code>migrate</code> 服务清晰很多。</p><h2 id="以前我们是怎么做的？"><a href="#以前我们是怎么做的？" class="headerlink" title="以前我们是怎么做的？"></a>以前我们是怎么做的？</h2><p>在 <code>pre_start</code> 出现之前，如果想表达“先执行迁移，再启动应用”，通常会这样写：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">migrate:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">command:</span> [<span class="string">&quot;./manage.py&quot;</span>, <span class="string">&quot;migrate&quot;</span>]</span><br><span class="line">    <span class="attr">restart:</span> <span class="string">&quot;no&quot;</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="attr">migrate:</span></span><br><span class="line">        <span class="attr">condition:</span> <span class="string">service_completed_successfully</span></span><br></pre></td></tr></table></figure><p>这种写法虽然可以工作，但存在以下几个明显的问题：</p><ul><li><strong>概念混淆</strong>：<code>migrate</code> 本质上并不是一个真正的长期运行服务，它只是 <code>app</code> 启动前的一个初始化步骤。把它放在 <code>services</code> 顶层，会让整个 Compose 配置文件显得臃肿。</li><li><strong>状态残留</strong>：任务执行完成后，它会作为已退出的服务留在 <code>docker compose ps</code> 列表中，使得容器服务列表不够清爽。</li><li><strong>编排繁琐</strong>：如果初始化步骤较多（比如先迁移数据库、再导入默认数据、最后生成配置文件），就需要定义多个一次性服务，并用一堆复杂的 <code>depends_on</code> 串联起来。</li></ul><p>使用新的 <code>pre_start</code> 特性后，我们可以直接把它们收纳进服务内部：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">pre_start:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">command:</span> [<span class="string">&quot;./manage.py&quot;</span>, <span class="string">&quot;migrate&quot;</span>]</span><br><span class="line">      <span class="bullet">-</span> <span class="attr">command:</span> [<span class="string">&quot;./manage.py&quot;</span>, <span class="string">&quot;loaddata&quot;</span>, <span class="string">&quot;fixtures.json&quot;</span>]</span><br></pre></td></tr></table></figure><p><strong>Docker</strong> 官方也明确指出，<code>pre_start</code> 的优势在于：</p><ol><li>初始化逻辑作为服务的<strong>从属步骤</strong>表达，不再伪装成并列的独立服务；</li><li>已完成的临时步骤不会出现在 <code>docker compose ps</code> 中，保持环境整洁；</li><li>多个步骤按顺序执行，无需再通过复杂的 <code>depends_on</code> 逻辑进行链式串联。</li></ol><h2 id="示例一：启动前执行数据库迁移"><a href="#示例一：启动前执行数据库迁移" class="headerlink" title="示例一：启动前执行数据库迁移"></a>示例一：启动前执行数据库迁移</h2><p>这是最典型的使用场景。</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="attr">db:</span></span><br><span class="line">        <span class="attr">condition:</span> <span class="string">service_healthy</span></span><br><span class="line">    <span class="attr">pre_start:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">command:</span> [<span class="string">&quot;./manage.py&quot;</span>, <span class="string">&quot;migrate&quot;</span>]</span><br><span class="line"></span><br><span class="line">  <span class="attr">db:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">postgres:18</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">POSTGRES_USER:</span> <span class="string">app</span></span><br><span class="line">      <span class="attr">POSTGRES_PASSWORD:</span> <span class="string">password</span></span><br><span class="line">      <span class="attr">POSTGRES_DB:</span> <span class="string">app</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD-SHELL&quot;</span>, <span class="string">&quot;pg_isready -U $$&#123;POSTGRES_USER&#125; -d $$&#123;POSTGRES_DB&#125;&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">10s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">5</span></span><br><span class="line">      <span class="attr">start_period:</span> <span class="string">30s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">10s</span></span><br></pre></td></tr></table></figure><p>这里有两个关键点：</p><ol><li><strong>依赖关系</strong>：<code>app</code> 通过 <code>depends_on</code> 等待 <code>db</code> 容器进入 <code>service_healthy</code>（健康）状态。</li><li><strong>初始化时机</strong>：在 <code>app</code> 真正启动前，会先在临时容器中执行 <code>./manage.py migrate</code>。</li></ol><p>若数据库迁移成功，<code>app</code> 主服务会继续启动；若失败，<code>app</code> 不会启动，且相关错误日志会直接输出在 <code>docker compose up</code> 中。</p><p>这种设计非常适合 <strong>Django</strong>、<strong>Rails</strong>、<strong>Laravel</strong>、<strong>Prisma</strong>、<strong>Drizzle</strong>、<strong>Alembic</strong> 等需要在服务运行前进行表结构迁移的项目。</p><h2 id="示例二：修复-Volume-权限"><a href="#示例二：修复-Volume-权限" class="headerlink" title="示例二：修复 Volume 权限"></a>示例二：修复 Volume 权限</h2><p>另一个痛点是权限问题：当服务本身以非 root 用户运行，但挂载的 <strong>Docker named volume</strong> 默认归属于 root 权限时，容器可能会因为没有写入权限而崩溃。</p><p>过去，我们可能需要在 <code>Dockerfile</code> 里大动干戈，或者单独拉起一个辅助服务。现在，使用 <code>pre_start</code> 可以非常轻量地搞定：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">user:</span> <span class="string">&quot;1000:1000&quot;</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">data:/data</span></span><br><span class="line">    <span class="attr">pre_start:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">image:</span> <span class="string">busybox</span></span><br><span class="line">        <span class="attr">user:</span> <span class="string">root</span></span><br><span class="line">        <span class="attr">command:</span> <span class="string">sh</span> <span class="string">-c</span> <span class="string">&#x27;chown -R 1000:1000 /data&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">volumes:</span></span><br><span class="line">  <span class="attr">data:</span></span><br></pre></td></tr></table></figure><p>在这个例子中：</p><ul><li><code>app</code> 容器以 <code>1000:1000</code> 非 root 用户运行。</li><li><code>pre_start</code> 步骤指定了覆盖镜像为 <code>busybox</code>，并以 <code>root</code> 权限执行 <code>chown</code>，从而在主服务运行前顺利修正挂载目录所有权。</li></ul><p>该场景在自托管&#x2F;开源应用部署中极度实用，例如：</p><ul><li>修复上传&#x2F;缓存目录权限；</li><li>自动初始化数据目录结构；</li><li>在挂载路径中提前生成默认配置文件。</li></ul><h2 id="示例三：串联多个初始化步骤"><a href="#示例三：串联多个初始化步骤" class="headerlink" title="示例三：串联多个初始化步骤"></a>示例三：串联多个初始化步骤</h2><p><code>pre_start</code> 支持定义一个步骤列表，并会按照声明顺序<strong>串行执行</strong>。只有当前一个步骤成功退出（返回 <code>0</code>）时，才会继续运行下一个步骤；若中间某一步失败，后续步骤和主服务都将终止。</p><p>例如：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="attr">db:</span></span><br><span class="line">        <span class="attr">condition:</span> <span class="string">service_healthy</span></span><br><span class="line">    <span class="attr">pre_start:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">command:</span> [<span class="string">&quot;./manage.py&quot;</span>, <span class="string">&quot;migrate&quot;</span>]</span><br><span class="line">      <span class="bullet">-</span> <span class="attr">command:</span> [<span class="string">&quot;./manage.py&quot;</span>, <span class="string">&quot;loaddata&quot;</span>, <span class="string">&quot;fixtures.json&quot;</span>]</span><br><span class="line">      <span class="bullet">-</span> <span class="attr">command:</span> [<span class="string">&quot;./scripts/generate-config.sh&quot;</span>]</span><br><span class="line"></span><br><span class="line">  <span class="attr">db:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">postgres:18</span></span><br></pre></td></tr></table></figure><p>整个启动流为：</p><ol><li><strong>等待</strong>数据库容器进入健康状态；</li><li><strong>执行</strong>数据库表结构迁移；</li><li><strong>导入</strong>系统初始数据；</li><li><strong>生成</strong>动态配置文件；</li><li><strong>拉起</strong>主应用容器。</li></ol><div class="flatpaper-note flatpaper-note--warning"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p>需要注意的是，<code>pre_start</code> 中的多个步骤<strong>并不是事务</strong>。如果第二步执行成功、第三步失败，<strong>Docker Compose</strong> 不会自动回滚第二步。<br>因此，强烈建议将初始化脚本设计为<strong>可重复运行的幂等逻辑</strong>。</p></div></div><p>例如在导入数据时：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 不推荐：每次无脑插入，可能会导致主键冲突或数据重复</span></span><br><span class="line"><span class="keyword">INSERT INTO</span> users (id, name) <span class="keyword">VALUES</span> (<span class="number">1</span>, <span class="string">&#x27;admin&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 推荐：检测到冲突时跳过，保证幂等性</span></span><br><span class="line"><span class="keyword">INSERT INTO</span> users (id, name) <span class="keyword">VALUES</span> (<span class="number">1</span>, <span class="string">&#x27;admin&#x27;</span>)</span><br><span class="line"><span class="keyword">ON</span> CONFLICT (id) DO NOTHING;</span><br></pre></td></tr></table></figure><h2 id="pre-start-容器的运行规则"><a href="#pre-start-容器的运行规则" class="headerlink" title="pre_start 容器的运行规则"></a><code>pre_start</code> 容器的运行规则</h2><p>根据官方文档说明，<code>pre_start</code> 步骤拉起的临时容器具有以下行为特征：</p><ul><li><strong>独立容器</strong>：每个步骤都在自己专属的临时容器中运行。</li><li><strong>默认继承</strong>：默认继承当前宿主服务的 <code>image</code> 定义，无需重复指定镜像。</li><li><strong>允许覆盖</strong>：可以通过 <code>image</code> 字段指定其他的轻量工具镜像（如 <code>busybox</code>）。</li><li><strong>同网共用</strong>：会自动加入当前宿主服务所在的网络，因此可以直接访问通过 <code>depends_on</code> 声明的其他依赖服务。</li><li><strong>共享卷挂载</strong>：会自动共享当前服务定义的所有 <code>volumes</code> 挂载。</li><li><strong>强状态约束</strong>：必须返回退出码 <code>0</code>，下一个步骤及主服务才会继续运行。</li></ul><p>这些特性为我们编写配置带来了很大便利。例如，若迁移命令就存放在应用镜像内，你只需直接声明命令，无需重复书写镜像名称：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">pre_start:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">command:</span> [<span class="string">&quot;pnpm&quot;</span>, <span class="string">&quot;db:migrate&quot;</span>]</span><br></pre></td></tr></table></figure><p>如果需要使用辅助镜像（如 <code>busybox</code>）来做文件操作，直接在步骤内声明 <code>image</code> 即可进行覆盖：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">pre_start:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">image:</span> <span class="string">busybox</span></span><br><span class="line">    <span class="attr">user:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">command:</span> <span class="string">sh</span> <span class="string">-c</span> <span class="string">&#x27;chown -R 1000:1000 /data&#x27;</span></span><br></pre></td></tr></table></figure><p>因为共享了同一网络与 <code>volumes</code>，初始化容器在挂载目录中写入的动态配置文件、修正的权限或是写入的数据，在主容器拉起后会立刻生效。</p><h2 id="它会每次-docker-compose-up-都执行吗？"><a href="#它会每次-docker-compose-up-都执行吗？" class="headerlink" title="它会每次 docker compose up 都执行吗？"></a>它会每次 <code>docker compose up</code> 都执行吗？</h2><p>答案是：<strong>不会</strong>。这是一个非常关键的细节。</p><p>根据 Docker 官方文档：</p><ul><li>如果某个 <code>pre_start</code> 步骤在上一次部署中已经<strong>成功执行</strong>过，且其<strong>定义没有发生任何变化</strong>，那么后续执行 <code>docker compose up</code> 时，Compose 会<strong>自动跳过</strong>该步骤。</li><li>当服务因 <code>restart</code> 策略发生重启时，<strong>不会</strong>重新触发 <code>pre_start</code>。</li><li><strong>只有在以下情况</strong>下，初始化步骤才会再次执行：<ol><li>步骤的配置定义发生变更；</li><li>上一次执行失败（退出码非 0）；</li><li>执行 <code>docker compose up --force-recreate</code> 强制重建服务。</li></ol></li></ul><p>由此可见，<code>pre_start</code> 偏向于“宿主服务生命周期中的一次性部署初始化”，而不是“每次容器进程启动前的强制拦截”。</p><div class="flatpaper-note flatpaper-note--info"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p><strong>提示</strong>： 如果你有一些需要在每次容器重启、扩容或进程拉起时都必定运行的逻辑（如动态读取最新环境变量），建议依然将其写入镜像的 <code>entrypoint.sh</code> 入口脚本中。</p></div></div><h2 id="什么时候不适合使用-Init-Containers？"><a href="#什么时候不适合使用-Init-Containers？" class="headerlink" title="什么时候不适合使用 Init Containers？"></a>什么时候不适合使用 Init Containers？</h2><p>Init Containers 虽然方便，但并非银弹。根据官方文档的建议，如果你的需求仅是注入静态配置文件或密钥，应当优先使用 <strong>Docker Compose</strong> 原生的 <code>configs</code> 和 <code>secrets</code>，因为它们支持直接挂载，并允许精细化配置权限和所属用户。</p><p>以下场景不建议使用 <code>pre_start</code>：</p><h3 id="1-静态配置文件挂载"><a href="#1-静态配置文件挂载" class="headerlink" title="1. 静态配置文件挂载"></a>1. 静态配置文件挂载</h3><p>对于不需要动态生成的固定配置文件，直接挂载即可，无需启动一个额外的初始化容器去写文件。</p><p><strong>推荐方案：</strong></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">configs:</span></span><br><span class="line">  <span class="attr">app_config:</span></span><br><span class="line">    <span class="attr">file:</span> <span class="string">./config/app.yml</span></span><br><span class="line"></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">configs:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">source:</span> <span class="string">app_config</span></span><br><span class="line">        <span class="attr">target:</span> <span class="string">/app/config.yml</span></span><br></pre></td></tr></table></figure><h3 id="2-敏感凭证-Secret-注入"><a href="#2-敏感凭证-Secret-注入" class="headerlink" title="2. 敏感凭证 (Secret) 注入"></a>2. 敏感凭证 (Secret) 注入</h3><p>数据库密码、API 密钥等敏感数据切忌通过初始化脚本写入 volume 或文件系统，以防泄露。</p><p><strong>推荐方案：</strong></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">secrets:</span></span><br><span class="line">  <span class="attr">db_password:</span></span><br><span class="line">    <span class="attr">file:</span> <span class="string">./secrets/db_password.txt</span></span><br><span class="line"></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">secrets:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">db_password</span></span><br></pre></td></tr></table></figure><h3 id="3-定时任务与后台运维任务"><a href="#3-定时任务与后台运维任务" class="headerlink" title="3. 定时任务与后台运维任务"></a>3. 定时任务与后台运维任务</h3><p>例如：</p><ul><li>定期数据备份</li><li>定期清理缓存与临时文件</li><li>容器销毁后的退出清理工作</li></ul><p>这些任务并不属于“主应用启动前必须阻塞完成的必要依赖”，因此不适合放进 <code>pre_start</code>。</p><h2 id="当前的设计限制"><a href="#当前的设计限制" class="headerlink" title="当前的设计限制"></a>当前的设计限制</h2><p>由于该特性还相对较新，在使用时需要注意以下局限性：</p><ul><li><strong>非副本级执行</strong>：<code>pre_start</code> 是针对服务整体执行一次，而非针对每个容器副本单独运行（目前尚不支持 <code>per_replica: true</code> 配置）。</li><li><strong>部分挂载类型不兼容</strong>：多副本共享的命名卷（Named Volume）和绑定挂载（Bind Mount）能够完美适配；但对于每个实例完全独立的匿名卷或 <code>tmpfs</code> 挂载，<code>pre_start</code> 临时容器写入的数据是无法同步到主容器的。</li><li><strong>扩容时不触发</strong>：当你执行扩容命令时（例如 <code>docker compose up --scale app=3</code>），新创建的副本容器<strong>不会</strong>再次触发 <code>pre_start</code> 执行。它依然只遵循“配置变更&#x2F;强制重建”的触发逻辑。</li></ul><p>因此，如果你的某些初始化逻辑（如本地缓存预热）必须在每一个容器副本里运行，目前请不要依赖 <code>pre_start</code>。</p><h2 id="与-Kubernetes-Init-Containers-的区别"><a href="#与-Kubernetes-Init-Containers-的区别" class="headerlink" title="与 Kubernetes Init Containers 的区别"></a>与 Kubernetes Init Containers 的区别</h2><p>从概念上看，两者的目的非常一致：都在主业务容器拉起前执行前置准备。</p><p>但实现和能力上有所差异：</p><ul><li><strong>Kubernetes (K8s)</strong> 的 Init Containers 是 Pod 级别的核心一等公民，高度契合云原生分布式调度，且天然对多副本容器进行各自初始化。</li><li><strong>Docker Compose</strong> 的 Init Containers 则是通过 <code>pre_start</code> 生命周期钩子实现的一种<strong>轻量级解决方案</strong>。它更契合单机部署、本地开发、小规模自托管（Self-Hosted）场景。</li></ul><p>简单来说，<strong>Docker Compose 的 Init Containers 是为 Compose 场景量身定制的精简版初始化机制</strong>，小巧但十分够用。</p><h2 id="最佳实践建议"><a href="#最佳实践建议" class="headerlink" title="最佳实践建议"></a>最佳实践建议</h2><p>在实际生产或开发环境使用 <code>pre_start</code> 时，建议遵循以下原则：</p><ol><li><strong>绝对的幂等性</strong>：初始化脚本一定要做到“多次执行，结果一致”，随时准备应对重试和重建场景。</li><li><strong>严禁包含长驻进程</strong>：<code>pre_start</code> 的步骤必须是能在短时间内主动退出并返回 <code>0</code> 的任务，否则将无限期阻塞主服务的启动。</li><li><strong>区分生产与开发环境的迁移策略</strong>：虽然在 <code>pre_start</code> 中自动运行 <code>migrate</code> 很爽，但在生产环境中自动执行数据库迁移依然存在一定风险。建议重要线上项目通过独立的 CI&#x2F;CD Pipeline 触发迁移。</li><li><strong>封装复杂逻辑为脚本</strong>：如果初始化流程复杂（包含多步判断和环境准备），建议封装为独立脚本（如 <code>./scripts/init.sh</code>）放入容器，而在 <code>compose.yaml</code> 中只调用该脚本，避免配置文件过长。</li></ol><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">pre_start:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">command:</span> [<span class="string">&quot;./scripts/init.sh&quot;</span>]</span><br></pre></td></tr></table></figure><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p><strong>Docker Compose</strong> 的 <strong>Init Containers</strong> 终于解决了容器编排中长久以来的一个痛点：<strong>如何优雅地表达“启动前的必要前置步骤”</strong>。</p><p>我们可以将它的应用场景简单归纳为：</p><table><thead><tr><th align="left">适合使用 ✅</th><th align="left">不适合使用 ❌</th></tr></thead><tbody><tr><td align="left">数据库自动迁移 (<code>migrate</code>)</td><td align="left">长期运行的后台任务</td></tr><tr><td align="left">初始数据导入与种子填充</td><td align="left">定时备份&#x2F;清理等 Cron 任务</td></tr><tr><td align="left">修正宿主卷挂载（Volume）权限</td><td align="left">纯静态的配置文件挂载 (使用 <code>configs</code>)</td></tr><tr><td align="left">动态生成局部配置</td><td align="left">敏感凭证的安全管理 (使用 <code>secrets</code>)</td></tr><tr><td align="left">串联多个有顺序的前置校验步骤</td><td align="left">必须针对每个副本 (Replica) 重复执行的初始化</td></tr></tbody></table><p>最后，让我们用一张直观的对比来看看引入这一新特性后的变化：</p><div class="flatpaper-tabs"><div class="flatpaper-tabs__nav" role="tablist"><button type="button" role="tab" id="tabs-21-tab-0" aria-controls="tabs-21-panel-0" aria-selected="true" class="flatpaper-tabs__nav-item is-active" data-index="0">以前的写法 (depends_on)</button><button type="button" role="tab" id="tabs-21-tab-1" aria-controls="tabs-21-panel-1" aria-selected="false" class="flatpaper-tabs__nav-item" data-index="1">现在的写法 (pre_start)</button></div><div class="flatpaper-tabs__panels"><section role="tabpanel" id="tabs-21-panel-0" aria-labelledby="tabs-21-tab-0" class="flatpaper-tabs__panel is-active" data-index="0"><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">migrate:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">command:</span> [<span class="string">&quot;./manage.py&quot;</span>, <span class="string">&quot;migrate&quot;</span>]</span><br><span class="line">    <span class="attr">restart:</span> <span class="string">&quot;no&quot;</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="attr">migrate:</span></span><br><span class="line">        <span class="attr">condition:</span> <span class="string">service_completed_successfully</span></span><br></pre></td></tr></table></figure></section><section role="tabpanel" id="tabs-21-panel-1" aria-labelledby="tabs-21-tab-1" class="flatpaper-tabs__panel" data-index="1" hidden><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">app:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">myapp:latest</span></span><br><span class="line">    <span class="attr">pre_start:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">command:</span> [<span class="string">&quot;./manage.py&quot;</span>, <span class="string">&quot;migrate&quot;</span>]</span><br></pre></td></tr></table></figure></section></div></div><p>这就是 <strong>Docker Compose Init Containers</strong> 的终极奥义 —— <strong>让初始化步骤，优雅地回到它真正属于的地方</strong>。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;在使用 Docker Compose 部署应用时，你是否也曾为“如何在主应用启动前优雅地运行数据库迁移或修复权限”而烦恼过？&lt;/p&gt;
&lt;p&gt;过去，我们不得不编写各种一次性服务并用复杂的 &lt;code&gt;depends_on&lt;/code&gt; 串联。而现在，随着 Docker Compose 新特性的发布，我们终于迎来了官方的 &lt;strong&gt;Init Containers&lt;/strong&gt; 支持。本文将带你一探究竟，看看它如何帮我们精简 &lt;code&gt;compose.yaml&lt;/code&gt;！&lt;/p&gt;</summary>
    
    
    
    <category term="教程" scheme="https://ooo.run/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="Docker" scheme="https://ooo.run/tags/Docker/"/>
    
    <category term="Docker Compose" scheme="https://ooo.run/tags/Docker-Compose/"/>
    
    <category term="Init Containers" scheme="https://ooo.run/tags/Init-Containers/"/>
    
  </entry>
  
  <entry>
    <title>开源项目: 把酷炫的 WebGL Shader 变成前端组件 - Paper Shaders 介绍</title>
    <link href="https://ooo.run/post/paper-shaders-open-source-webgl-design-effects.html"/>
    <id>https://ooo.run/post/paper-shaders-open-source-webgl-design-effects.html</id>
    <published>2026-07-02T03:42:27.000Z</published>
    <updated>2026-07-02T04:47:36.361Z</updated>
    
    <content type="html"><![CDATA[<p>如果你做过前端视觉效果，大概率会遇到一个尴尬问题：<br>普通 CSS 很方便，但一旦想要做更复杂的动态纹理、噪声、渐变、玻璃、液态金属、粒子感背景，就很容易被迫走向 WebGL、Three.js、GLSL 和一大堆初始化样板代码。</p><p>而 <strong>Paper Shaders</strong> 想解决的正是这个问题。</p><p>它是 Paper Design 团队开源的一组 <strong>零依赖 Canvas &#x2F; WebGL Shader 组件</strong>，可以直接通过 npm 安装使用，也可以在 Paper 设计工具中可视化调整后导出代码。项目目前托管在 GitHub，采用 Apache 2.0 协议开源，官方定位是 “ultra fast zero-dependency shaders for your designs”。</p><h2 id="Paper-Shaders-是什么？"><a href="#Paper-Shaders-是什么？" class="headerlink" title="Paper Shaders 是什么？"></a>Paper Shaders 是什么？</h2><p>简单来说，Paper Shaders 是一套可以直接放进网页里的视觉特效组件库。</p><p>它把原本需要手写 GLSL、配置 WebGL 上下文、处理 Canvas 渲染循环的复杂过程，封装成了更接近普通前端组件的使用方式。对于 React 项目，你可以直接安装：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i @paper-design/shaders-react</span><br></pre></td></tr></table></figure><p>如果不使用 React，也可以安装 vanilla 版本：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i @paper-design/shaders</span><br></pre></td></tr></table></figure><p>官方 README 中也特别提醒，目前项目仍处在 <code>0.0.x</code> 版本阶段，可能会有破坏性更新，因此建议固定依赖版本。</p><h2 id="它能做哪些效果？"><a href="#它能做哪些效果？" class="headerlink" title="它能做哪些效果？"></a>它能做哪些效果？</h2><p>Paper Shaders 内置了不少适合现代网站设计的视觉效果。官方示例站把它们大致分成几类：</p><p><strong>图片滤镜类</strong>：<br>比如 paper texture、fluted glass、water、image dithering、halftone dots、halftone cmyk。</p><p><img src="https://img.nep.me/ooo/paper-shaders-1.webp" alt="paper-shaders-1.png"></p><p><strong>Logo 动画类</strong>：<br>比如 heatmap、liquid metal、gem smoke。</p><p><img src="https://img.nep.me/ooo/paper-shaders-2.webp" alt="paper-shaders-2.png"></p><p><strong>背景与动态效果类</strong>：<br>比如 mesh gradient、static mesh gradient、grain gradient、dot orbit、warp、spiral、swirl、waves、neuro noise、perlin、simplex noise、voronoi、metaballs、god rays 等。</p><p><img src="https://img.nep.me/ooo/paper-shaders-3.webp" alt="paper-shaders-3.png"></p><p>这些效果很适合用在：</p><ul><li>Landing Page 首屏背景</li><li>产品官网 Hero 区域</li><li>Logo 动效</li><li>文章封面图生成</li><li>开发者工具官网</li><li>设计感较强的 SaaS 页面</li><li>作品集网站</li><li>音乐、游戏、创意类项目页面</li></ul><p>相比直接使用静态图片，Shader 的优势是可以实时渲染、动态变化，并且通常能保持更好的响应式适配能力。</p><p>所有效果都可以在项目官网：<a href="https://shaders.paper.design/">https://shaders.paper.design/</a> 预览并进行调整。</p><h2 id="React-中如何使用？"><a href="#React-中如何使用？" class="headerlink" title="React 中如何使用？"></a>React 中如何使用？</h2><p>Paper Shaders 的 React 用法非常接近普通组件。</p><p>例如官方 README 中给出的 <code>MeshGradient</code> 示例：</p><figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">MeshGradient</span>, <span class="title class_">DotOrbit</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@paper-design/shaders-react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">MeshGradient</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">        <span class="attr">colors</span>=<span class="string">&#123;[</span>&#x27;#<span class="attr">5100ff</span>&#x27;, &#x27;#<span class="attr">00ff80</span>&#x27;, &#x27;#<span class="attr">ffcc00</span>&#x27;, &#x27;#<span class="attr">ea00ff</span>&#x27;]&#125;</span></span></span><br><span class="line"><span class="tag"><span class="language-xml">        <span class="attr">distortion</span>=<span class="string">&#123;1&#125;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">        <span class="attr">swirl</span>=<span class="string">&#123;0.8&#125;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">        <span class="attr">speed</span>=<span class="string">&#123;0.2&#125;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">        <span class="attr">style</span>=<span class="string">&#123;&#123;</span> <span class="attr">width:</span> <span class="attr">200</span>, <span class="attr">height:</span> <span class="attr">200</span> &#125;&#125;</span></span></span><br><span class="line"><span class="tag"><span class="language-xml">      /&gt;</span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">DotOrbit</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">        <span class="attr">colors</span>=<span class="string">&#123;[</span>&#x27;#<span class="attr">d2822d</span>&#x27;, &#x27;#<span class="attr">0c3b7e</span>&#x27;, &#x27;#<span class="attr">b31a57</span>&#x27;, &#x27;#<span class="attr">37a066</span>&#x27;]&#125;</span></span></span><br><span class="line"><span class="tag"><span class="language-xml">        <span class="attr">colorBack</span>=<span class="string">&quot;#000000&quot;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">        <span class="attr">scale</span>=<span class="string">&#123;0.3&#125;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">        <span class="attr">style</span>=<span class="string">&#123;&#123;</span> <span class="attr">width:</span> <span class="attr">200</span>, <span class="attr">height:</span> <span class="attr">200</span> &#125;&#125;</span></span></span><br><span class="line"><span class="tag"><span class="language-xml">      /&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/&gt;</span></span></span><br><span class="line">  );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>从这个例子可以看出，它并不要求开发者先理解完整的 WebGL 渲染流程，而是通过 <code>colors</code>、<code>distortion</code>、<code>swirl</code>、<code>speed</code>、<code>scale</code> 这类参数来调节视觉表现。对于设计师或前端开发者来说，这种抽象会更容易试错。</p><h2 id="设计师友好的-Shader-工作流"><a href="#设计师友好的-Shader-工作流" class="headerlink" title="设计师友好的 Shader 工作流"></a>设计师友好的 Shader 工作流</h2><p>Paper Shaders 最有意思的一点，不只是“提供了一堆 Shader 组件”，而是它试图打通 <strong>设计工具 → 前端代码</strong> 的流程。</p><p>项目 README 中提到，它的目标之一是让设计师可以用视觉化方式使用常见 Shader，并且最终产物可以直接导出为轻量代码，放进任意代码库中使用。</p><p>这点其实很重要。</p><p>很多网页视觉效果在设计稿里看起来很漂亮，但真正落地时会遇到几个问题：</p><p>设计师不知道如何描述 Shader 参数；<br>开发者不想从零写 WebGL；<br>设计稿里的动态效果很难准确还原；<br>最后只能用视频、GIF 或静态图片代替。</p><p>Paper Shaders 的思路是把 Shader 变成一种更“产品化”的设计资产：<br>设计阶段可以调，开发阶段可以直接用，最终上线时又不需要引入庞大的运行时依赖。</p><h2 id="零依赖的意义"><a href="#零依赖的意义" class="headerlink" title="零依赖的意义"></a>零依赖的意义</h2><p>Paper Shaders 官方强调自己是 <strong>zero-dependency HTML canvas shaders</strong>。</p><p>这对前端项目来说很有吸引力。很多视觉动效库虽然效果强大，但往往会带来明显的 bundle 体积、依赖链和运行时复杂度。对于只想在首页加一个动态背景、给 Logo 增加一点高级感、或者做一个轻量交互效果的项目来说，引入完整 3D 引擎有时候显得太重。</p><p>Paper Shaders 的定位更轻：<br>它不是要取代 Three.js、R3F 或专业图形引擎，而是提供一组可以快速嵌入网页的高质量 Shader 效果。</p><h2 id="开源协议与商业使用"><a href="#开源协议与商业使用" class="headerlink" title="开源协议与商业使用"></a>开源协议与商业使用</h2><p>Paper Shaders 使用 <strong>Apache 2.0 License</strong>。官方说明中提到，可以在商业网站、应用、游戏、视频、原型、内部工具和其他最终产品中使用，不要求可见署名。若将 Paper Shaders 代码作为另一个 Shader 库、插件或工具的一部分重新分发，则需要保留 LICENSE 和 NOTICE 文件。</p><p>这意味着它对个人项目、商业官网、SaaS 产品、内部工具都比较友好。</p><h2 id="适合哪些项目？"><a href="#适合哪些项目？" class="headerlink" title="适合哪些项目？"></a>适合哪些项目？</h2><p>我觉得 Paper Shaders 特别适合以下几类场景。</p><p>第一类是 <strong>想快速提升视觉质感的官网</strong>。<br>比如一个 AI 工具、设计工具、开发者平台或者 SaaS 产品首页，使用 Mesh Gradient、Grain Gradient、God Rays 这类效果，很容易让页面从“普通模板感”变得更有记忆点。</p><p>第二类是 <strong>需要动态 Logo 或品牌动效的项目</strong>。<br>Liquid Metal、Heatmap、Gem Smoke 这类效果非常适合做品牌展示，尤其适合科技、创意、设计类产品。</p><p>第三类是 <strong>不想写底层 WebGL 的前端项目</strong>。<br>如果你只是想要一个漂亮的 Shader 背景，而不是开发一套图形引擎，Paper Shaders 的组件化封装会比从零写 WebGL 轻松很多。</p><p>第四类是 <strong>设计师与开发者协作密集的团队</strong>。<br>如果设计师希望动态视觉效果不是“截图给开发者猜”，而是能直接变成可用代码，那么 Paper Shaders 的方向就很值得关注。</p><h2 id="需要注意的问题"><a href="#需要注意的问题" class="headerlink" title="需要注意的问题"></a>需要注意的问题</h2><p>当然，它也不是万能的。</p><p>首先，Paper Shaders 目前版本号仍然处于 <code>0.0.x</code>，官方也明确建议固定依赖版本，因为这个阶段仍可能出现破坏性更新。</p><p>其次，Shader 本质上仍然是实时渲染效果。虽然官方强调轻量和高性能，但在实际项目中，仍然建议注意移动端性能、低端设备表现、电池消耗，以及是否会影响页面可读性。</p><p>最后，视觉效果不要滥用。Shader 很适合做氛围和品牌感，但如果整页都是动态纹理、噪声和闪动渐变，反而会影响内容阅读。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>Paper Shaders 是一个很有意思的开源项目。</p><p>它把原本偏图形编程领域的 Shader，封装成了更接近现代前端组件的形态：可以 npm 安装，可以 React 使用，可以调参数，也可以与设计工具结合。对于想给网站增加动态背景、纹理、Logo 动画和高级视觉效果的开发者来说，它提供了一条比手写 WebGL 更轻量的路径。</p><p>它并不是一个庞大的 3D 框架，而更像是一盒彩色墨水：<br>你不需要重新造画布，只需要把它滴进页面里，就能让原本平面的界面多一点流动感、颗粒感和生命力。</p><h2 id="项目地址"><a href="#项目地址" class="headerlink" title="项目地址"></a>项目地址</h2><ul><li>官网：<a href="https://shaders.paper.design/">https://shaders.paper.design/</a></li><li>GitHub：<a href="https://github.com/paper-design/shaders">https://github.com/paper-design/shaders</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;如果你做过前端视觉效果，大概率会遇到一个尴尬问题：&lt;br&gt;普通 CSS 很方便，但一旦想要做更复杂的动态纹理、噪声、渐变、玻璃、液态金属、粒子感背景，就很容易被迫走向 WebGL、Three.js、GLSL 和一大堆初始化样板代码。&lt;/p&gt;
&lt;p&gt;而 &lt;strong&gt;Pap</summary>
      
    
    
    
    <category term="工具资源" scheme="https://ooo.run/categories/%E5%B7%A5%E5%85%B7%E8%B5%84%E6%BA%90/"/>
    
    
    <category term="开源" scheme="https://ooo.run/tags/%E5%BC%80%E6%BA%90/"/>
    
    <category term="前端开发" scheme="https://ooo.run/tags/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
    
    <category term="WebGL" scheme="https://ooo.run/tags/WebGL/"/>
    
    <category term="React" scheme="https://ooo.run/tags/React/"/>
    
  </entry>
  
  <entry>
    <title>Sonnet 5 已发布，值得用吗？</title>
    <link href="https://ooo.run/post/is-sonnet-5-worth-using.html"/>
    <id>https://ooo.run/post/is-sonnet-5-worth-using.html</id>
    <published>2026-07-01T09:30:48.000Z</published>
    <updated>2026-07-01T10:35:36.952Z</updated>
    
    <content type="html"><![CDATA[<p>北京时间 2026 年 7 月 1 日， Anthropic 宣布 <strong>Fable 5</strong> 解除封禁，并发布了新模型 <strong>Sonnet 5</strong>， Anthopic 宣称该版本显著提升了自主执行任务和调用工具的智能体 (Agent) 能力，性能逼近旗舰级 Opus 4.8，采用了全新的分词器。其定价为：</p><table><thead><tr><th>模型</th><th>输入（每百万 Token）</th><th>输出（每百万 Token）</th><th>备注</th></tr></thead><tbody><tr><td>Sonnet 5</td><td>3 美元</td><td>15 美元</td><td>8 月 31 日前优惠价 2 美元 &#x2F; 10 美元</td></tr><tr><td>Opus 4.8</td><td>5 美元</td><td>25 美元</td><td>无限时优惠</td></tr><tr><td>Fable 5</td><td>10 美元</td><td>50 美元</td><td>7 月 7 日后订阅额度不再包含，需按 API 付费</td></tr></tbody></table><p>无论输入还是输出，Sonnet 5 的单价都只有 Opus 的六成。但单价更低不代表实际更省——后面会提到，按实际任务成本衡量，Sonnet 5 完成同一任务反而可能花更多钱，这也是后面争议的根源。</p><p>Sonnet 5 相比 Opus 单价全面更低，又完成了一次大版本号的跃迁，你可能会有疑问，Sonnet 5 到底值得使用吗？</p><h2 id="结论"><a href="#结论" class="headerlink" title="结论"></a>结论</h2><p>这里直接上结论：</p><p><strong>Sonnet 5 不适合直接作为默认模型使用，其性能不如 Opus 4.8，但是在写作方面获得了表现出色的评价。</strong></p><p>因此对于大型、大规模代码编辑，直接使用 Opus 4.8 系列即可，如果预算充足则使用 Fable 5（7 月 7 日后 Claude Code Pro 订阅中将无法直接使用 Fable，需要按照 API 定价收费）。</p><p>当需要考虑费用成本、需要较新的知识库（已更新至 2026 年 1 月）时，以及在小型任务、写作任务中，可以切换为 Sonnet 5。</p><p>对于更简单的任务，使用其他更经济的模型即可覆盖。</p><h2 id="Sonnet-5-是什么？"><a href="#Sonnet-5-是什么？" class="headerlink" title="Sonnet 5 是什么？"></a>Sonnet 5 是什么？</h2><p>按照 Anthropic 官方新闻页的说法，Claude Sonnet 5 是 Sonnet 系列的新一代模型，定位是「面向编码、Agent 和专业工作的前沿性能模型」。Anthropic 将其放在 Sonnet 产品线上，而不是 Opus 或 Fable 这种更高阶、更昂贵的旗舰线，这本身就是一个信号：Sonnet 5 不是用来刷榜的模型，而是用来「天天用」的模型。</p><p>外媒报道也提到，Sonnet 5 被设计为一个更适合日常高频使用的模型，重点加强了浏览、编码、规划、知识工作和自主任务执行能力，并已同步面向 Claude Free、Pro、Max、Team、Enterprise 等所有订阅层级开放。这种「首发即全量」的铺开方式，也印证了它的定位：主力机型，不是尝鲜彩蛋。</p><p>简单说，Sonnet 5 不是「最高规格炫技模型」，而是 Anthropic 想推给大多数 Claude 用户的主力工作模型。</p><p>这和过去 Anthropic 对 Sonnet 系列的定位一致：  <strong>比 Haiku 强，比 Opus 便宜，适合作为日常主力。</strong></p><h2 id="社交媒体评价：完全不值"><a href="#社交媒体评价：完全不值" class="headerlink" title="社交媒体评价：完全不值"></a>社交媒体评价：完全不值</h2><p>一张来自 Artificial Analysis 的「Cost per Intelligence Index Task」图表显示，Claude Sonnet 5 在 <strong>Max 思考等级</strong> 下的单任务成本明显高于 GPT-5.5、GLM-5.2、Kimi-K2.6、DeepSeek-V4-Pro 等模型，甚至高于 Opus 系列。于是有人直接总结：</p><blockquote><p>Sonnet 5 直接扔进垃圾桶<br>比 Opus 4.8 Max 贵 1.2 倍<br>比 GPT-5.5-xhigh 贵 2 倍<br>比 GLM-5.2 贵 5 倍<br>比 Kimi-K2.6 贵 7 倍<br>比 DeepSeek-V4-Pro 贵 57 倍</p></blockquote><p><img src="https://img.nep.me/ooo/sonnet5-per-task-cost.webp" alt="sonnet5-per-task-cost"></p><p>对此 OpenClaw 的作者 Peter Steinberger 直接 <a href="https://x.com/steipete/status/2072144627474579925">评价</a>： <strong>每 Token 价格 !&#x3D; 实际任务成本 !&#x3D; 最终生产力成本</strong>。</p><p>由于 Sonnet 5 的智能没有实现很大进步，需要消耗更多的 Token 来完成任务，导致总消耗反而比 Opus 系列更多。 </p><p>因此对于大型、大规模的代码编辑项目直接使用更高智能的 Opus 系列即可。</p><h2 id="争议点：Sonnet-5-贵不贵？"><a href="#争议点：Sonnet-5-贵不贵？" class="headerlink" title="争议点：Sonnet 5 贵不贵？"></a>争议点：Sonnet 5 贵不贵？</h2><p>贵。</p><p>尤其是放在 2026 年这个时间点看，Sonnet 5 的成本压力会比过去更明显。</p><p>Artificial Analysis 的成本图并不是单纯比较输入 &#x2F; 输出 Token 单价，而是按 Intelligence Index 任务加权计算，包括 Input、Answer、Reasoning、Cache Write、Cache Hit 等不同 Token 类型。它试图回答的是：完成一个标准化智能任务，平均要花多少钱。</p><p>这就解释了为什么「看起来 API 单价差不多」的模型，实际任务成本可能完全不同。举个例子：如果一个模型平均需要 3 轮工具调用、每轮都要重新读一遍上下文才能完成任务，而另一个模型 1 轮就能给出可用结果，那么即使两者单价一致，前者的实际账单也会是后者的数倍——差距不是来自定价表，而是来自「模型解决问题需要绕多少路」。</p><p>一个模型如果：</p><ul><li>输出更长</li><li>推理 Token 更多</li><li>工具调用链路更重</li><li>不擅长一次完成，需要反复修正</li><li>Cache 利用率不高</li></ul><p>那么它的实际成本就会被拉高。</p><p>这也是很多人吐槽 Sonnet 5 的原因：<br><strong>Anthropic 的模型越来越像豪华燃油车，性能强，但开起来不便宜。</strong></p><h2 id="但只看单任务成本，也容易误判"><a href="#但只看单任务成本，也容易误判" class="headerlink" title="但只看单任务成本，也容易误判"></a>但只看单任务成本，也容易误判</h2><p>问题在于，开发者真正关心的往往不是「跑一次 Benchmark 花多少钱」，而是：</p><p><strong>它能不能少折腾我？</strong></p><p>对写代码、重构项目、分析仓库、修 Bug、跑 Agent 来说，模型成本只是总成本的一部分。更重要的是：</p><ul><li>第一次方案是否靠谱</li><li>是否理解大型项目上下文</li><li>是否会乱改无关文件</li><li>是否能保持长期任务稳定</li><li>是否能自己发现问题并修正</li><li>是否减少人工 review 和返工</li></ul><p>如果 Sonnet 5 在这些方面明显强于便宜模型，那么它即使「每次任务更贵」，最终仍然可能更划算。</p><p>打个比方：假设一个中型重构任务，便宜模型单价是 Sonnet 5 的五分之一，但因为理解不了项目边界，需要反复试错 6 轮才能勉强跑通，且中途还改坏了两个无关文件，需要你手动回滚；而 Sonnet 5 单价更高，但 2 轮就能给出可用方案，且不会牵连其他文件。算上你自己排查、回滚、二次确认的时间成本，便宜模型的「总成本」未必比 Sonnet 5 低——只是这部分成本没有出现在账单上，而是变成了你的时间。</p><p>这就像云服务器：</p><p>便宜的很便宜，但如果一天炸三次、IO 抽风、网络绕路，最后浪费的是人的时间。</p><p>AI 模型也是一样。</p><h2 id="Sonnet-5-真正的价值：Agent-和代码工作流"><a href="#Sonnet-5-真正的价值：Agent-和代码工作流" class="headerlink" title="Sonnet 5 真正的价值：Agent 和代码工作流"></a>Sonnet 5 真正的价值：Agent 和代码工作流</h2><p>从 Anthropic 的宣传重点看，Sonnet 5 最核心的卖点不是普通聊天，而是 <strong>Agentic Workflows</strong>。</p><p>也就是让模型不只是回答问题，而是能连续执行任务：</p><ul><li>阅读项目文件</li><li>理解现有架构</li><li>制定修改计划</li><li>调用终端</li><li>修改代码</li><li>跑测试</li><li>根据报错继续修</li><li>最后总结变更</li></ul><p>这正是 Claude Code、Cursor、Windsurf、OpenClaw 这类工具最依赖的能力。</p><p>对这类场景来说，模型的「听话程度」「上下文稳定性」「工具调用判断」往往比单纯的知识问答更重要。Anthropic 过去几代 Sonnet 在代码 Agent 场景中口碑一直不错，Sonnet 5 如果继续强化这条路线，那它仍然会是开发者绕不开的模型。</p><p>尤其是复杂项目里，很多模型不是不会写代码，而是：</p><ul><li>看不懂项目边界</li><li>喜欢重写整个文件</li><li>改 A 坏 B</li><li>测试失败后开始胡猜</li><li>上下文一长就开始失忆</li><li>看到报错只会重复同一个错误修法</li></ul><p>如果 Sonnet 5 能减少这些问题，那么它就不是单纯的「贵」，而是「贵但省心」。</p><h2 id="那它适合所有人吗？"><a href="#那它适合所有人吗？" class="headerlink" title="那它适合所有人吗？"></a>那它适合所有人吗？</h2><p><strong>不适合。</strong></p><p>如果你的需求只是：</p><ul><li>翻译</li><li>摘要</li><li>写普通文章</li><li>生成短代码片段</li><li>问一些常识问题</li><li>做轻量客服 QA</li><li>批量处理低价值文本</li></ul><p>那 Sonnet 5 很可能不是性价比最高的选择。</p><p>这类任务已经进入「模型过剩」阶段。GLM、Kimi、DeepSeek、GPT 的中低价模型都能做得不错。尤其是批量任务，成本差距会被无限放大。</p><p>比如一篇博客摘要、一个 JSON 转换、一个普通 SQL 生成任务，Sonnet 5 的优势可能并不能抵消它的成本。</p><p>这时候更合理的策略是：</p><p><strong>便宜模型跑基础任务，Opus &#x2F; Fable 系列处理大型复杂的任务，当有成本考虑是，将一些中阶的小规模任务交给 Sonnet 5 处理。</strong></p><h2 id="我的建议：不要把-Sonnet-5-当默认模型无脑用"><a href="#我的建议：不要把-Sonnet-5-当默认模型无脑用" class="headerlink" title="我的建议：不要把 Sonnet 5 当默认模型无脑用"></a>我的建议：不要把 Sonnet 5 当默认模型无脑用</h2><p>Sonnet 5 最适合的使用方式，不是「所有请求都丢给它」，而是把它当成一个经济型的工作模型。</p><p>可以这样分层：</p><h3 id="1-普通文本任务：不用-Sonnet-5"><a href="#1-普通文本任务：不用-Sonnet-5" class="headerlink" title="1. 普通文本任务：不用 Sonnet 5"></a>1. 普通文本任务：不用 Sonnet 5</h3><p>翻译、润色、改标题、写摘要、生成普通 Markdown，用便宜模型就够了。</p><p>这些任务对推理深度、工具调用、项目理解要求不高，用 Sonnet 5 属于杀鸡用牛刀。</p><h3 id="2-一般代码片段：看情况"><a href="#2-一般代码片段：看情况" class="headerlink" title="2. 一般代码片段：看情况"></a>2. 一般代码片段：看情况</h3><p>写一个简单函数、改一个 CSS、生成一个 Docker Compose，便宜模型也能胜任。</p><p>但如果它开始反复出错，或者你已经花了 10 分钟纠错，那就应该可以尝试切换 Sonnet 5。</p><p><strong>便宜模型最贵的地方，是让你以为它快好了。</strong></p><h3 id="3-中小型代码任务：可以用-Sonnet-5"><a href="#3-中小型代码任务：可以用-Sonnet-5" class="headerlink" title="3. 中小型代码任务：可以用 Sonnet 5"></a>3. 中小型代码任务：可以用 Sonnet 5</h3><p>例如：</p><ul><li>修改单个页面</li><li>补一个组件</li><li>写一个脚本</li><li>修一个明确报错</li><li>添加一个简单 API</li><li>生成测试用例</li><li>对已有代码做小范围重构</li></ul><p>这类任务的特点是边界清晰、上下文较短、失败成本较低。Sonnet 5 在这里可以发挥 Claude 系列一贯的代码理解和指令遵循能力，同时比 Opus 4.8 单价更低。</p><p>如果任务本身不复杂，用 Opus 4.8 反而有些浪费；但如果用更便宜的模型反复出错，Sonnet 5 就是一个不错的折中选择。</p><p>它适合处理「需要一点智能，但还不值得动用最高智能模型」的代码任务。</p><h3 id="4-大型项目的开发与重构：直接使用更高智能的模型"><a href="#4-大型项目的开发与重构：直接使用更高智能的模型" class="headerlink" title="4. 大型项目的开发与重构：直接使用更高智能的模型"></a>4. 大型项目的开发与重构：直接使用更高智能的模型</h3><p>如果你的目标不是修一个小 Bug、改一个组件、写一段脚本，而是让 AI 参与实现一个完整项目，那么 Sonnet 5 反而不一定是最优选择。</p><p>这类任务通常包括：</p><ul><li>从零搭建一个完整应用</li><li>设计项目架构</li><li>实现多模块功能</li><li>连续修改几十个文件</li><li>处理数据库、鉴权、状态管理、路由、部署配置</li><li>长时间运行 Claude Code &#x2F; Codex &#x2F; OpenClaw 这类 Agent 工具</li></ul><p>在这种场景里，模型最重要的不是「单价低」，而是「一次做对的概率高」。</p><p>大型项目的成本并不只是 Token 成本，而是由多部分组成：</p><ul><li>模型理解需求的成本</li><li>模型维护上下文的成本</li><li>多轮修改产生的返工成本</li><li>改错文件带来的回滚成本</li><li>测试失败后的排查成本</li><li>人工 review 和补救的时间成本</li></ul><p>如果一个模型智能略低，它可能每一步看起来都能做，但组合起来就会出现问题：前面设计的架构后面忘了，刚写好的接口下一轮又被改坏，A 页面修好了 B 页面挂了，最后整个项目进入「能跑但不敢碰」的状态。</p><p>这也是为什么在大型项目里，应该优先使用 Opus 4.8、Fable 5 这类更高智能模型。</p><p>它们的单价更高，但在复杂任务中更容易保持全局一致性，能减少无效尝试和重复修复。尤其是当任务涉及架构设计、跨文件重构、测试修复和长期上下文时，更高智能模型带来的稳定性往往比价格差异更重要。</p><p>Sonnet 5 更适合做局部任务：<br>比如写一个页面、改一个模块、生成一段文案、补一个测试、修一个明确的报错。</p><p>但如果你要让 AI 从头到尾实现一个大型项目，尤其是需要连续运行 Agent 多小时，那么更合理的策略是：</p><p><strong>直接使用 Opus 4.8 或 Fable 5，不要为了省一点单价把项目交给 Sonnet 5 硬跑。</strong></p><p>因为大型项目里最贵的不是模型，而是模型犯错之后你还要继续相信它。</p><h2 id="Sonnet-5-的问题：Anthropic-还是那个-Anthropic"><a href="#Sonnet-5-的问题：Anthropic-还是那个-Anthropic" class="headerlink" title="Sonnet 5 的问题：Anthropic 还是那个 Anthropic"></a>Sonnet 5 的问题：Anthropic 还是那个 Anthropic</h2><p>Sonnet 5 的发布，也再次暴露了 Anthropic 的老问题：</p><p><strong>模型很好，但生态和价格让人焦虑。</strong></p><p>Claude 的体验一直很强，尤其是代码和长上下文任务。但 Anthropic 在可用性、额度、区域、订阅限制、API 成本和第三方工具支持上，始终不像 OpenAI 那样稳定。</p><p>更重要的是，随着 AI Agent 消耗越来越大，「订阅制无限用」这件事本身就越来越难持续。此前已有分析指出，重度 AI 用户实际消耗的 API 等价成本可能远超订阅价格——一个长期跑 Agent 任务的开发者，一天消耗的 Token 换算成 API 价格可能就超过月费本身。这意味着 AI 公司未来很可能继续向更细粒度、更接近成本的计费方式调整，比如更严格的用量上限、分层限速，或者像 Sonnet 5 这样在输出端悄悄提价。</p><p>所以 Sonnet 5 的问题不是单个模型贵，而是代表了一种趋势：</p><p><strong>好模型会越来越强，但真正便宜随便用的时代正在结束。</strong></p><h2 id="一句话总结"><a href="#一句话总结" class="headerlink" title="一句话总结"></a>一句话总结</h2><p><strong>Sonnet 5 不是便宜模型，也不是最强模型，而是一个适合写作和中小型任务的 Claude 日常模型。</strong> 它在代码编辑领域没有找到一个足够舒服的位置：便宜任务轮不到它，复杂任务又不如直接上 Opus &#x2F; Fable。</p><p>如果你把它当成 Opus 的廉价替代品，可能会失望；<br>如果你把它当成一个更适合日常文本和轻量工作的 Sonnet，它依然值得放进工具箱。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;北京时间 2026 年 7 月 1 日， Anthropic 宣布 &lt;strong&gt;Fable 5&lt;/strong&gt; 解除封禁，并发布了新模型 &lt;strong&gt;Sonnet 5&lt;/strong&gt;， Anthopic 宣称该版本显著提升了自主执行任务和调用工具的智能体 (Ag</summary>
      
    
    
    
    <category term="资讯" scheme="https://ooo.run/categories/%E8%B5%84%E8%AE%AF/"/>
    
    
    <category term="AI" scheme="https://ooo.run/tags/AI/"/>
    
    <category term="Claude" scheme="https://ooo.run/tags/Claude/"/>
    
    <category term="Sonnet 5" scheme="https://ooo.run/tags/Sonnet-5/"/>
    
  </entry>
  
  <entry>
    <title>Vercel Services 发布：一个项目部署 Next.js、FastAPI、Go 和 Astro</title>
    <link href="https://ooo.run/post/vercel-services-multiple-frameworks-one-project.html"/>
    <id>https://ooo.run/post/vercel-services-multiple-frameworks-one-project.html</id>
    <published>2026-06-30T16:09:42.000Z</published>
    <updated>2026-06-30T16:47:09.870Z</updated>
    
    <content type="html"><![CDATA[<p>当你手头有一个包含 Next.js 前端、FastAPI 后端、Go 服务和 Astro 文档站的复杂项目时，是否也曾为如何在 Vercel 上部署和管理而感到头疼？</p><p>过去，这类项目往往需要拆成多个 Vercel Project，或者把部分服务放到其他平台上运行。项目一多，域名、环境变量、Preview URL、跨服务调用、CORS、路由转发都会变复杂。</p><p>Vercel 最近推出的 <a href="https://vercel.com/changelog/run-multiple-frameworks-in-one-project-with-vercel-services">Vercel Services</a>，就是为了解决这个问题：它允许开发者在一个 Vercel Project 中部署多个独立构建的服务，并通过统一的路由规则把请求分发到不同服务中。</p><p>换句话说，一个项目里可以同时放：</p><ul><li>Next.js 前端</li><li>FastAPI 后端</li><li>Go API 服务</li><li>Astro 文档站</li><li>Vite &#x2F; React 管理后台</li><li>其他独立构建单元</li></ul><p>这些服务可以共享同一个部署、同一个域名、同一套 Preview Deployment，并且可以通过 Vercel 的服务路由和内部绑定进行通信。</p><h2 id="Vercel-Services-是什么？"><a href="#Vercel-Services-是什么？" class="headerlink" title="Vercel Services 是什么？"></a>Vercel Services 是什么？</h2><p>简单来说，Vercel Services 可以把一个项目拆成多个独立的 <strong>Service</strong>。</p><p>每个 Service 都是一个独立构建单元，可以有自己的根目录、框架、运行时、启动入口和依赖文件。但它们最终仍然属于同一个 Vercel Project，并共享同一个部署。</p><p>例如，一个项目可以设计成这样：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">my-project/</span><br><span class="line">├── apps/</span><br><span class="line">│   ├── web/        # Next.js 前端</span><br><span class="line">│   ├── docs/       # Astro 文档站</span><br><span class="line">│   └── admin/      # Vite 管理后台</span><br><span class="line">├── backend/</span><br><span class="line">│   └── fastapi/    # FastAPI 后端</span><br><span class="line">├── services/</span><br><span class="line">│   └── go/         # Go 服务</span><br><span class="line">└── vercel.json</span><br></pre></td></tr></table></figure><p>部署后，可以通过同一个域名访问不同服务：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">https://example.vercel.app/          -&gt; Next.js 前端</span><br><span class="line">https://example.vercel.app/api       -&gt; FastAPI 后端</span><br><span class="line">https://example.vercel.app/go        -&gt; Go 服务</span><br><span class="line">https://example.vercel.app/docs      -&gt; Astro 文档站</span><br></pre></td></tr></table></figure><p>这就是 Vercel Services 最核心的价值：<strong>一个项目，多个服务，统一部署。</strong></p><p><img src="https://img.nep.me/ooo/cover-vercel-services.webp" alt="Vercek Services"></p><h2 id="它解决了什么问题？"><a href="#它解决了什么问题？" class="headerlink" title="它解决了什么问题？"></a>它解决了什么问题？</h2><h3 id="1-前端和后端不用拆成多个-Vercel-Project"><a href="#1-前端和后端不用拆成多个-Vercel-Project" class="headerlink" title="1. 前端和后端不用拆成多个 Vercel Project"></a>1. 前端和后端不用拆成多个 Vercel Project</h3><p>很多项目一开始只是一个前端站点，后来逐渐加上 API、后台、Webhook、文档站、小工具页面，最后目录可能变成这样：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">my-project/</span><br><span class="line">├── apps/</span><br><span class="line">│   ├── web/</span><br><span class="line">│   ├── admin/</span><br><span class="line">│   └── docs/</span><br><span class="line">├── backend/</span><br><span class="line">│   ├── main.py</span><br><span class="line">│   └── requirements.txt</span><br><span class="line">├── packages/</span><br><span class="line">│   └── shared/</span><br><span class="line">└── vercel.json</span><br></pre></td></tr></table></figure><p>如果没有 Services，你可能需要这样拆：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">apps/web     -&gt; 一个 Vercel Project</span><br><span class="line">apps/admin   -&gt; 另一个 Vercel Project</span><br><span class="line">apps/docs    -&gt; 再一个 Vercel Project</span><br><span class="line">backend      -&gt; 部署到 VPS、Render、Fly.io 或其他平台</span><br></pre></td></tr></table></figure><p>这样做当然可以，但维护成本会变高：</p><ul><li>每个项目都有单独的域名和 Preview URL</li><li>环境变量需要重复配置</li><li>前端调用后端要处理 CORS</li><li>PR 预览时前后端地址可能对不上</li><li>多个服务之间的版本同步更麻烦</li></ul><p>Vercel Services 的思路是：这些东西本来就属于同一个产品，那就让它们作为一个项目中的多个服务一起部署。</p><h3 id="2-更适合多语言项目"><a href="#2-更适合多语言项目" class="headerlink" title="2. 更适合多语言项目"></a>2. 更适合多语言项目</h3><p>Vercel 过去最强的体验主要集中在前端和 Node.js 生态，尤其是 Next.js。</p><p>但现实项目中，后端不一定都是 JavaScript。很多项目会同时使用：</p><ul><li>Next.js</li><li>Astro</li><li>Vite</li><li>FastAPI</li><li>Go</li><li>Express</li><li>Hono</li><li>其他后端框架</li></ul><p>Vercel Services 让这些服务可以在一个项目中组合起来。</p><p>例如：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">apps/web         -&gt; Next.js 前端</span><br><span class="line">apps/docs        -&gt; Astro 文档站</span><br><span class="line">backend/fastapi  -&gt; FastAPI 后端</span><br><span class="line">services/go      -&gt; Go 服务</span><br></pre></td></tr></table></figure><p>这类项目过去更像是“多个部署拼起来”，现在则更接近“一个产品的多个组成部分”。</p><h3 id="3-Preview-Deployment-更统一"><a href="#3-Preview-Deployment-更统一" class="headerlink" title="3. Preview Deployment 更统一"></a>3. Preview Deployment 更统一</h3><p>Vercel 最好用的能力之一是 Preview Deployment。</p><p>每次提交 PR，都可以自动生成一个预览地址。如果前端、后端、文档站都拆成多个 Project，那么你可能需要同时管理多个预览地址。</p><p>使用 Services 后，多个服务可以共享同一个部署 URL，通过不同路径区分：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">https://my-project-git-feature.vercel.app/</span><br><span class="line">https://my-project-git-feature.vercel.app/api</span><br><span class="line">https://my-project-git-feature.vercel.app/go</span><br><span class="line">https://my-project-git-feature.vercel.app/docs</span><br></pre></td></tr></table></figure><p>对于团队协作、产品验收、临时测试来说，这会简单很多。</p><h2 id="基础配置示例"><a href="#基础配置示例" class="headerlink" title="基础配置示例"></a>基础配置示例</h2><p>Vercel Services 使用 <code>vercel.json</code> 中的 <code>services</code> 字段声明多个服务。</p><p>一个最简单的前后端项目可以这样写：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;services&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;my_frontend&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;frontend/&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;framework&quot;</span><span class="punctuation">:</span> <span class="string">&quot;nextjs&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;my_backend&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;backend/&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;entrypoint&quot;</span><span class="punctuation">:</span> <span class="string">&quot;main:app&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;rewrites&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;source&quot;</span><span class="punctuation">:</span> <span class="string">&quot;/api/(.*)&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;destination&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;service&quot;</span><span class="punctuation">:</span> <span class="string">&quot;my_backend&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;source&quot;</span><span class="punctuation">:</span> <span class="string">&quot;/(.*)&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;destination&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;service&quot;</span><span class="punctuation">:</span> <span class="string">&quot;my_frontend&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>这里定义了两个服务：</p><ul><li><code>my_frontend</code>：前端服务，根目录是 <code>frontend/</code>，使用 Next.js。</li><li><code>my_backend</code>：后端服务，根目录是 <code>backend/</code>，启动入口是 <code>main:app</code>。</li></ul><p>下面的 <code>rewrites</code> 决定公网请求如何进入不同服务：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/api/*  -&gt; my_backend</span><br><span class="line">/*      -&gt; my_frontend</span><br></pre></td></tr></table></figure><p>也就是说：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">https://example.vercel.app/api/users  -&gt; FastAPI 后端</span><br><span class="line">https://example.vercel.app/about      -&gt; Next.js 前端</span><br></pre></td></tr></table></figure><p>需要注意的是，Service 默认不会自动暴露到公网。只有被顶层 <code>rewrites</code> 指向的服务，才会接收公网请求。</p><p>这点非常重要。</p><p>如果你声明了一个 <code>my_backend</code> 服务，但没有在 <code>rewrites</code> 中把路径指向它，那么它不会直接对公网开放。这种设计适合处理一些只给内部调用的后端服务。</p><img src="https://img.nep.me/ooo/vercel-services-deployment-ui.webp" alt="vercel-services-deployment-ui" style="width:75%;max-width:100%;height:auto" /><h2 id="更完整的示例：Next-js-FastAPI-Go-Astro"><a href="#更完整的示例：Next-js-FastAPI-Go-Astro" class="headerlink" title="更完整的示例：Next.js + FastAPI + Go + Astro"></a>更完整的示例：Next.js + FastAPI + Go + Astro</h2><p>假设我们有一个 Monorepo：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">my-app/</span><br><span class="line">├── apps/</span><br><span class="line">│   ├── web/</span><br><span class="line">│   │   ├── package.json</span><br><span class="line">│   │   └── app/</span><br><span class="line">│   └── docs/</span><br><span class="line">│       ├── package.json</span><br><span class="line">│       └── src/</span><br><span class="line">├── backend/</span><br><span class="line">│   └── fastapi/</span><br><span class="line">│       ├── main.py</span><br><span class="line">│       └── requirements.txt</span><br><span class="line">├── services/</span><br><span class="line">│   └── go/</span><br><span class="line">│       ├── main.go</span><br><span class="line">│       └── go.mod</span><br><span class="line">└── vercel.json</span><br></pre></td></tr></table></figure><p>我们希望：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">/        -&gt; Next.js 前端</span><br><span class="line">/api/*   -&gt; FastAPI 后端</span><br><span class="line">/go/*    -&gt; Go 服务</span><br><span class="line">/docs/*  -&gt; Astro 文档站</span><br></pre></td></tr></table></figure><p>那么 <code>vercel.json</code> 可以这样写：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;services&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;web&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;apps/web&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;framework&quot;</span><span class="punctuation">:</span> <span class="string">&quot;nextjs&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;api&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;backend/fastapi&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;entrypoint&quot;</span><span class="punctuation">:</span> <span class="string">&quot;main:app&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;go_service&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;services/go&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;entrypoint&quot;</span><span class="punctuation">:</span> <span class="string">&quot;main.go&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;docs&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;apps/docs&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;framework&quot;</span><span class="punctuation">:</span> <span class="string">&quot;astro&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;rewrites&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;source&quot;</span><span class="punctuation">:</span> <span class="string">&quot;/api/(.*)&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;destination&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;service&quot;</span><span class="punctuation">:</span> <span class="string">&quot;api&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;source&quot;</span><span class="punctuation">:</span> <span class="string">&quot;/go/(.*)&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;destination&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;service&quot;</span><span class="punctuation">:</span> <span class="string">&quot;go_service&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;source&quot;</span><span class="punctuation">:</span> <span class="string">&quot;/docs/(.*)&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;destination&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;service&quot;</span><span class="punctuation">:</span> <span class="string">&quot;docs&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;source&quot;</span><span class="punctuation">:</span> <span class="string">&quot;/(.*)&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;destination&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;service&quot;</span><span class="punctuation">:</span> <span class="string">&quot;web&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>这段配置的核心逻辑很清晰：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">/api/*   交给 FastAPI</span><br><span class="line">/go/*    交给 Go 服务</span><br><span class="line">/docs/*  交给 Astro 文档站</span><br><span class="line">其他路径 交给 Next.js 前端</span><br></pre></td></tr></table></figure><p>注意，<code>rewrites</code> 的顺序很重要。更具体的路径应该放在前面，例如 <code>/api/(.*)</code>、<code>/go/(.*)</code>、<code>/docs/(.*)</code>；兜底的 <code>/(.*)</code> 应该放在最后。</p><p>否则所有请求都可能先被前端服务接走。</p><h2 id="配置字段说明"><a href="#配置字段说明" class="headerlink" title="配置字段说明"></a>配置字段说明</h2><h3 id="services"><a href="#services" class="headerlink" title="services"></a>services</h3><p><code>services</code> 用于声明当前项目中的多个服务。</p><p>每个 key 都是一个服务名，例如：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;services&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;web&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;api&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;docs&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>这些服务名之后可以在 <code>rewrites</code> 或服务间调用配置中使用。</p><h3 id="root"><a href="#root" class="headerlink" title="root"></a>root</h3><p><code>root</code> 指定该服务所在的目录。</p><p>例如：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;services&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;web&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;apps/web&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>这表示 <code>web</code> 服务的代码位于 <code>apps/web</code> 目录下。</p><h3 id="framework"><a href="#framework" class="headerlink" title="framework"></a>framework</h3><p><code>framework</code> 用于指定服务使用的框架。</p><p>例如：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;services&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;web&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;apps/web&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;framework&quot;</span><span class="punctuation">:</span> <span class="string">&quot;nextjs&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;docs&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;apps/docs&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;framework&quot;</span><span class="punctuation">:</span> <span class="string">&quot;astro&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>如果不写，Vercel 会尝试自动识别框架。但对于复杂 Monorepo 项目，显式指定通常更稳定。</p><h3 id="entrypoint"><a href="#entrypoint" class="headerlink" title="entrypoint"></a>entrypoint</h3><p><code>entrypoint</code> 通常用于后端服务，指定应用启动入口。</p><p>FastAPI 常见写法类似：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;services&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;api&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;backend/fastapi&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;entrypoint&quot;</span><span class="punctuation">:</span> <span class="string">&quot;main:app&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>其中 <code>main:app</code> 通常表示：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">main.py 文件中的 app 对象</span><br></pre></td></tr></table></figure><p>Go 服务可以根据项目结构指定入口，例如：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;services&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;go_service&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;root&quot;</span><span class="punctuation">:</span> <span class="string">&quot;services/go&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;entrypoint&quot;</span><span class="punctuation">:</span> <span class="string">&quot;main.go&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>实际写法需要根据项目结构和 Vercel 支持的运行方式调整。</p><h3 id="rewrites"><a href="#rewrites" class="headerlink" title="rewrites"></a>rewrites</h3><p><code>rewrites</code> 是 Services 模式里非常重要的一部分。</p><p>它决定公网请求会被路由到哪个 Service。</p><p>例如：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;rewrites&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;source&quot;</span><span class="punctuation">:</span> <span class="string">&quot;/api/(.*)&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;destination&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;service&quot;</span><span class="punctuation">:</span> <span class="string">&quot;api&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;source&quot;</span><span class="punctuation">:</span> <span class="string">&quot;/(.*)&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;destination&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;service&quot;</span><span class="punctuation">:</span> <span class="string">&quot;web&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>这表示：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/api/*  -&gt; api 服务</span><br><span class="line">其他路径 -&gt; web 服务</span><br></pre></td></tr></table></figure><p>没有被 <code>rewrites</code> 暴露的服务，默认不会接收公网请求。</p><p>这和传统的“每个服务自动挂一个公开路径”不太一样。Vercel Services 更像是先声明服务，再通过统一的顶层路由表决定哪些服务对外开放。</p><h2 id="服务之间如何通信？"><a href="#服务之间如何通信？" class="headerlink" title="服务之间如何通信？"></a>服务之间如何通信？</h2><p>除了通过公网路径访问，Services 之间也可以通过内部方式通信。</p><p>这适合一些不希望直接暴露给公网的服务。</p><p>例如，你可能有：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">web       -&gt; Next.js 前端</span><br><span class="line">api       -&gt; 对外 API</span><br><span class="line">worker    -&gt; 内部任务服务</span><br></pre></td></tr></table></figure><p><code>worker</code> 不需要公开 URL，只需要被 <code>api</code> 调用。这种情况下，就可以让它作为内部服务存在，而不是给它配置公网 rewrite。</p><p>这种设计的好处是：</p><ul><li>减少公网暴露面</li><li>避免无意义的外部路由</li><li>更适合拆分后台能力</li><li>让项目结构更接近真实的微服务或模块化后端</li></ul><p>当然，对于个人项目来说，不一定需要一开始就拆这么细。普通项目可以先从 <code>web + api</code> 两个服务开始。</p><h2 id="它不是-Docker-Compose"><a href="#它不是-Docker-Compose" class="headerlink" title="它不是 Docker Compose"></a>它不是 Docker Compose</h2><p>需要注意的是，Vercel Services 并不等于 Docker Compose。</p><p>Docker Compose 更像是在一台服务器或容器环境中编排多个长期运行的服务，例如：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">web</span><br><span class="line">api</span><br><span class="line">postgres</span><br><span class="line">redis</span><br><span class="line">worker</span><br></pre></td></tr></table></figure><p>它通常负责启动多个容器，并让这些容器在同一个网络环境中长期运行。</p><p>而 Vercel Services 更偏向于 Vercel 平台上的多服务构建与路由组织。它适合部署 Web 应用、API 服务、前端项目和轻量后端，但并不是让你在 Vercel 上直接运行一整套传统服务器环境。</p><p>如果你的项目依赖：</p><ul><li>长期运行的数据库</li><li>Redis</li><li>队列</li><li>后台常驻进程</li><li>自定义守护进程</li><li>复杂内网服务发现</li><li>完整 Docker Compose 生态</li></ul><p>那仍然需要使用外部托管服务，或者选择 VPS &#x2F; Docker &#x2F; Kubernetes 等更传统的部署方式。</p><p>不过，Vercel Services 确实让 Vercel 更接近“一个产品部署多个组成部分”的形态。对于不想自己维护服务器的人来说，这已经覆盖了很多常见场景。</p><h2 id="适合哪些项目？"><a href="#适合哪些项目？" class="headerlink" title="适合哪些项目？"></a>适合哪些项目？</h2><p>Vercel Services 很适合这些场景。</p><h3 id="Monorepo-项目"><a href="#Monorepo-项目" class="headerlink" title="Monorepo 项目"></a>Monorepo 项目</h3><p>例如：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">apps/web</span><br><span class="line">apps/admin</span><br><span class="line">apps/docs</span><br><span class="line">packages/ui</span><br><span class="line">packages/db</span><br><span class="line">backend/api</span><br></pre></td></tr></table></figure><p>如果你已经在使用 pnpm workspace、Turborepo、Nx 或类似结构，Services 会很适合。</p><h3 id="前后端分离项目"><a href="#前后端分离项目" class="headerlink" title="前后端分离项目"></a>前后端分离项目</h3><p>例如：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">frontend/</span><br><span class="line">backend/</span><br></pre></td></tr></table></figure><p>前端用 Next.js，后端用 FastAPI、Go 或其他框架。</p><p>以前这类项目在 Vercel 上不够自然，现在可以通过 Services 放在一个 Project 内。</p><h3 id="多个后台服务"><a href="#多个后台服务" class="headerlink" title="多个后台服务"></a>多个后台服务</h3><p>有些项目可能不只是一个 API：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">services/auth</span><br><span class="line">services/payment</span><br><span class="line">services/webhook</span><br><span class="line">services/image</span><br></pre></td></tr></table></figure><p>它们可以分别通过不同路径公开：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">/auth</span><br><span class="line">/payment</span><br><span class="line">/webhook</span><br><span class="line">/image</span><br></pre></td></tr></table></figure><p>也可以只让部分服务公开，其他服务保持内部访问。</p><h3 id="静态站点-后台接口"><a href="#静态站点-后台接口" class="headerlink" title="静态站点 + 后台接口"></a>静态站点 + 后台接口</h3><p>比如：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">apps/site      -&gt; Astro / Vite / Hexo 构建后的静态站</span><br><span class="line">backend/api    -&gt; Python / Node.js API</span><br></pre></td></tr></table></figure><p>对于个人项目、工具站、轻量 SaaS、文档站 + API 的组合，这个功能会很有吸引力。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>Vercel Services 的意义在于，它让 Vercel 从“一个项目部署一个框架”更进一步，变成 <strong>一个项目可以承载多个框架、多个服务</strong> 。</p><p>对于现代 Web 项目来说，这个变化非常实用。</p><p>过去我们经常需要在多个 Vercel Project、多个域名、多个 Preview URL 之间来回切换。现在，前端、后端、管理后台、文档站、工具页都可以作为一个项目里的多个服务统一部署。</p><p>它尤其适合：</p><ul><li>Monorepo</li><li>前后端分离项目</li><li>Python + JavaScript 混合项目</li><li>Go + Next.js 混合项目</li><li>多框架应用</li><li>个人工具站</li><li>小型 SaaS</li><li>静态站点 + API 的组合</li></ul><p>如果你一直想把一个复杂项目整理成更清晰的部署结构，Vercel Services 值得关注。</p><p>它不是 Docker Compose 的替代品，也不是所有项目都必须使用的新能力。但对于已经开始变复杂的前端项目、个人工具站和轻量全栈应用来说，它确实让 Vercel 的部署模型更完整了。</p><h2 id="参控"><a href="#参控" class="headerlink" title="参控"></a>参控</h2><ul><li><a href="https://vercel.com/docs/services">Vercel - Services</a></li><li><a href="https://vercel.com/changelog/run-multiple-frameworks-in-one-project-with-vercel-services">Run multiple frameworks in one project with Vercel Services</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;当你手头有一个包含 Next.js 前端、FastAPI 后端、Go 服务和 Astro 文档站的复杂项目时，是否也曾为如何在 Vercel 上部署和管理而感到头疼？&lt;/p&gt;
&lt;p&gt;过去，这类项目往往需要拆成多个 Vercel Project，或者把部分服务放到其他平台上运</summary>
      
    
    
    
    <category term="资讯" scheme="https://ooo.run/categories/%E8%B5%84%E8%AE%AF/"/>
    
    
    <category term="Vercel" scheme="https://ooo.run/tags/Vercel/"/>
    
    <category term="Cloud" scheme="https://ooo.run/tags/Cloud/"/>
    
    <category term="前端开发" scheme="https://ooo.run/tags/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
    
  </entry>
  
  <entry>
    <title>后端回来了：Vercel 支持直接运行 Dockerfile</title>
    <link href="https://ooo.run/post/backends-are-back-vercel-support-dockerfile.html"/>
    <id>https://ooo.run/post/backends-are-back-vercel-support-dockerfile.html</id>
    <published>2026-06-30T15:51:53.000Z</published>
    <updated>2026-06-30T16:12:26.430Z</updated>
    
    <content type="html"><![CDATA[<p>你是否也想过用部署前端的丝滑体验来部署后端 Docker 服务？<strong>Vercel</strong> 近日正式支持直接运行 <strong>Dockerfile</strong>！本文我们将深入解析这一重磅更新、适用场景以及 Fluid Compute 底层机制。</p><span id="more"></span><p>北京时间 2026 年 7 月 1 日， <strong>Vercel</strong> 在官网宣布正式支持 <a href="https://vercel.com/blog/dockerfile-on-vercel">通过 Dockerfile 部署应用</a>，并在文章结尾喊出了 <mark>Backends are back</mark>。开发者现在可以在项目中添加 <code>Dockerfile.vercel</code>，让 <strong>Vercel</strong> 自动完成镜像构建、镜像存储和部署，并将应用运行在 <strong>Fluid Compute</strong> 之上。</p><p>这项更新意味着，<strong>Vercel</strong> 不再只是一个更适合 <strong>Next.js</strong>、前端应用和 <strong>Serverless Functions</strong> 的平台，而是进一步向自定义后端服务 and 通用 Web 应用运行平台扩展。</p><ul><li><a href="https://vercel.com/docs/functions/container-images">文档</a></li><li><a href="https://vercel.com/templates">示例</a></li></ul><details class="flatpaper-note flatpaper-note--warning"><summary class="flatpaper-note__title"><span class="flatpaper-note__icon" aria-hidden="true"></span><span class="flatpaper-note__label">注意事项</span><span class="flatpaper-note__chevron" aria-hidden="true"></span></summary><div class="flatpaper-note__body"><p>这并不等于 <strong>Vercel</strong> 可以运行任何 <strong>Docker</strong> 应用。更准确地说，<strong>Vercel</strong> 支持的是通过 <strong>Dockerfile</strong> 描述构建过程、并以 HTTP 服务形式运行的无状态应用。</p><p>应用需要监听平台注入的端口，并把数据库、文件、缓存等持久化状态交给外部服务处理。</p></div></details><p><img src="https://img.nep.me/ooo/cover-vercel-dockerfile.webp" alt="Vercel Support Dockerfile"></p><h2 id="什么是-Dockerfile？"><a href="#什么是-Dockerfile？" class="headerlink" title="什么是 Dockerfile？"></a>什么是 Dockerfile？</h2><p><strong>Dockerfile</strong> 是一个用来描述“如何构建 Docker 镜像”的文本文件。</p><p>它通常会写明应用基于什么系统或运行时镜像、需要安装哪些依赖、复制哪些代码、执行什么构建命令，以及容器启动时应该运行什么程序。简单来说，<strong>Dockerfile</strong> 不是应用本身，而是应用运行环境的说明书。</p><p>例如，一个 <strong>Node.js</strong> Web 服务的 <strong>Dockerfile</strong> 可能长这样：</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> node:<span class="number">22</span>-alpine</span><br><span class="line"></span><br><span class="line"><span class="keyword">WORKDIR</span><span class="language-bash"> /app</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> package.json pnpm-lock.yaml ./</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> corepack <span class="built_in">enable</span> &amp;&amp; pnpm install --frozen-lockfile</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> . .</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> pnpm build</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> [<span class="string">&quot;pnpm&quot;</span>, <span class="string">&quot;start&quot;</span>]</span></span><br></pre></td></tr></table></figure><p>这个文件表达的意思是：使用 <strong>Node.js 22</strong> 作为基础环境，安装依赖，复制项目代码，执行构建，最后启动应用。</p><p>对于开发者来说，<strong>Dockerfile</strong> 最大的价值是“可复现”。只要 <strong>Dockerfile</strong> 写得清楚，无论是在本地、CI、云平台还是其他服务器上，都可以构建出相对一致的运行环境。</p><p>这也是 <strong>Vercel</strong> 支持 <strong>Dockerfile</strong> 的意义：当平台无法通过框架自动识别一个项目应该如何构建和运行时，开发者可以直接用 <strong>Dockerfile</strong> 明确告诉 <strong>Vercel</strong>。</p><h2 id="Dockerfile-和-docker-compose-yaml-有什么区别？"><a href="#Dockerfile-和-docker-compose-yaml-有什么区别？" class="headerlink" title="Dockerfile 和 docker-compose.yaml 有什么区别？"></a>Dockerfile 和 docker-compose.yaml 有什么区别？</h2><p>很多人会把 <strong>Dockerfile</strong> 和 <code>docker-compose.yaml</code> 混在一起，但它们其实解决的是两个不同层级的问题。</p><p><strong>Dockerfile</strong> 负责“构建一个镜像”，而 <code>docker-compose.yaml</code> 负责“编排多个容器”。</p><p>举个例子，一个 Web 应用可能需要：</p><ul><li>一个 <strong>Next.js</strong> 前端；</li><li>一个 <strong>Express</strong> API；</li><li>一个 <strong>PostgreSQL</strong> 数据库；</li><li>一个 <strong>Redis</strong> 缓存；</li><li>一个 <strong>MinIO</strong> 对象存储。</li></ul><p>其中，<strong>Express</strong> API 自己可以有一个 <strong>Dockerfile</strong>，用来描述 API 镜像怎么构建。而 <code>docker-compose.yaml</code> 则负责把 API、数据库、Redis、MinIO 这些服务一起启动，并配置端口、环境变量、数据卷和服务之间的网络关系。</p><p>简单对比如下：</p><table><thead><tr><th>项目</th><th>Dockerfile</th><th>docker-compose.yaml</th></tr></thead><tbody><tr><td>主要作用</td><td>构建单个镜像</td><td>启动和编排多个容器</td></tr><tr><td>关注重点</td><td>应用如何打包、安装依赖、启动</td><td>多个服务如何协作</td></tr><tr><td>常见内容</td><td>FROM、RUN、COPY、CMD</td><td>services、ports、volumes、networks</td></tr><tr><td>适合场景</td><td>定义一个应用的运行环境</td><td>本地开发、多容器部署、服务编排</td></tr><tr><td>是否包含数据库编排</td><td>通常不包含</td><td>可以包含 PostgreSQL、Redis 等</td></tr><tr><td>Vercel 此次支持重点</td><td>是</td><td>不是传统 Compose 部署</td></tr></tbody></table><details class="flatpaper-note flatpaper-note--info"><summary class="flatpaper-note__title"><span class="flatpaper-note__icon" aria-hidden="true"></span><span class="flatpaper-note__label">核心差异</span><span class="flatpaper-note__chevron" aria-hidden="true"></span></summary><div class="flatpaper-note__body"><p><strong>Vercel</strong> 这次支持的是 <strong>Dockerfile</strong>，而不是把 <strong>Vercel</strong> 变成一台可以直接运行完整 <code>docker compose up -d</code> 的 <strong>VPS</strong>。</p><p>你可以把一个 HTTP 服务通过 <strong>Dockerfile</strong> 部署到 <strong>Vercel</strong>，但不能直接把一整套包含数据库、Redis、后台 worker、对象存储、管理面板的 Compose 栈原样搬到 <strong>Vercel</strong> 上运行。</p></div></details><h2 id="Vercel-支持的是什么类型的-Docker-应用？"><a href="#Vercel-支持的是什么类型的-Docker-应用？" class="headerlink" title="Vercel 支持的是什么类型的 Docker 应用？"></a>Vercel 支持的是什么类型的 Docker 应用？</h2><p><strong>Vercel</strong> 官方文档中，后端框架如 <strong>Express</strong>、<strong>Fastify</strong> 等会作为 Vercel Function 运行，并默认使用 <strong>Fluid Compute</strong>；<strong>Fluid Compute</strong> 可以让应用根据流量自动伸缩，并支持更高效的并发处理。</p><p>从使用模型看，适合部署到 <strong>Vercel</strong> 的 <strong>Dockerfile</strong> 应用通常具备几个特征：</p><ul><li>是 Web 服务或 API 服务；</li><li>通过 HTTP 对外提供能力；</li><li>能监听平台提供的端口；</li><li>本身无状态；</li><li>数据库存储、文件上传、缓存、队列等依赖外部托管服务。</li></ul><p>下面我们通过 Tab 栏来看看适合与不适合部署到 <strong>Vercel</strong> 的应用类型对比：</p><div class="flatpaper-tabs"><div class="flatpaper-tabs__nav" role="tablist"><button type="button" role="tab" id="tabs-17-tab-0" aria-controls="tabs-17-panel-0" aria-selected="true" class="flatpaper-tabs__nav-item is-active" data-index="0">适合部署的类型</button><button type="button" role="tab" id="tabs-17-tab-1" aria-controls="tabs-17-panel-1" aria-selected="false" class="flatpaper-tabs__nav-item" data-index="1">不适合部署的类型</button></div><div class="flatpaper-tabs__panels"><section role="tabpanel" id="tabs-17-panel-0" aria-labelledby="tabs-17-tab-0" class="flatpaper-tabs__panel is-active" data-index="0"><table><thead><tr><th>应用类型</th><th>示例</th></tr></thead><tbody><tr><td>Web 后端 API</td><td>Express、Hono、Fastify、FastAPI、Go HTTP Server</td></tr><tr><td>全栈 Web 应用</td><td>Next.js、Nuxt、SvelteKit、TanStack Start</td></tr><tr><td>内容网站</td><td>博客、文档站、企业官网、CMS 前台</td></tr><tr><td>Bot &#x2F; Webhook 服务</td><td>Slack Bot、GitHub Webhook、MCP Server</td></tr><tr><td>AI 工具后端</td><td>Chatbot API、Agent 控制层、图片处理入口</td></tr><tr><td>轻量内部工具</td><td>Dashboard、Admin Panel、数据查询面板</td></tr></tbody></table></section><section role="tabpanel" id="tabs-17-panel-1" aria-labelledby="tabs-17-tab-1" class="flatpaper-tabs__panel" data-index="1" hidden><table><thead><tr><th>应用类型</th><th>原因</th></tr></thead><tbody><tr><td>PostgreSQL、MySQL、Redis</td><td>需要长期持久化状态和磁盘</td></tr><tr><td>1Panel、宝塔、CasaOS</td><td>依赖完整服务器环境和系统级能力</td></tr><tr><td>Docker Compose 多容器栈</td><td>Vercel 不是传统容器编排平台</td></tr><tr><td>BT 下载器、网盘服务</td><td>通常需要长时间运行和本地持久化</td></tr><tr><td>游戏服务器、VPN、代理服务</td><td>不属于普通 HTTP Web 应用模型</td></tr><tr><td>强依赖本地磁盘的应用</td><td>容器实例应视为无状态</td></tr></tbody></table></section></div></div><p>换句话说，<strong>Vercel</strong> 支持 <strong>Dockerfile</strong> 后，部署范围确实扩大了，但它依然不是 <strong>VPS</strong>，也不是 <strong>Kubernetes</strong> 的替代品。</p><h2 id="从-Vercel-Templates-看适合的应用场景"><a href="#从-Vercel-Templates-看适合的应用场景" class="headerlink" title="从 Vercel Templates 看适合的应用场景"></a>从 Vercel Templates 看适合的应用场景</h2><p>从 <a href="https://vercel.com/templates">Vercel Templates</a> 页面也可以看出，<strong>Vercel</strong> 目前重点覆盖的仍然是 Web 应用、后端 API、AI 应用和全栈项目，而不是传统意义上的服务器软件。<strong>Vercel</strong> 的 Backend Templates 中已经包含 <strong>Hono</strong>、<strong>Express</strong>、<strong>Elysia</strong>、<strong>MCP Server</strong>、<strong>Slack Bolt</strong> 等模板，这些都属于轻量 HTTP 服务、Bot 后端、Webhook 服务或 AI 工具后端。</p><p>Starter Templates 中也可以看到 <strong>Next.js</strong>、<strong>Nuxt</strong>、<strong>SvelteKit</strong>、<strong>Rust Hello World</strong>、<strong>Rust Axum</strong>、<strong>TanStack Start</strong>、<strong>Slack Bolt with Hono</strong> 等模板。这说明 <strong>Vercel</strong> 希望覆盖的不只是前端页面，也包括通过 HTTP 暴露能力的后端程序。</p><p><strong>Payload Website Starter</strong> 是另一个很典型的例子。这个模板包含后台管理、认证、内容发布、草稿预览、SEO、搜索、重定向、定时发布等功能，但它会配合 <strong>Neon Database</strong> 和 <strong>Vercel Blob Storage</strong> 等外部服务处理数据库和文件存储。</p><p>这其实体现了 <strong>Vercel</strong> 的推荐架构：计算放在 <strong>Vercel</strong>，状态放在外部托管服务。</p><h2 id="为什么这次更新重要？"><a href="#为什么这次更新重要？" class="headerlink" title="为什么这次更新重要？"></a>为什么这次更新重要？</h2><p>过去，<strong>Vercel</strong> 的最佳体验主要集中在 <strong>Next.js</strong> 和前端生态。虽然 <strong>Vercel</strong> 也支持多种 <strong>Serverless Functions</strong> 和后端框架，但如果项目需要特殊系统依赖、自定义启动命令、非标准框架、<strong>FFmpeg</strong>、<strong>Chromium</strong>、<strong>nginx</strong> 或其他复杂运行环境，就可能需要额外改造。</p><p><strong>Dockerfile</strong> 支持补上了这块短板。</p><p>开发者不再必须完全适配 <strong>Vercel</strong> 的框架检测逻辑，而是可以用 <strong>Dockerfile</strong> 描述自己的应用如何构建、如何启动。对于传统后端项目、跨语言服务、AI 工具后端 and 自定义 Web Server 来说，这会明显降低迁移成本。</p><p>同时，部署到 <strong>Vercel</strong> 后，应用仍然可以获得 <strong>Vercel</strong> 原有的工程体验，例如 <strong>Git</strong> 集成、<strong>Preview Deployment</strong>、自动伸缩、日志、指标、回滚和平台级安全能力。<strong>Vercel</strong> 的 Functions 文档也强调，平台会根据框架自动设置构建和优化，并通过 CDN 与函数运行环境提供低运维体验。</p><h2 id="Fluid-Compute：介于-Serverless-和服务器之间"><a href="#Fluid-Compute：介于-Serverless-和服务器之间" class="headerlink" title="Fluid Compute：介于 Serverless 和服务器之间"></a>Fluid Compute：介于 Serverless 和服务器之间</h2><p><strong>Vercel</strong> 这次 <strong>Dockerfile</strong> 支持的底层重点之一，是 <strong>Fluid Compute</strong>。</p><p>根据 <strong>Vercel</strong> 文档，<strong>Fluid Compute</strong> 是一种介于传统 <strong>Serverless</strong> 和服务器之间的计算模型。它保留了 <strong>Serverless</strong> 的自动伸缩和低运维优势，同时加入了类似服务器的能力，例如同一个实例可以并发处理多个请求。</p><p>对于 AI 应用、API 服务和 I&#x2F;O 密集型任务来说，这一点很重要。很多请求的大部分时间并不是 CPU 真正在计算，而是在等待数据库、向量数据库、外部 API 或模型服务返回结果。<strong>Fluid Compute</strong> 的并发模型可以让同一个实例更有效地处理这些等待时间。</p><p><strong>Vercel</strong> 的 <strong>Fluid Compute</strong> 文档也提到，它支持 <strong>Node.js</strong>、<strong>Python</strong>、<strong>Edge</strong>、<strong>Bun</strong>、<strong>Rust</strong> 等运行时，并且适合需要优化并发和减少冷启动影响的场景。</p><h2 id="计费方式：按实际资源使用付费"><a href="#计费方式：按实际资源使用付费" class="headerlink" title="计费方式：按实际资源使用付费"></a>计费方式：按实际资源使用付费</h2><p><strong>Vercel</strong> 在 <strong>Fluid Compute</strong> 的计费文档中使用 CPU 与内存维度计算资源消耗。例如，一个请求如果实例存活 10 秒，但实际活跃 CPU 时间只有 4 秒，费用会拆分为 CPU 使用和内存占用两部分计算。</p><p>这说明 <strong>Vercel</strong> 并不是按照传统 VPS 那样“买一台机器一直开着”来计费，而是更接近按请求、按资源消耗计费的云函数模型。</p><details class="flatpaper-note flatpaper-note--info"><summary class="flatpaper-note__title"><span class="flatpaper-note__icon" aria-hidden="true"></span><span class="flatpaper-note__label">成本考量</span><span class="flatpaper-note__chevron" aria-hidden="true"></span></summary><div class="flatpaper-note__body"><p>对于低频访问、突发流量、I&#x2F;O 等待较多的 Web 服务来说，这种模式可能更划算。但对于需要 24 小时高负载运行、持续占用 CPU 或内存的服务，传统 VPS、专用服务器或 Kubernetes 仍然可能更合适。</p></div></details><h2 id="这不是-VPS，但让-Vercel-更像完整应用平台"><a href="#这不是-VPS，但让-Vercel-更像完整应用平台" class="headerlink" title="这不是 VPS，但让 Vercel 更像完整应用平台"></a>这不是 VPS，但让 Vercel 更像完整应用平台</h2><p><strong>Vercel</strong> 支持 <strong>Dockerfile</strong> 后，最容易产生的误解是：“是不是以后所有 Docker 应用都能放到 Vercel？”</p><p>答案是否定的。</p><p>它不能取代 <strong>VPS</strong>，也不能取代 <strong>Docker Compose</strong> 或 <strong>Kubernetes</strong>。它更适合部署单个 Web 服务、API 服务、全栈应用或 AI 工具后端，而不是运行一整套长期常驻、强依赖本地磁盘和系统权限的服务器环境。</p><p>但这次更新依然非常重要。因为它把 <strong>Vercel</strong> 的边界从“框架友好的前端和全栈应用”继续推向“更通用的 HTTP 后端服务”。</p><p>对于开发者来说，理想场景可能是：</p><ul><li>前端页面部署在 <strong>Vercel</strong>；</li><li>后端 API 通过 <strong>Dockerfile</strong> 部署到 <strong>Vercel</strong>；</li><li><strong>PostgreSQL</strong> 使用 <strong>Neon</strong>、<strong>Supabase</strong> 或其他托管数据库；</li><li>文件存储使用 <strong>Vercel Blob</strong>、<strong>S3</strong> 或 <strong>R2</strong>；</li><li>缓存和队列使用外部托管 <strong>Redis</strong> 或消息队列；</li><li>每次 Git push 自动生成 Preview 环境。</li></ul><p>这是一种更现代的云应用部署方式：不再维护服务器本身，而是把应用拆成计算、数据库、对象存储、缓存和队列等托管组件。</p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p><strong>Vercel</strong> 支持 <strong>Dockerfile</strong>，并不是简单地“支持 Docker”这么一句话就能概括。</p><p>它真正改变的是：开发者可以用更标准、更通用的方式，把自定义 HTTP 服务部署到 <strong>Vercel</strong>。对于那些无法被框架自动识别、但本质上仍然是 Web 服务的项目，<strong>Dockerfile</strong> 提供了一条更直接的上云路径。</p><p>不过，<strong>Dockerfile on Vercel</strong> 不是 <strong>Docker Compose on Vercel</strong>，也不是 <strong>VPS on Vercel</strong>。</p><p>它适合的是无状态 HTTP 应用，而不是完整服务器环境。</p><p>如果说过去 <strong>Vercel</strong> 最擅长的是前端部署体验，那么这次 <strong>Dockerfile</strong> 支持，则让更多后端服务也能享受到类似的开发体验：一次提交、自动构建、自动预览、自动伸缩，并在同一个平台上完成发布。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;你是否也想过用部署前端的丝滑体验来部署后端 Docker 服务？&lt;strong&gt;Vercel&lt;/strong&gt; 近日正式支持直接运行 &lt;strong&gt;Dockerfile&lt;/strong&gt;！本文我们将深入解析这一重磅更新、适用场景以及 Fluid Compute 底层机制。&lt;/p&gt;</summary>
    
    
    
    <category term="资讯" scheme="https://ooo.run/categories/%E8%B5%84%E8%AE%AF/"/>
    
    
    <category term="Vercel" scheme="https://ooo.run/tags/Vercel/"/>
    
    <category term="Dockerfile" scheme="https://ooo.run/tags/Dockerfile/"/>
    
    <category term="Serverless" scheme="https://ooo.run/tags/Serverless/"/>
    
    <category term="Cloud" scheme="https://ooo.run/tags/Cloud/"/>
    
  </entry>
  
  <entry>
    <title>2026 Debian 13 安装 Docker 以及 Docker Compose 教程</title>
    <link href="https://ooo.run/post/debian-13-install-docker.html"/>
    <id>https://ooo.run/post/debian-13-install-docker.html</id>
    <published>2026-06-29T20:15:00.000Z</published>
    <updated>2026-06-29T20:27:15.611Z</updated>
    
    <content type="html"><![CDATA[<p>现在越来越多的应用可以使用 <strong>Docker</strong> 一键部署，本文将介绍如何在最新的 Debian 13 (Trixie) 中安装 <strong>Docker</strong> 与 <strong>Docker Compose</strong>。</p><p>验证环境</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">root@debian:~# lsb_release -a</span><br><span class="line">No LSB modules are available.</span><br><span class="line">Distributor ID:Debian</span><br><span class="line">Description:Debian GNU/Linux 13 (trixie)</span><br><span class="line">Release:13</span><br><span class="line">Codename:trixie</span><br></pre></td></tr></table></figure><p>安装同样适用于 Ubuntu 26.04。</p><h2 id="Docker-介绍"><a href="#Docker-介绍" class="headerlink" title="Docker 介绍"></a>Docker 介绍</h2><p><strong>Docker</strong> 是一个开源的容器化平台，它可以将应用程序及其依赖打包到一个轻量级、可移植的容器中，使其能够在任何环境中一致地运行。</p><ul><li><strong>轻量</strong>：容器共享宿主机的操作系统内核，启动速度快，占用资源少。</li><li><strong>可移植</strong>：容器可以在开发、测试和生产环境中一致运行，解决“环境不一致”的问题。</li><li><strong>隔离性</strong>：每个容器都是独立运行的，互不影响。</li><li><strong>快速部署</strong>：通过镜像技术，实现应用的快速打包、发布和部署。</li></ul><h2 id="Docker-Compose-介绍"><a href="#Docker-Compose-介绍" class="headerlink" title="Docker Compose 介绍"></a>Docker Compose 介绍</h2><p><strong>Docker Compose</strong> 是 <strong>Docker</strong> 提供的用于定义和管理多容器应用的工具。通过一个简单的 YAML 文件 <code>docker-compose.yml</code>，你可以定义和启动多个服务容器，使得应用的部署和管理更加便捷，可以不必使用长串的 <code>docker run</code> 命令。 </p><p>特点：</p><ul><li><strong>多容器管理</strong>：同时启动、停止和管理多个容器。</li><li><strong>通过 YAML 配置</strong>：通过 <code>docker-compose.yml</code> 定义服务、网络、存储等。</li><li><strong>简化命令</strong>：使用单一命令 <code>docker compose</code> 管理容器。</li></ul><p>本文将介绍安装 V2 版本，对应的命令是 <code>docker compose</code>。</p><h2 id="使用官方源安装"><a href="#使用官方源安装" class="headerlink" title="使用官方源安装"></a>使用官方源安装</h2><p>以下操作需要在 root 用户下完成，请使用 <code>sudo -i</code> 或 <code>su root</code> 切换到 root 用户进行操作。</p><p>首先，安装一些必要的软件包： </p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">apt update</span><br><span class="line">apt upgrade -y</span><br><span class="line">apt install curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates</span><br></pre></td></tr></table></figure><p>然后加入 <strong>Docker</strong> 的 GPG 公钥和 apt 源：</p><div class="flatpaper-tabs"><div class="flatpaper-tabs__nav" role="tablist"><button type="button" role="tab" id="tabs-18-tab-0" aria-controls="tabs-18-panel-0" aria-selected="true" class="flatpaper-tabs__nav-item is-active" data-index="0">Debian</button><button type="button" role="tab" id="tabs-18-tab-1" aria-controls="tabs-18-panel-1" aria-selected="false" class="flatpaper-tabs__nav-item" data-index="1">Ubuntu</button></div><div class="flatpaper-tabs__panels"><section role="tabpanel" id="tabs-18-panel-0" aria-labelledby="tabs-18-tab-0" class="flatpaper-tabs__panel is-active" data-index="0"><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">curl -sSL https://download.docker.com/linux/debian/gpg | gpg --dearmor &gt; /usr/share/keyrings/docker-ce.gpg</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;deb [arch=<span class="subst">$(dpkg --print-architecture)</span> signed-by=/usr/share/keyrings/docker-ce.gpg] https://download.docker.com/linux/debian <span class="subst">$(lsb_release -sc)</span> stable&quot;</span> &gt; /etc/apt/sources.list.d/docker.list</span><br></pre></td></tr></table></figure></section><section role="tabpanel" id="tabs-18-panel-1" aria-labelledby="tabs-18-tab-1" class="flatpaper-tabs__panel" data-index="1" hidden><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">curl -sSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor &gt; /usr/share/keyrings/docker-ce.gpg</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;deb [arch=<span class="subst">$(dpkg --print-architecture)</span> signed-by=/usr/share/keyrings/docker-ce.gpg] https://download.docker.com/linux/ubuntu <span class="subst">$(lsb_release -sc)</span> stable&quot;</span> &gt; /etc/apt/sources.list.d/docker.list</span><br></pre></td></tr></table></figure></section></div></div><p>国内机器可以用 <a href="https://mirrors.tuna.tsinghua.edu.cn/">清华 TUNA</a> 的国内源：</p><div class="flatpaper-tabs"><div class="flatpaper-tabs__nav" role="tablist"><button type="button" role="tab" id="tabs-19-tab-0" aria-controls="tabs-19-panel-0" aria-selected="true" class="flatpaper-tabs__nav-item is-active" data-index="0">Debian</button><button type="button" role="tab" id="tabs-19-tab-1" aria-controls="tabs-19-panel-1" aria-selected="false" class="flatpaper-tabs__nav-item" data-index="1">Ubuntu</button></div><div class="flatpaper-tabs__panels"><section role="tabpanel" id="tabs-19-panel-0" aria-labelledby="tabs-19-tab-0" class="flatpaper-tabs__panel is-active" data-index="0"><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">curl -sS https://download.docker.com/linux/debian/gpg | gpg --dearmor &gt; /usr/share/keyrings/docker-ce.gpg</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;deb [arch=<span class="subst">$(dpkg --print-architecture)</span> signed-by=/usr/share/keyrings/docker-ce.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian <span class="subst">$(lsb_release -sc)</span> stable&quot;</span> &gt; /etc/apt/sources.list.d/docker.list</span><br></pre></td></tr></table></figure></section><section role="tabpanel" id="tabs-19-panel-1" aria-labelledby="tabs-19-tab-1" class="flatpaper-tabs__panel" data-index="1" hidden><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">curl -sS https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor &gt; /usr/share/keyrings/docker-ce.gpg</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;deb [arch=<span class="subst">$(dpkg --print-architecture)</span> signed-by=/usr/share/keyrings/docker-ce.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu <span class="subst">$(lsb_release -sc)</span> stable&quot;</span> &gt; /etc/apt/sources.list.d/docker.list</span><br></pre></td></tr></table></figure></section></div></div><p>然后更新系统后即可安装 Docker CE 和 Docker Compose 插件：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">apt update</span><br><span class="line">apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin</span><br></pre></td></tr></table></figure><p>此时可以使用 <code>docker version</code> 命令检查是否安装成功：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">Client: Docker Engine - Community</span><br><span class="line"> Version:           29.6.1</span><br><span class="line"> API version:       1.55</span><br><span class="line"> Go version:        go1.26.4</span><br><span class="line"> Git commit:        8900f1d</span><br><span class="line"> Built:             Fri Jun 26 11:40:34 2026</span><br><span class="line"> OS/Arch:           linux/amd64</span><br><span class="line"> Context:           default</span><br><span class="line"></span><br><span class="line">Server: Docker Engine - Community</span><br><span class="line"> Engine:</span><br><span class="line">  Version:          29.6.1</span><br><span class="line">  API version:      1.55 (minimum version 1.40)</span><br><span class="line">  Go version:       go1.26.4</span><br><span class="line">  Git commit:       8ec5ab3</span><br><span class="line">  Built:            Fri Jun 26 11:40:34 2026</span><br><span class="line">  OS/Arch:          linux/amd64</span><br><span class="line">  Experimental:     <span class="literal">false</span></span><br><span class="line"> containerd:</span><br><span class="line">  Version:          v2.2.5</span><br><span class="line">  GitCommit:        e53c7c1516c3b2bff98eb76f1f4117477e6f4e66</span><br><span class="line"> runc:</span><br><span class="line">  Version:          1.3.6</span><br><span class="line">  GitCommit:        v1.3.6-0-g491b69ba</span><br><span class="line"> docker-init:</span><br><span class="line">  Version:          0.19.0</span><br><span class="line">  GitCommit:        de40ad0</span><br></pre></td></tr></table></figure><p>如果需要以非 root 模式运行 <strong>Docker</strong>，那么可以把特定用户也加入 docker 组，比如我们把 <code>www-data</code> 用户加进去：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">apt install docker-ce-rootless-extras</span><br><span class="line"><span class="built_in">sudo</span> usermod -aG docker www-data</span><br></pre></td></tr></table></figure><h2 id="Docker-Compose-V2"><a href="#Docker-Compose-V2" class="headerlink" title="Docker Compose V2"></a>Docker Compose V2</h2><p><strong>Docker</strong> 已自带 Docker Compose V2 版本，即 <code>docker compose</code> 命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">root@debian:~# docker compose version </span><br><span class="line">Docker Compose version v5.2.0</span><br></pre></td></tr></table></figure><h2 id="修改-Docker-配置"><a href="#修改-Docker-配置" class="headerlink" title="修改 Docker 配置"></a>修改 Docker 配置</h2><p>以下配置会增加一段自定义内网 IPv6 地址，开启容器的 IPv6 功能，以及限制日志文件大小，防止 <strong>Docker</strong> 日志塞满硬盘：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cat</span> &gt; /etc/docker/daemon.json &lt;&lt; <span class="string">EOF</span></span><br><span class="line"><span class="string">&#123;</span></span><br><span class="line"><span class="string">    &quot;log-driver&quot;: &quot;json-file&quot;,</span></span><br><span class="line"><span class="string">    &quot;log-opts&quot;: &#123;</span></span><br><span class="line"><span class="string">        &quot;max-size&quot;: &quot;20m&quot;,</span></span><br><span class="line"><span class="string">        &quot;max-file&quot;: &quot;3&quot;</span></span><br><span class="line"><span class="string">    &#125;,</span></span><br><span class="line"><span class="string">    &quot;ipv6&quot;: true,</span></span><br><span class="line"><span class="string">    &quot;fixed-cidr-v6&quot;: &quot;fd00:dead:beef:c0::/80&quot;,</span></span><br><span class="line"><span class="string">    &quot;experimental&quot;:true,</span></span><br><span class="line"><span class="string">    &quot;ip6tables&quot;:true</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string">EOF</span></span><br></pre></td></tr></table></figure><p>然后重启 <strong>Docker</strong> 服务：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl restart docker</span><br></pre></td></tr></table></figure><h2 id="Docker-常用命令使用介绍"><a href="#Docker-常用命令使用介绍" class="headerlink" title="Docker 常用命令使用介绍"></a>Docker 常用命令使用介绍</h2><p>快速了解一下 <code>docker</code> 常见命令，使用 <code>docker compose</code> 进行管理会更方便。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 拉取镜像</span></span><br><span class="line">docker pull &lt;镜像名&gt;:&lt;标签&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看当前正在运行的容器</span></span><br><span class="line">docker ps</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看所有容器（包括已停止的）</span></span><br><span class="line">docker ps -a</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看本地镜像</span></span><br><span class="line">docker images</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除镜像</span></span><br><span class="line">docker rmi &lt;镜像ID或名称&gt;</span><br><span class="line">docker rmi ubuntu:latest</span><br><span class="line"></span><br><span class="line"><span class="comment"># 运行容器 </span></span><br><span class="line">docker run -d -p &lt;宿主端口&gt;:&lt;容器端口&gt; --name &lt;容器名&gt; &lt;镜像名&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动，停止，重启，删除</span></span><br><span class="line">docker start / stop / restart / <span class="built_in">rm</span> &lt;容器名或ID&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 进入容器执行交互式命令</span></span><br><span class="line">docker <span class="built_in">exec</span> -it &lt;容器名或ID&gt; /bin/bash</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看容器日志</span></span><br><span class="line">docker logs &lt;容器名或ID&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查询 Docker 使用的磁盘空间：</span></span><br><span class="line">docker system <span class="built_in">df</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除所有未被使用的镜像</span></span><br><span class="line">docker image prune -a</span><br></pre></td></tr></table></figure><h2 id="Docker-Compose-使用介绍"><a href="#Docker-Compose-使用介绍" class="headerlink" title="Docker Compose 使用介绍"></a>Docker Compose 使用介绍</h2><p><code>docker compose</code> 需要在 <code>docker-compose.yml</code> 文件所在的工作目录执行，这里推荐创建一个工作目录，在其中统一存放配置文件，比如： </p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">docker/</span><br><span class="line">├── nginx/                         </span><br><span class="line">│   └── docker-compose.yml            </span><br><span class="line">├── mysql/                          </span><br><span class="line">│   └── docker-compose.yml          </span><br><span class="line">└── redis/                           </span><br><span class="line">    └── docker-compose.yml   </span><br></pre></td></tr></table></figure><p><code>docker compose</code> 常用命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 拉取，更新镜像</span></span><br><span class="line">docker compose pull</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动容器</span></span><br><span class="line">docker compose up</span><br><span class="line"></span><br><span class="line"><span class="comment"># 后台启动</span></span><br><span class="line">docker compose up -d</span><br><span class="line"></span><br><span class="line"><span class="comment"># 停止容器</span></span><br><span class="line">docker compose stop</span><br><span class="line"></span><br><span class="line"><span class="comment"># 停止容器，并移除创建的网络、卷和镜像</span></span><br><span class="line">docker compose down</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启容器</span></span><br><span class="line">docker compose restart</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看正在运行的服务</span></span><br><span class="line">docker compose ps</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看日志</span></span><br><span class="line">docker compose logs</span><br><span class="line"><span class="comment"># 查看实时日志</span></span><br><span class="line">docker compose logs -f</span><br><span class="line"></span><br><span class="line"><span class="comment"># 进入容器。执行交互命令</span></span><br><span class="line">docker compose <span class="built_in">exec</span> &lt;服务名&gt; &lt;命令&gt;</span><br><span class="line">docker compose <span class="built_in">exec</span> nginx /bin/bash</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看服务统计信息，实时显示 CPU、内存等资源使用情况。</span></span><br><span class="line">docker compose stats</span><br></pre></td></tr></table></figure><p><code>docker compose</code> 还是太长？ 执行下面的命令后就可以使用 <code>dc</code> 作为替代：</p><div class="flatpaper-note flatpaper-note--info"><span class="flatpaper-note__icon" aria-hidden="true"></span><div class="flatpaper-note__body"><p>执行前，先运行一下 <code>dc</code> 确认命令当前没有在使用，执行后运行 <code>dc version</code> 确认。</p></div></div><div class="flatpaper-tabs"><div class="flatpaper-tabs__nav" role="tablist"><button type="button" role="tab" id="tabs-20-tab-0" aria-controls="tabs-20-panel-0" aria-selected="true" class="flatpaper-tabs__nav-item is-active" data-index="0">bash</button><button type="button" role="tab" id="tabs-20-tab-1" aria-controls="tabs-20-panel-1" aria-selected="false" class="flatpaper-tabs__nav-item" data-index="1">zsh</button></div><div class="flatpaper-tabs__panels"><section role="tabpanel" id="tabs-20-panel-0" aria-labelledby="tabs-20-tab-0" class="flatpaper-tabs__panel is-active" data-index="0"><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;alias dc=&quot;docker compose&quot;&#x27;</span> &gt;&gt; ~/.bashrc </span><br><span class="line"><span class="built_in">source</span> ~/.bashrc </span><br></pre></td></tr></table></figure></section><section role="tabpanel" id="tabs-20-panel-1" aria-labelledby="tabs-20-tab-1" class="flatpaper-tabs__panel" data-index="1" hidden><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;alias dc=&quot;docker compose&quot;&#x27;</span> &gt;&gt; ~/.zshrc </span><br><span class="line"><span class="built_in">source</span> ~/.zshrc </span><br></pre></td></tr></table></figure></section></div></div><p>效果:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">root@debian:~# dc</span><br><span class="line">-bash: dc: <span class="built_in">command</span> not found</span><br><span class="line"></span><br><span class="line">root@debian:~# dc version</span><br><span class="line">Docker Compose version v5.2.0</span><br></pre></td></tr></table></figure><p>之后，当我们创建了 <code>docker-compose.yml</code> 文件后，启动或是更新服务只需要执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">dc pull</span><br><span class="line">dc up -d </span><br></pre></td></tr></table></figure><p>现在前往 GitHub 或是 <a href="https://hub.docker.com/">Docker Hub</a> 寻找有趣的项目吧！</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;现在越来越多的应用可以使用 &lt;strong&gt;Docker&lt;/strong&gt; 一键部署，本文将介绍如何在最新的 Debian 13 (Trixie) 中安装 &lt;strong&gt;Docker&lt;/strong&gt; 与 &lt;strong&gt;Docker Compose&lt;/strong&gt;。&lt;</summary>
      
    
    
    
    <category term="教程" scheme="https://ooo.run/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="Docker" scheme="https://ooo.run/tags/Docker/"/>
    
    <category term="Docker Compose" scheme="https://ooo.run/tags/Docker-Compose/"/>
    
    <category term="Debian" scheme="https://ooo.run/tags/Debian/"/>
    
    <category term="Linux" scheme="https://ooo.run/tags/Linux/"/>
    
  </entry>
  
</feed>
