内容创作 · iart-ai/javascript-animation-skills

soundtrack

This skill should be used when the user asks to "add music to the animation", "make the music in code", "synthesize a soundtrack", "compose background music that fits the cuts", "sync the music to the video", "check if the audio lines up with the picture", or "the music is too sudden / startling". Covers a code-synthesized score that lives inside the animation page (Web Audio API, rendered offline to WAV), AI-generated or user-supplied music, and an automatic check that cuts land on the beat without a startling jump in loudness.

L4 高权限 · 分级授权与审计V1 已固定执行命令联网读写文件Dual-pass Audit
Author iart-aiGitHub iart-ai/javascript-animation-skills ↗Stars 9License MIT(仓库根 LICENSE 为 MIT License / Copyright (c) 2026 iart.ai;.claude-plugin/plugin.json 亦声明 "license": "MIT")Commit deb46e0eff
管控等级描述 skill 的能力与建议配套的管控措施,不代表质量或安全认证,也不表示可用或不可用。是否使用由用户和管理者决定。不同 agent 宿主对权限的约束各不相同,请勿假定宿主一定会提供安全兜底。第三方 skill 版权归原作者,使用风险由使用者自行承担。

1实现原理 · 为什么它能做到

默认路线是「在页面里用代码合成」:把模板贴进动画页的 <script>,配乐与画面共享同一份 BPM/SECTIONS/EVENTS,因此每个动作的声音落在同一帧上——无 key、无音频文件。

skills/soundtrack/SKILL.md
Paste `templates/score.js` into the animation page's `<script>`, before the live-preview block at the bottom (the starter marks the spot), and set:
这里在做什么:把配乐变成页面的一部分(Web Audio),由 javascript-animation 的 render.mjs 离线渲染成 WAV 再 mux,所以既不需要素材也不需要密钥。

音乐跟随画面的机制是速度图而非手动对表:每个场景分配整数小节(约 70–110 bpm),于是每个剪切天然落在强拍上。

skills/soundtrack/SKILL.md
- **Tempo map.** Each scene gets a whole number of bars (tempo flexes per scene, roughly 70-110 bpm), so every cut lands on a downbeat.
这里在做什么:score.js 按 cues 切段、每段取整小节,并让和声走向收束到主音,用「小节整数化」把对齐问题解掉。

剪切用和声而非音量标记(场景走向属和弦、剪切到达主和弦),并给出实测数值说明为什么不能加音量:+7~10 dB 的跳变会被用户指为惊吓,+3~5 dB 配和声变化才读作干净剪辑。

skills/soundtrack/SKILL.md
- **Mark cuts with harmony, not volume.** Each scene walks home to the dominant (G) and the cut arrives on the tonic (C). A loud accent on a cut (bass + bright chime at once) reads as a jump scare: users flagged a +7 to +10 dB jump as startling; +3 to +5 dB with a chord change reads as a clean edit.
这里在做什么:把混音判断写成可复现的经验值——本 skill 最有价值的部分,且每条都在代码里有对应分支。

自动校验把「对齐」与「不惊吓」变成两个可失败判据:逐事件报告到最近强起音的偏移与进入时的响度跳变,偏移超 ±100 ms 判 OFF-BEAT、跳变超 +6 dB 判 STARTLE;并跳过开头一秒与结尾淡出。

skills/soundtrack/SKILL.md
It fails on OFF-BEAT (more than ±100 ms, ~3 frames) or STARTLE (more than +6 dB versus the second before). The opening second and the final fade are skipped (no "before" to compare against; a fade-out is not a cut).
这里在做什么:sync-check.mjs 自建分析(64×64 灰度帧找切点与空白基线、10ms 能量上升找起音、±1s 邻域判「强」起音),并特殊处理「切入静音也算落地」与「休息段后按休息前电平比较」。

使用非自制音乐时方向反转:画面跟随音乐——渲染、混音、跑检查,再按报告偏移移动页面 SCENES 的场景边界并重渲;因为场景函数只接收本地时间,移动边界不动场景代码,所以这个循环很便宜。

skills/soundtrack/SKILL.md
With music you don't control, reverse the direction: **the picture follows the music.**
这里在做什么:把「音乐不可改」约束转成「画面对齐成本很低」的工程结论,并给出迭代回路。

能力边界被主动声明:代码合成擅长音乐盒、类钢琴拨弦、pad、铃、轻打击,做不了写实人声/管弦/类型化制作——需要时改用 AI 音乐或真曲。

