npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@speclip/pi-talking-head

v0.3.1

Published

Pause-aware talking-head editing and B-roll planning for Pi, exported as generic pi-media EDLs

Readme

@speclip/pi-talking-head

给 Pi 用的口播剪辑决策包。它读取 pi-speech 风格的词级时间戳,结合整句上下文识别词间停顿、语气词和相邻重复,生成保守的 A-roll 剪辑方案,并在查找素材前把 B-roll 候选压缩成“最小充分画面”。

它不直接调用 FFmpeg。最终输出是 pi-media 的通用 timeline EDL,由 pi-media 负责素材校验、不可变 revision、渲染和验收。

为什么这样拆

  • pi-talking-head:决定哪里该剪、气口留多少、B-roll 为什么出现。
  • pi-media:执行任意来源的通用 EDL,保证路径安全、素材哈希、渲染和凭证。
  • pi-speech:提供词级 beginMs / endMs 转录。

表达整理由 Agent 判断,插件校验取舍记录和时间线的一致性;候选匹配和技术验收都不能替代语义判断或真实试听。

环境要求

  • Node.js 22.19+
  • Pi 0.84.1–0.85.x
  • @speclip/pi-media 0.4.0+(本版配套渲染器:保持主素材帧率,输出实际帧/样本时间映射与渲染凭证;需单独升级)
  • 一份带词级时间戳的 JSON 转录;格式兼容 @speclip/pi-speech

安装和验证

0.3.1:减少工具交接中的返工

  • BGM mix 按内容比较,不再因对象字段顺序不同误报回执不匹配;原有哈希算法保持不变。
  • A-roll 未变时,talking_head_apply 可传 inheritBroll: true,省略 broll/continuityPlanReceipt,添加音乐无需重新匹配和选择 B-roll。原样提交旧完整 placements 也能复用;素材、清单、视觉证据、回执和当前连续性策略仍重新校验。
  • talking_head_broll_match/select 支持 needId + continuityPlanReceipt,不必重抄需求或补写 mask-cut 派生字段。完整 need 仍支持,两者不能同时传。
  • 选窗失败返回错误代码、候选起点、已有证据帧、尾部阈值和下一步,减少查源码与猜参数。

新调用示例与恢复方式见 工具交接说明。本版保留正式 0.3.0 的渲染器要求、默认相对响度模式及项目/回执格式;不迁移另行维护的 Speclip 私有 quality 版本。

npm install
npm run check
pi install ./

工作流

1. 创建口播项目

talking_head_create {
  projectId: "launch-video",
  sourcePath: "raw/launch.mp4",
  transcriptPath: "transcripts/launch.json",
  sourceDurationMs: 93224, // 来自 media_probe
  cutThresholdMs: 500,
  headPaddingMs: 50,
  tailPaddingMs: 80
}

初剪建议只收紧至少 500ms、且没有语气词或表达边界保护信号的词间停顿。每个保留片段前留 50ms、后留 80ms,避免切掉辅音、尾音和自然气口。停顿还会分为:

  • safe:至少 400ms,通常可以切。
  • review:150–399ms,必须结合语义和画面判断。
  • unsafe:少于 150ms,默认不切。

若停顿紧邻候选语气词,或位于问号、感叹号等表达边界之后,即使超过阈值也会降级为 review,不会进入默认自动剪辑。ASR 分段边界也先进入复核。工具返回 revision 1、内容与停顿摘要、editorialStatus: draft 和 previewMediaOperation;初始方案不是完成版。50/80ms 是初始参考,最终每个接点按原音和表达节奏决定。

2. 分页检查整句和编辑候选

talking_head_get {
  projectId: "launch-video",
  sentenceOffset: 0,
  sentenceLimit: 20,
  pauseOffset: 0,
  pauseLimit: 50,
  fillerOffset: 0,
  fillerLimit: 50,
  repetitionOffset: 0,
  repetitionLimit: 50,
  contentOffset: 0,
  contentLimit: 50,
  includeWords: true,
  includeTranscriptText: true
}