skills/soundtrack/SKILL.md
Synthesized in code: music box, piano-like plucks, pads, bells, soft percussion are fine. Realistic voices, orchestras and genre production are not; use AI music or a real track for those.
这里在做什么:提前划边界,避免用合成器硬凑不擅长的曲风;也解释了为什么另给一条 AI 音乐支路。

AI 音乐支路需要用户提供的 API key,由 agent 直接 curl 外部生成服务(OpenRouter 上的 Lyria),把音乐描述发出去——这是本 skill 唯一读凭证并外发素材的分支,且被定位为「只在被要求时」。

skills/soundtrack/references/ai-music.md
Use when the user wants something richer than a synthesized score. Needs an API key.
这里在做什么:ai-music.md 给出 stream:true 的 curl(Authorization: Bearer $OPENROUTER_API_KEY)与 base64 音频合并脚本,再给 ffmpeg 混音命令;默认路径不涉及它。

2核心能力

01代码合成配乐(默认):两套模板——节拍网格型 groove(段落/鼓/贝斯/pad/主音/可选 break + 约 20 个合成音效)与音乐盒型 score(速度图 + 每次剪切可选轻铃)
02四套音色 kit(electro/acoustic/keys/percussion)与多种和声情绪(bright/wistful/dreamy/tense/folk/blues 或自定义和弦 + key 移调),分层可自选(可以完全不要鼓)
03离线渲染与混流:由 javascript-animation 的 render.mjs 用 OfflineAudioContext 渲染成 WAV 并 mux 进 MP4(确定性、快于实时)
04声画同步检查(sync-check.mjs):可从 CUES 文件或从画面自动检测切点,报告每个事件的偏移与响度跳变,OFF-BEAT/STARTLE 时退出非零
05混音/编排纪律:一小节最多进一两层、允许用 break(整段静音)当最强拍、不给剪切拍额外重音、场景内硬切也进 CUES
06非自制音乐接入:AI 生成(Lyria via OpenRouter,stream 模式收 base64 音频)或用户自带曲目,并用 ffmpeg 裁剪/淡入淡出后再用 sync-check 反推画面对齐
07无音轨/无 SCORE 情形显式报告:视频没有音频流会被直接指出并退出非零,而不是静默通过

3外部依赖

KindDependency / Endpoint
cliffmpeg / ffprobe(分析视频与音频:抽灰度帧、抽 PCM;AI 支路里还用于混音)
apiOpenRouter 上的 Lyria(可选 AI 音乐生成,stream:true 收 base64 音频)
api该端点的凭证:从环境变量读取并放入 Authorization 头(仅 AI 音乐支路)
package兄弟 skill javascript-animation 的 render.mjs(离线渲染 SCORE 为 WAV 并 mux 进 MP4)
networkWeb Audio API(浏览器内置,用于合成与离线渲染;非外部服务)

4管控建议与判定依据