工具会分页返回整句上下文、停顿、语气词和相邻重复;需要判断整段结构时可显式取得完整转录文本。啊、额、嗯 等只会成为 review 候选,Agent 必须判断它是口癖、语义成分还是刻意表达,不能自动删除。文本标点只能提供低置信度且可以并存的表达线索,不等同于声学情绪识别。

只有调用这个工具时才会把这些证据放进当前会话上下文;安装 package 不会把整份转录常驻注入上下文。

3. 先整理完整表达并提交编辑计划

“气口剪辑”默认包括全片检查、重录取舍、无效起句和重复讲述清理、保留独有信息,再处理停顿。只有用户明确要求仅处理间隔时,才使用 scope: pauses-only 并在 scopeReason 中记录原要求。

新增的 contentCandidates 提示跨句重复短语、近邻相似段落和重新起句,全部为低置信度 review。它们不是完整问题清单。diagnostics 会报告首尾相接的时间戳比例和候选截断:大量零间隔不能证明原音没有句内停顿。semanticBoundary: unknown 表示 ASR 分段没有可靠语义边界证据。

Agent 阅读完整转录、检查原素材之后,先确定输出 A-roll 顺序,再调用:

talking_head_editorial_plan {
  projectId: "launch-video",
  expectedRevision: 1,
  aroll: plannedAroll,
  plan: {
    scope: "full",
    reviewedSentenceIndexes: allReviewedSentenceIndexes,
    sourceReview: { method: "text-and-visual", notes: "已比较完整表达;尚未试听成片" },
    decisions: reviewedDecisions,
    uniqueInformation: retainedUniqueInformation,
    segmentReasons: plannedSegmentReasons,
    unresolvedIssues: []
  }
}
  • decisions 每项包含 id、kind(retake/false-start/filler/pause/other)、action(edit/keep/review)、candidateIds、ranges 和 reason。ranges 每项为零起始且首尾包含的 startWordIndex/endWordIndex,以及 disposition: keep/remove/review。自行发现的问题可不引用候选;纯停顿候选可以没有词区间。
  • 全部候选必须有决定;每个删掉的词必须有对应 disposition;声明保留或删除的词必须与 A-roll 一致。程序检查记录和时间线的一致性,不能验证文字理由是否真实反映听感。
  • uniqueInformation 每项包含 id/startWordIndex/endWordIndex/reason,所指词必须在输出中。支持把前一遍独有内容插入后一遍完整表达。空列表表示比较后确认没有独有信息。
  • segmentReasons 每项为 segmentId/reason,必须覆盖全部输出片段。reviewedSentenceIndexes 必须覆盖全部 ASR 分段。
  • 保存返回的 editorialPlanReceipt,应用时原样提交。它绑定项目、revision、源文件、转录、A-roll 顺序和编辑计划。A-roll 改动必须重新规划;仅 B-roll/BGM 改动可以沿用当前 revision 已保存的内容审阅。

| 状态 | 输出与含义 | | --- | --- | | draft | 没有编辑计划,仅返回 previewMediaOperation | | needs-review | 有未决问题或 review 决定,仅返回预览 | | pauses-only-reviewed | 用户明确限制的间隔处理,仅返回预览,不代表完整表达整理 | | content-reviewed | 完整表达计划通过一致性校验,返回 mediaOperation;listeningStatus 仍为 pending |

允许随时渲染明确标注的草稿小样,但不能把草稿或技术检查成功称为完整剪辑验收。旧快照仍可读取;没有编辑计划的旧版本按草稿对待,旧分析会从未变更的转录重新计算且不改写旧快照。依赖 create/get/apply 固定返回 mediaOperation 的调用方需要迁移到上述状态分支。

4. 先规划 B-roll 视觉连续性

在查找素材前,把最终 A-roll 和所有 B-roll 需求交给连续性规划工具:

talking_head_broll_plan {
  projectId: "launch-video",
  aroll: [
    { id: "hook", sourceStartMs: 50, sourceEndMs: 4120 },
    { id: "answer", sourceStartMs: 4860, sourceEndMs: 13200 }
  ],
  needs: [
    {
      id: "product-a",
      outputStartMs: 1000,
      outputEndMs: 3000,
      speechText: "接下来第一步,我们先打开设置页面",
      visualCueText: "打开设置页面",
      necessity: "essential",
      purpose: "demonstrate",
      searchTerms: ["设置", "打开"],
      reason: "展示第一步"
    },
    {
      id: "product-b",
      outputStartMs: 3300,
      outputEndMs: 5200,
      speechText: "然后第二步,在列表里选择设备",
      visualCueText: "选择设备",
      necessity: "supporting",
      purpose: "demonstrate",
      searchTerms: ["设备", "选择"],
      reason: "展示第二步"
    }
  ],
  cutCoverBeforeMs: 250,
  cutCoverAfterMs: 500
}

第一次分析时,开场、结论、个人观点、情绪和转折默认留在 A-roll。speechText 保存完整句子上下文,visualCueText 只写真正需要被看见的关键词;输出区间也只覆盖这个最短有效画面。只有“不看画面就难以理解或验证”的需求才能标为 essential,其余使用 supporting。

规划结果同时返回 plan.selection、plan.coverage 和 continuityPlanReceipt。规划器会先删除没有信息增量的 supporting 转场,并确保观看连续组不超过 8000ms、结尾至少保留 3000ms A-roll。两个 B-roll 之间不足 3000ms 的 A-roll 会按同一个观看连续组计算,但只有不超过 500ms 的闪屏才会被直接衔接覆盖。essential 违反连续性规则时会要求 Agent 缩短、移动或拆分画面,而不是直接查素材。plan.selection.omittedNeeds 只用于解释淘汰原因,后续严禁匹配;素材查找只能使用 plan.needs。v4 凭证会绑定最终入选区间和 A-roll 可见性策略,talking_head_apply 会重新核对。旧版快照仍可读取;v1-v3 凭证若包含 B-roll,应用前必须重新规划为 v4,不能绕过新规则。

规划结果处理两类问题:

  • 首轮稀疏化:先按 transition → establish → explain → demonstrate → evidence 的顺序淘汰 supporting 候选;mask-cut 和明确标注的 essential 不会被静默删除。完整语义只是最大上下文边界,不代表要用 B-roll 覆盖整句话。
  • B-roll 闪屏:只有入选的两个 B-roll 之间只露出不超过 500ms 的 A-roll 时,plan.needs 才会把前一个需求延长到后一个需求的起点。被淘汰的候选不会参与衔接。
  • 气口剪辑跳转:A-roll 相邻片段的源时间不连续时会生成 jumpCuts。未覆盖项标为 review,只表示 Agent 需要查看实际画面。只有确认跳点视觉上突兀时才能添加 purpose: "mask-cut",保存工作区内的审阅图片或视频,并提交 visualReview: { decision: "mask-with-broll", reviewedJumpCutOutputMs, artifactPath };规划器会计算文件哈希并绑定到 v4 凭证,应用时再次校验。否则继续保留 A-roll。
  • 时长与覆盖控制:不能把 B-roll 固定为三秒,也不能把完整句子直接变成覆盖区间。总覆盖量由 Agent 根据主题和画面信息增量判断,不设固定比例目标。硬约束是观看连续组不超过 8000ms、结尾至少保留 3000ms A-roll。这里的 3000ms 只用于判断 A-roll 是否形成有效人物窗口,不规定 B-roll 本身的固定时长。
  • 避免重复:同一素材 SHA-256 在一个时间线中只能使用一次,即使选择的是不同源时间段。每次选段还必须按实际画面填写 visualIdentity 的主体、动作、景别和角度;不同文件只要画面身份相同也会被拒绝。选择凭证会把该身份与素材、manifest 和时间戳一起哈希绑定。

是否加入 B-roll 只看当前画面能否增加理解或证据;不要为了达到某个覆盖比例而添加素材。

5. 文件名优先筛选 B-roll

只使用 plan.needs 中入选的最短有效区间扫描素材目录,绝不为 plan.selection.omittedNeeds 查找素材:

talking_head_broll_match {
  projectId: "launch-video",
  assetDirectory: "assets/broll",
  recursive: true,
  maxFiles: 1000,
  maxEntries: 20000,
  maxDepth: 12,
  maxCandidates: 5,
  candidateOffset: 0,
  needId: plan.needs[0].id,
  continuityPlanReceipt
}