建议配套管控措施
面向 Agent
分级或逐次授权,建议在沙箱运行
面向管理者
审批流程、可回滚、全程审计
判定依据(文件路径与关键语句摘要)
  • scripts/: 执行本地脚本或命令: node scripts/sync-check.mjs piece.mp4 [--cues-file piece.cues.json] [--tol
  • 网络端点: 声明外部网络访问: https://openrouter.ai/api/v1/chat/completions —— 仅 AI 音乐支路(用户明确要求时),Authori
  • 本地工作目录: 文件读写与工件输出: 素材与中间产物:bgm.mp3(curl 流式音频落盘)、piece_music.mp4(ffmpeg 混音输出)
审计说明: 。判级对象=skill 自身目录,触发橙档的是其目录内的 references/ai-music.md:① 读凭证/环境变量——命令直接从环境取 `$OPENROUTER_API_KEY` 并放进 `Authorization: Bearer` 头部(与范式中 home-assistant 读 $HASS_TOKEN 同类);② 把用户素材送外部生成/服务后端——POST 到 https://openrouter.ai/api/v1/chat/completions(modalities:[audio]、stream:true),把音乐描述交给第三方模型生成音频,返回的 base64 直接落盘 bgm.mp3 再混入成片,消耗账号额度且生成物入库。触发条件明确:仅当用户要求比合成曲更丰富的音乐时才走这条支路(SKILL.md 把它列在 'Other sources (only when asked)';默认路径是页面内代码合成,零 key 零端点)。除该支路外其余行为均为本地:模板是 Web Audio 合成代码、sync-check.mjs 只调 ffprobe/ffmpeg 读本地文件并打印报告。无沙箱降级、无关 TLS、无绕过自动化侦测、无任意代码执行面,故非红档;默认路径本身也不含黄档以上的网络行为。

5第二遍独立确认

  • [ok] $OPENROUTER_API_KEY 是否真的被读取并外发(橙档判定关键) — references/ai-music.md 原文给出 `curl -s -N https://openrouter.ai/api/v1/chat/completions -H "Authorization: Bearer $OPENROUTER_API_KEY" …`,且开头写明 'Needs an API key.';端点与凭证同处一条可复制命令,调用点真实存在。
  • [ok] 该支路是否真的是「可选、非默认」(避免过度判级) — SKILL.md 正文写 'Don't ask the user to choose a music source up front.',并把 AI 音乐放在 '## Other sources (only when asked)' 段下;默认段标题为 '## Default: synthesize it in the page (no key, no files)'。触发条件为用户显式要求。
  • [ok] sync-check 的判据是否与文档一致(能力声明可信度) — 代码内 TOL = Number(opt('--tol', 100)) / 1000 对应 ±100ms;`const jump = 20 * Math.log10(rms(v.t, v.t + .3) / ref), startle = jump > 6;` 对应 +6 dB;无音轨时 console.error 并 process.exit(1);与 SKILL.md 逐条吻合,无夸大。
  • [ok] 模板是否真的与画面共享数据(而非各自维护时间) — groove.js 头注释给出 schema(sections/events/kit/harmony/key)并写 'The picture reads the same BPM / SECTIONS / EVENTS, so sound and image can't drift apart.';score.js 同样由 cues(即 window.CUES)切段并做小节取整。声明与实现一致。
  • [ok] 是否有比橙更高的行为(红档特征) — 全仓扫描 `sandbox|automationcontrolled|no-verify|stealth|bypass|ignoreHTTPSErrors|dangerously` 零命中;curl 未使用 -k/--insecure,无绕防护动作,无任意代码执行面(模板是页面内 Web Audio 代码)。
  • [ok] 确定性声明(每次渲染一致)是否可在模板代码内定位 — score.js 的混响脉冲用固定种子 LCG 生成并注释 'deterministic noise tail (seeded, so every render is identical)';groove.js 同样用 `let s = 99 + c` 起手的 LCG 与固定种子噪声缓冲。声明属实。

6结论

  • 把「配乐对不对」转成可失败的客观判据(±100 ms 对齐、+6 dB 惊吓阈值),并有真实数值来源
  • 声画同源是结构性的:画面与配乐读同一份 BPM/SECTIONS/EVENTS,剪切天然落在强拍
  • 默认路线零 key 零素材且完全确定性(种子化混响/噪声),可随页面一起分发
  • 混音经验以数值教训形式沉淀(分层入场 +11 dB vs +3.5 dB、切拍不加额外重音、允许 break)
  • 诚实声明能力边界,并把不擅长的曲风导向 AI 音乐或真曲
  • 非自制音乐时给出「画面对齐音乐」的低成本迭代回路
  • 适合: 适合给代码生成的短片配乐(默认零 key、零素材、确定性可复现)、需要「剪切落在拍上且不惊吓」的成片验收、以及音乐盒/pad/拨弦/轻打击气质的作品;也适合把「AI 音乐或用户自带曲目」接入同一套同步检查与画面对齐回路(需自备 OpenRouter key)。输出是页面内配乐代码 + 由 render.mjs 渲染的 WAV/MP4。
    不适合: 不适合:① 需要写实人声、管弦乐、类型化制作水准的配乐(文档自己划了边界);② 不接受任何凭证读取与素材出网的部署(应完全避开 ai-music.md 支路);③ 没有 ffmpeg/ffprobe 的环境(检查与 mux 都依赖它们);④ 无 window.CUES/无 SCORE 的片子(脚本会直接报「没有音频流,无可检查」而非给出结论);⑤ 期望脚本替代听感判断的流程(阈值只是下限)。
    Install Agent-Ready
    ① Verified Mirror 2026-09-28
    Option A · Direct DownloadDownload soundtrack.tar.gz
    sha256: 7cd2fd4b7c5af0a2…
    Option B · Copy Guide for Agent
    install.json
    agent 读 JSON 指南后会自动从本站下载安装,无需更多说明。
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit deb46e0eff.