每一个 plan.needs 都必须单独执行匹配。保存返回的 matchReceipt,后续只能从该次返回的候选页中选择素材。

该工具只读取目录项和文件名,不解码、不探测、不哈希视频。它最多返回限定数量的候选,并给出三种结果:

  • filename-direct:一个文件名唯一且明确命中,只检查这一条素材。
  • filename-shortlist:多个名字可能匹配,只检查返回的 shortlist。
  • visual-fallback:文件名没有有效语义,再对限定 shortlist 使用低成本联络表。

扫描同时受 maxFiles、maxEntries 和 maxDepth 约束并支持取消。完整扫描时,若当前 shortlist 都不合格,可使用非空的 nextCandidateOffset 读取下一批。结果一旦截断,工具不会声称唯一命中,也不会返回可复用的分页游标;此时应缩小素材目录后重扫,避免文件系统枚举顺序造成候选漂移。

确定素材后才调用 media_probe 和 media_contact_sheet。长素材先低密度定位大致范围,再只对候选范围高密度抽帧;必须使用 contact_sheet_manifest.json 的真实时间戳,不能从 PNG 猜时间。找到连续可用且覆盖完整成片窗口的片段后,验证并生成 placement:

talking_head_broll_select {
  projectId: "launch-video",
  needId: plan.needs[0].id,
  continuityPlanReceipt,
  matchReceipt,
  assetPath: "assets/broll/mouse-demo.mp4",
  manifestPath: "analysis/mouse-demo/contact_sheet_manifest.json",
  selectedStartMs: 12400,
  evidenceTimestampsMs: [12400, 13900, 15400],
  fit: "cover",
  visualIdentity: {
    subject: "鼠标",
    action: "手部移动鼠标",
    shotScale: "close-up",
    angle: "top-down"
  }
}

match 和 select 都会先验证 v4 continuityPlanReceipt,被首轮淘汰或被手动改回完整句子范围的 need 会在读取素材前直接拒绝。select 不接受未出现在对应 matchReceipt 候选中的素材;apply 会再按计划中的同一 need 完整复核项目、revision、计划、need 和候选素材。随后工具验证素材 SHA-256、manifest 分析范围、起始帧和覆盖片段尾部的证据时间戳,并把匹配来源与 visualIdentity 一起写入选择哈希。placement 内含选择凭证;不要手写、修改或删除其中字段。0.1.8 生成的旧 placement 不含 matchReceipt,应用前需要重新匹配并选择。

6. 用波形图和标准响度证据添加 BGM

先让 pi-media.media_audio_analyze 分析两份音频证据:原视频传入与最终 A-roll 完全一致的有序 ranges,BGM 则分析完整文件。工具会生成带 HH:MM:SS.mmm 绝对时间戳、短时 LUFS 曲线的波形 PNG,以及 EBU R128 / ITU-R BS.1770 manifest。

talking_head_bgm_plan {
  projectId: "launch-video",
  aroll,
  voiceAnalysisPath: "analysis/voice/audio_analysis_manifest.json",
  musicAnalysisPath: "analysis/bgm/audio_analysis_manifest.json",
  targetMusicBelowDialogueLu: 12
}

规划器根据真实时长返回 trim 或 loop,并绑定目标 LU 差值,不接受音量百分比。默认使用 12 LU:这会在 sidechain 再次压低人声下方的 BGM 之前保留足够可听度。只有用户明确要求更轻的氛围底,或音乐本身特别密集、明亮时,才提高到 14–18 LU;不要把 18 LU 当成通用的“更安全”默认值。Agent 打开完整 BGM 波形 PNG 得到起止时间后,必须再调用一次 media_audio_analyze,只分析这个最终选中窗口;不能拿整首曲子的平均 LUFS 代替片段响度。随后提交视觉判断和选中窗口的 manifest:

talking_head_bgm_select {
  projectId: "launch-video",
  aroll,
  planReceipt,
  selectedMusicAnalysisPath: "analysis/bgm-window/audio_analysis_manifest.json",
  selectedStartMs: 12_000,
  selectedEndMs: 42_000,
  evidenceTimestampsMs: [12_000, 42_000],
  fadeInMs: 500,
  fadeOutMs: 1500
}

长 BGM 必须选择一个与成片等长的连续窗口;短 BGM 选择至少 500ms 的循环窗口。完整 bgm 返回值交给 talking_head_apply。渲染时 pi-media 会在循环接缝做短交叉淡化、在口播出现时 sidechain ducking,并在结尾淡出。波形只能展示振幅和结构,不能单独证明音乐情绪,仍需结合用户要求和素材信息判断。

7. 写入人工确认后的时间线

talking_head_apply {
  projectId: "launch-video",
  expectedRevision: 1,
  aroll: [
    { id: "hook", sourceStartMs: 50, sourceEndMs: 4120 },
    { id: "answer", sourceStartMs: 4860, sourceEndMs: 13200 }
  ],
  broll: [selectionA.placement, selectionB.placement],
  bgm: selectedBgm.bgm,
  continuityPlanReceipt,
  editorialPlanReceipt
}

B-roll 使用成片时间轴定位,assetStartMs 来自联络表 manifest,并永远保留主口播音轨。talking_head_apply 会重新校验连续性规划凭证、选段哈希、素材与 manifest 的 SHA-256;规划区间、画面身份或时间点被手改、素材被替换都会拒绝写入新修订。同一素材 SHA-256 或跨文件重复画面身份也会被拒绝。若两个 B-roll 之间仍存在不超过 500ms 的 A-roll、观看连续组超过 8000ms,或结尾 A-roll 少于 3000ms,也会要求重新规划。当前不支持 B-roll 相互重叠,因为未定义 z-order。BGM 的素材、两份响度 manifest、波形图、起止时间、循环策略和混音参数也会被重新校验。

8. 交给 pi-media 渲染

完整表达计划通过后,用同一个源文件创建 pi-media 项目,再把上一步的 mediaOperation 原样传入;草稿只能使用明确标注的 previewMediaOperation:

project_create { projectId: "launch-video-render", sourcePath: "raw/launch.mp4" }

edit_apply {
  projectId: "launch-video-render",
  expectedRevision: 1,
  operations: [mediaOperation]
}

render {
  projectId: "launch-video-render",
  revision: 2,
  outputPath: "out/launch-final.mp4"
}

review { path: "out/launch-final.mp4" }

新渲染器默认采用第一段主素材帧率,保存累计视频帧/音频样本对齐后的 timelineTiming 与正式渲染回执;字幕重映射应使用实际输出映射。review.accepted 是技术检查结果,不代表表达、接点或听感已通过。无法直接试听时必须列出成片接点并标为待听感验收。

工具

| 工具 | 作用 | | --- | --- | | talking_head_create | 从视频和词级转录建立 revision 1,用探测时长保护源文件边界并生成默认 EDL | | talking_head_get | 读取指定 revision,分页返回整句与编辑候选,可选导出 pi-media EDL | | talking_head_editorial_plan | 校验全片内容取舍、独有信息和输出区间,生成绑定凭证 | | talking_head_broll_plan | 按主题规划 B-roll,保护有效 A-roll 窗口并报告覆盖率与待审阅跳点 | | talking_head_broll_match | 只用文件名和目录名匹配本地 B-roll,返回受限 shortlist 与匹配凭证 | | talking_head_broll_select | 验证匹配凭证和 pi-media 联络表 manifest 后生成 placement | | talking_head_bgm_plan | 比较最终 A-roll 与完整 BGM 的 EBU R128 manifest,决定截取或循环 | | talking_head_bgm_select | 验证波形图起止时间、淡入淡出和 BGM 选择凭证 | | talking_head_apply | 写入新的不可变口播 revision,并返回 pi-media EDL |

当前边界

当前版本不负责语音转录、声学情绪识别、联网素材搜索、字幕、画面理解、音频解码或渲染。它提供整句文本、编辑计划及其凭证、时间轴、B-roll 选择凭证和 BGM 编排凭证;波形、EBU R128 检测、循环、ducking、混音和最终渲染仍由 pi-media 完成。