earshot

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

earshot: ears for an agent

earshot:Agent 的耳朵

You cannot hear. Never say how audio sounds, or that a sound "fits", without an earshot reading behind it, and quote the number when you report ("strong match, z +3.9; p_real 0.96; -14.2 LUFS"). earshot runs locally on CPU (audio never leaves the machine, except with the optional
llm
command) and caches every embedding and result on disk. Cost: each CLI call is a new process that loads the models first (~20-40 s on a busy laptop, even for a cached file); inside the MCP server or one Python script the models load once and repeat calls take seconds. For more than a handful of calls, use MCP or a short script (
from earshot import api; api.find(...); api.realness(...)
).
你无法听见。若没有 earshot 读数作为依据,绝不能描述音频听起来如何,也不能说某个声音“契合”;报告时务必引用具体数值(“匹配很强,z +3.9;p_real 0.96;-14.2 LUFS”)。earshot 在本地 CPU 上运行(音频不会离开本机,除非使用可选的
llm
command),并会将每个 embedding 和结果缓存在磁盘上。成本:每次 CLI 调用都会启动一个新进程,首先加载模型(在繁忙的笔记本上,即使文件已有缓存,也约需 20–40 秒);在 MCP server 内或同一个 Python script 中,模型只加载一次,重复调用只需数秒。若调用超过少数几次,请使用 MCP 或一个简短 script(
from earshot import api; api.find(...); api.realness(...)
)。

Setup (once)

一次性设置

pip install -e "/path/to/earshot[mcp,llm]"   # or the repo venv: /path/to/earshot/.venv/bin/python -m earshot ...
earshot doctor                           # packages, ffmpeg, models (pinned revision, cache state); --load times them
Two ways in, same functions:
  • CLI:
    earshot <command> ... [--json] [--out result.json]
    . Text output starts with a plain summary; times are m:ss.ss in text and seconds in JSON.
  • MCP (models stay loaded between calls):
    claude mcp add earshot --scope user -e EARSHOT_THREADS=3 -- /path/to/earshot/.venv/bin/python -m earshot mcp
    , or in any client's
    .mcp.json
    :
    {"mcpServers": {"earshot": {"command": "/path/to/earshot/.venv/bin/python", "args": ["-m", "earshot", "mcp"], "env": {"EARSHOT_THREADS": "3", "GEMINI_API_KEY": "${GEMINI_API_KEY:-}"}}}}
    (the key line only for the optional llm tool; Claude Code fills it from the user's environment, other clients may need the key set in the environment that launches them: never write a literal key into a project file). Tools: measure, describe, match, rank, find, compare, ab, realness, timeline, sheet, critique, doctor, llm_critique; the sound bank (no models): sfx_list, sfx_render, kit_render (Loop 5). Pass absolute paths;
    full=true
    returns all JSON. The server answers within a few seconds, longer on a cold or busy machine; if Claude Code shows no earshot tools, start it with
    MCP_TIMEOUT=60000
    (PowerShell:
    $env:MCP_TIMEOUT=60000; claude
    ).
    earshot mcp --warm
    preloads the models at startup. If the machine is shared, set
    EARSHOT_THREADS=2-3
    (or
    --threads 2
    on any command). The first model call of a process loads CLAP + AST (~20-60 s); later calls in the same process are fast. Any ffmpeg-readable file works, including the audio of an mp4 (a video with no audio track says so). Errors are one line on stderr:
    earshot <command>: error: ...
    , exit 1.
pip install -e "/path/to/earshot[mcp,llm]"   # or the repo venv: /path/to/earshot/.venv/bin/python -m earshot ...
earshot doctor                           # packages, ffmpeg, models (pinned revision, cache state); --load times them
进入方式有两种,使用的函数相同:
  • CLI:
    earshot <command> ... [--json] [--out result.json]
    。文本输出以纯文本摘要开头;文本中的时间格式为 m:ss.ss,JSON 中则为秒。
  • MCP(模型会在调用之间保持加载):
    claude mcp add earshot --scope user -e EARSHOT_THREADS=3 --\ /path/to/earshot/.venv/bin/python -m earshot mcp
    ,或在任何 client 的
    .mcp.json
    中配置:
    {"mcpServers": {"earshot": {"command": "/path/to/earshot/.venv/bin/python", "args": ["-m", "earshot", "mcp"], "env": {"EARSHOT_THREADS": "3", "GEMINI_API_KEY": "${GEMINI_API_KEY:-}"}}}}
    (key 行仅供可选的 llm tool 使用;Claude Code 会从用户 environment 填充该 key,其他 client 可能需要在启动它们的 environment 中设置该 key:绝不要把 literal key 写入 project file)。 工具包括:measure、describe、match、rank、find、compare、ab、realness、timeline、sheet、critique、doctor、llm_critique;sound bank(不加载模型):sfx_list、sfx_render、kit_render(Loop 5)。请传入绝对路径;
    full=true
    会返回完整 JSON。server 通常会在数秒内响应,在冷启动或机器繁忙时可能更慢;如果 Claude Code 未显示 earshot 工具,请使用
    MCP_TIMEOUT=60000
    启动(PowerShell:
    $env:MCP_TIMEOUT=60000; claude
    )。
    earshot mcp --warm
    会在启动时预加载模型。 如果机器由多人共享,请设置
    EARSHOT_THREADS=2-3
    (或在任意 command 上使用
    --threads 2
    )。进程中的首次模型调用会加载 CLAP + AST(约 20–60 秒);同一进程中的后续调用速度很快。任何 ffmpeg 可读取的文件都受支持,包括 mp4 的音频(视频没有音轨时会明确说明)。错误会以单行形式写入 stderr:
    earshot <command>: error: ...
    ,退出码为 1。

Loop 1: choose an asset

循环 1:选择素材

  1. earshot rank "a soft felt mallet hit on a wooden block" downloads/sfx/ --top 5
    - shortlist from a folder.
  2. earshot find winner.ogg "a single clean mallet hit" --top 3
    - the best moments as sample trims (start / end in seconds). Each segment has a kind:
    stroke
    (one onset until it decays) and
    event
    (strokes that belong together, e.g. a key's down + up) start 5 ms before the attack and end after the decay;
    window
    is a stretch whose edges find snapped onto the sound for one-shot queries (a plain stretch, to be crossfaded, for beds).
    head
    /
    tail
    = how loud the first 5 ms / last 10 ms are against the trim's peak (-30 dB or lower = clean); a trim marked 'head cut' or 'tail cut' starts or ends inside a sound: do not use it as is.
    --kind event
    returns onset-based trims only (hits, clicks, steps),
    --kind texture
    plain windows only (beds); the default reads the query.
  3. earshot describe winner.ogg --start 1.12 --end 1.48
    - what it actually sounds like; check the top tags fit what you need and the shape (attack / decay) fits the picture. AudioSet labels are weak on one-shots under ~0.5 s: 'tagger unsure' or a near class (Zipper for a swish, Finger snapping for a click) is neutral; only an outright different class (Speech, Music, Engine, Vehicle) is a red flag.
  4. earshot realness winner.ogg --start 1.12 --end 1.48
    (or a whole folder) - judge the trim you will use: a multi-take file's p_real is a mean over every take and the silence between them. When the user wants real or professionally produced sound, do not use a 'likely code-synthesized' trim, and read the evidence of an 'uncertain' one before using it (write why you kept it). When synthesized sound is the point (procedural music, UI tones, sounds made with earshot forge), realness is information, not a gate. The verdict thresholds depend on length (each summary names them): a sound up to 6 s uses the clip thresholds (lo 0.17 / hi 0.77), a longer file the mean of its 4 s windows with weakly calibrated file thresholds (lo 0.40 / hi 0.77), so compare verdicts, not raw p_real, across files of different lengths. Real recordings and professionally produced music and sound design usually read real, but realness hears how a sound sounds, not where it came from: clean professionally synthesized tones (UI sounds, chimes, synth stabs) also read as code-synthesized. If realness is unavailable (model missing), say plainly that real-vs-synthetic was not checked; describe's AudioSet classes (Sine wave, Beep, Synthesizer) are weaker evidence. Exact digital zeros alone prove nothing (59% of the project's licensed real recordings have some edit or fade padding).
  5. To choose between two candidates:
    earshot ab a.ogg b.ogg --query "a crisp fast air whoosh"
    , with
    --a-start/--a-end/--b-start/--b-end
    for trims from find (A and B may be the same multi-take file). Optional:
    earshot match winner.ogg "a deep thocky key press" --alts "a clicky blue switch" "a typewriter key"
    to test one claim, or
    earshot compare winner.ogg --refs approved/ [--start --end]
    to check it fits the palette.
  1. earshot rank "a soft felt mallet hit on a wooden block" downloads/sfx/ --top 5
    ——从文件夹中生成候选 shortlist。
  2. earshot find winner.ogg "a single clean mallet hit" --top 3
    ——将最佳时刻作为 sample trims 返回(以秒为单位给出 start / end)。每段都有一个 kind:
    stroke
    (从一次 onset 持续到衰减结束)和
    event
    (属于同一事件的多个 stroke,例如按键的按下 + 抬起)从 attack 前 5 ms 开始,并在 decay 结束后结束;对于 one-shot 查询,
    window
    是一段连续音频,其边缘会由 find 吸附到声音上(用于 bed 的普通片段,可以进行 crossfade)。
    head
    /
    tail
    表示前 5 ms / 后 10 ms 的响度相对于 trim 峰值的水平(-30 dB 或更低 = clean);标记为 'head cut' 或 'tail cut' 的 trim 从声音内部开始或结束:不要原样使用。
    --kind event
    仅返回基于 onset 的 trims(hits、clicks、steps),
    --kind texture
    仅返回普通 windows(beds);默认值会根据 query 判断。
  3. earshot describe winner.ogg --start 1.12 --end 1.48
    ——了解它实际听起来是什么样;检查排名靠前的 tags 是否符合需求,以及 shape(attack / decay)是否契合画面。对于短于约 0.5 秒的 one-shots,AudioSet labels 的可靠性较弱:'tagger unsure' 或相近 class(例如 Zipper 对应 swish,Finger snapping 对应 click)属于中性情况;只有明确不同的 class(Speech、Music、Engine、Vehicle)才是 red flag。
  4. earshot realness winner.ogg --start 1.12 --end 1.48
    (也可传入整个文件夹)——判断准备使用的 trim:multi-take 文件的 p_real 是对每个 take 及其间静音取到的平均值。当用户需要真实或专业制作的 sound 时,不要使用标记为 'likely code-synthesized' 的 trim;如果结果为 'uncertain',应先阅读证据再使用,并写明为何予以保留。当合成 sound 本身就是目标时(procedural music、UI tones、使用 earshot forge 制作的声音),realness 只是参考信息,而不是 gate。verdict thresholds 取决于长度(每个 summary 都会标出):6 秒以内的 sound 使用 clip thresholds(lo 0.17 / hi 0.77),更长的文件使用其 4 秒 windows 的平均值,并采用校准较弱的 file thresholds(lo 0.40 / hi 0.77);因此,在比较不同长度的文件时,应比较 verdicts,而不是原始 p_real。真实 recordings 以及专业制作的 music 和 sound design 通常会被判定为 real,但 realness 判断的是 sound 的听感,而不是其来源:干净的专业合成 tones(UI sounds、chimes、synth stabs)也可能被判定为 code-synthesized。如果 realness 不可用(model 缺失),应直白说明未检查 real-vs-synthetic;describe 的 AudioSet classes(Sine wave、Beep、Synthesizer)是较弱的证据。仅有 exact digital zeros 本身不能证明任何事情(该项目 59% 的授权真实 recordings 都带有某种 edit 或 fade padding)。
  5. 要在两个 candidates 之间做选择:
    earshot ab a.ogg b.ogg --query "a crisp fast air whoosh"
    ,并可使用
    --a-start/--a-end/--b-start/--b-end
    指定 find 返回的 trims(A 和 B 可以来自同一个 multi-take 文件)。可选操作:
    earshot match winner.ogg "a deep thocky key press" --alts "a clicky blue switch" "a typewriter key"
    用于验证一个具体说法,或使用
    earshot compare winner.ogg --refs approved/ [--start --end]
    检查它是否符合现有 palette。

Loop 2: review a mix or a film

循环 2:审听 mix 或影片

  1. earshot timeline film.mp4 --cues cues.json
    (or
    soundtrack.wav --video film.mp4
    ) - the listening transcript: events with time, level and tags, sections, loudness curve, picture cuts, sync per cut / cue.
    --detail low
    is fast,
    high
    tags up to 96 events (most important first; the summary says how many were tagged, so an untagged event is not a missing sound). Read the sync stats: offset_ms = sound minus picture (negative = early), and the 'chance' fraction says what random edit points would score; only better-than-chance sync means anything. A cut listed with no hit can still carry a soft whoosh: check it on the sheet before adding a sound.
  2. earshot sheet film.mp4 -o sheet.png --cues cues.json
    (
    --from 10 --to 25
    zooms,
    --detail low
    is faster) - an annotated PNG: frames, sections, labelled events, spectrogram, loudness, beats, cue markers coloured by sync (green = within a frame, amber = within 100 ms, red = no sound). OPEN THE PNG with your image reader: gaps, pile-ups, masking and late hits are obvious at a glance.
  3. earshot critique film.mp4
    (
    --fast
    skips the AudioSet / realness passes) - scorecard against the measured range of professional launch films: each metric ok / low / high with its weight and actions with timestamps, and a verdict (launch-grade / close / needs work / not launch-grade). Fix critical rows first, re-run 1-3 on the new render. Its "onset on visual events" share counts new attacks within +-100 ms only (the references' definition); its fixes and tips name the cuts with no sound at all, by the same matcher as timeline. If the file is one of the profile's own reference films, critique says so and scores it against the others.
  4. Exact meters any time (LUFS, true peak dBTP, LRA, noise floor, attack / decay, brightness, bands):
    earshot measure mix.wav [--music]
    or the MCP
    measure
    tool.
  1. earshot timeline film.mp4 --cues cues.json
    (或
    soundtrack.wav --video film.mp4
    )——生成 listening transcript:包含带时间、level 和 tags 的 events、sections、loudness curve、picture cuts,以及每个 cut / cue 的 sync。
    --detail low
    速度较快,
    high
    最多标记 96 个 events(最重要的排在前面;summary 会说明标记了多少个,因此未标记的 event 并不代表缺少声音)。请阅读 sync stats:offset_ms = sound minus picture(负值表示提前),而 'chance' fraction 表示随机 edit points 能获得的分数;只有优于 chance 的 sync 才具有意义。某个 cut 即使没有列出的 hit,也仍可能带有柔和的 whoosh:添加声音前,应先在 sheet 上检查。
  2. earshot sheet film.mp4 -o sheet.png --cues cues.json
    (
    --from 10 --to 25
    可放大,
    --detail low
    更快)——生成 annotated PNG:包含 frames、sections、labelled events、spectrogram、loudness、beats,以及按 sync 着色的 cue markers(绿色 = 在一帧内,黄色 = 在 100 ms 内,红色 = 没有 sound)。务必使用 image reader 打开 PNG:gaps、pile-ups、masking 和 late hits 一眼即可发现。
  3. earshot critique film.mp4
    (
    --fast
    会跳过 AudioSet / realness passes)——根据专业 launch films 的测量范围生成 scorecard:每项 metric 标为 ok / low / high,附有 weight、带时间戳的 actions,以及 verdict(launch-grade / close / needs work / not launch-grade)。先修复关键行,再对新 render 重新运行步骤 1–3。“onset on visual events” share 只统计位于 ±100 ms 内的新 attacks(与 references 的定义一致);fixes 和 tips 会通过与 timeline 相同的 matcher 指出完全无声的 cuts。如果该文件属于 profile 自身的 reference films,critique 会明确说明,并将它与其他文件进行评分比较。
  4. 随时获取精确 meters(LUFS、true peak dBTP、LRA、noise floor、attack / decay、brightness、bands):
    earshot measure mix.wav [--music]
    或使用 MCP
    measure
    tool。

Loop 3: A/B a change

循环 3:对改动进行 A/B 测试

  • earshot ab before.wav after.wav --query "warm punchy kick"
    or
    --refs pro_refs/
    - which is closer, and how B differs from A in measured words (louder, brighter, longer decay). For sounds inside longer files pass the trims (
    --a-start 1.217 --a-end 1.615 --b-start 7.881 --b-end 8.285
    ): a whole-file A/B of multi-take files compares every take plus the silence between them. Then
    earshot timeline after.wav
    and compare the event lines and sync stats with the old run. Change one thing at a time.
  • earshot ab before.wav after.wav --query "warm punchy kick"
    或
    --refs pro_refs/
    ——判断哪一个更接近,并用 measured words 说明 B 与 A 的差异(更响、更亮、decay 更长等)。对于较长文件内部的声音,请传入 trims(
    --a-start 1.217 --a-end 1.615 --b-start 7.881 --b-end 8.285
    ):对 multi-take 文件执行 whole-file A/B 会比较每个 take 及其间的所有静音。随后运行
    earshot timeline after.wav
    ,并将 event lines 和 sync stats 与旧结果进行比较。每次只改一个因素。

Loop 4: make a sound in code (earshot forge)

循环 4:在代码中制作声音(earshot forge)

Use this when the user wants a sound made, not chosen: an AI that hears can write synthesis code, listen, and improve it. Every sample must be computed (no recorded audio inside, not even an impulse response); real recordings are only the references the critic compares with.
  1. Write or pick a recipe in
    earshot/forge/recipes/<name>.py
    :
    SPACE
    (parameter ranges),
    DEFAULTS
    ,
    TARGET
    ,
    ALTS
    (realistic confusions) and
    render(params, r) -> 48 kHz array
    , built from
    earshot.forge.dsp
    (modal resonators, contact excitations, noise colours, a time-varying SVF, a computed room, a mic with a noise floor). Model the physics of the real thing, measured on the references: what strikes what, what rings, how long, in what room.
  2. Run one round:
    earshot forge <recipe> --refs <real refs> --budget 144 --reps 2 --tone 1.5 --keep 4 --robust 8 --dir <round dir>
    , or in one Python script per round that loads the models once:
    forge(recipe, critic=Critic(target, alts, refs, tone=1.5), reps=2, space={...})
    .
    • --tone
      puts the model-free tonal balance and tail into the objective.
    • --reps 2
      ranks each candidate by 2 renders, against lucky renders.
    • It takes about 3-5 minutes per 160 renders on a busy laptop CPU, including a 30-60 s model warm-up.
  3. Read what it heard. Each pick's summary says, for example, "sounds like: a cork pop, a glass ting", "decay +2.4 outside the refs" or "tone 11.2 dB from the refs' median: +16 dB at 500-630 Hz (above every ref)". Then check the picks four ways:
    • the model-free
      tone
      words: which bands fall outside every reference, the energy shares, the tail, the length (the most trustworthy signal once the model scores are high)
    • robust
      : the mean over new seeds, not the lucky best render
    • alt_zs
      : which confusion is closest
    • spectrograms next to the references:
      ffmpeg -i x.wav -lavfi showspectrumpic=s=900x360:scale=log:legend=0 x.png
    The AudioSet tags in report.json are held out only while you do not pick or steer by them. Fix a selection rule (for example, the robust mean) before you look, and report the tags afterwards.
  4. Change the recipe's structure, not only its ranges, for what is wrong (a missing release tick, a metallic ring, a tail too long). Then repeat. Keep a LOG of each round's change and numbers.
  5. Report honestly, next to the real references scored by the same critic (
    report.json
    ref_scores, leave-one-out).
Goodhart, say it plainly:
  • The search optimises earshot's own models. Made sounds routinely out-score real recordings on them, which means the critic is satisfied, not that the sound is better.
  • p_real is easy to fool: modal resonators plus a room and a mic noise floor read "real".
  • Typicality rewards being an average of the references.
  • The model checks saturate: after a search, every model check, held-out phrasings and independent real sets included, puts the made sound inside the real ones. Only measurements and ears can still tell them apart.
  • Judge by measured closeness to the references: tonal balance, bands outside every reference, tails, lengths. Also use robust re-renders and spectrograms.
  • Ask for a human blind test (random order, loudness-matched, hidden key) before calling a made sound "as good as real".
In the first test (demo/forge-test) an independent judge found the key press 8-13 dB off the real tonal balance and the pops band-unlimited with long hissy tails, while every model check called them real. Re-made by steering with the model-free check, they now sit inside the real recordings' measured spread. The whoosh was re-made as a truly fast one. The impact (darker, swell-led) and the click (short tails) were not re-made. No human has listened yet.
当用户希望制作声音,而不是挑选现成声音时,使用此功能:能够听见的 AI 可以编写 synthesis code、进行聆听并不断改进。每个 sample 都必须通过计算生成(内部不得包含 recorded audio,即使是 impulse response 也不允许);真实 recordings 仅作为 critic 进行比较的 references。
  1. 在
    earshot/forge/recipes/<name>.py
    中编写或选择一个 recipe:
    SPACE
    (parameter ranges)、
    DEFAULTS
    、
    TARGET
    、
    ALTS
    (realistic confusions)以及
    render(params, r) -> 48 kHz array
    ,并基于
    earshot.forge.dsp
    构建(modal resonators、contact excitations、noise colours、time-varying SVF、computed room、带 noise floor 的 mic)。依据 references 上测得的物理规律建模真实对象:什么撞击什么、什么会产生 ring、持续多久、处于何种 room。
  2. 运行一轮:
    earshot forge <recipe> --refs <real refs> --budget 144 --reps 2 --tone 1.5 --keep 4 --robust 8\n   --dir <round dir>
    ,或者每轮使用一个 Python script,从而只加载一次 models:
    forge(recipe, critic=Critic(target, alts, refs, tone=1.5), reps=2, space={...})
    。
    • --tone
      会把不依赖模型的 tonal balance 和 tail 加入 objective。
    • --reps 2
      会依据 2 次 renders 对每个 candidate 进行 ranking,并与幸运 renders 对比。
    • 在繁忙的笔记本 CPU 上,每 160 次 renders 约需 3–5 分钟,其中包括 30–60 秒的 model warm-up。
  3. 阅读它听到的结果。每个 pick 的 summary 例如会写:“sounds like: a cork pop, a glass ting”“decay +2.4 outside the refs”或“tone 11.2 dB from the refs' median: +16 dB at 500-630 Hz (above every ref)”。然后从四个方面检查 picks:
    • 不依赖模型的
      tone
      words:哪些 bands 超出所有 references、energy shares、tail、length(当 model scores 较高时,这是最可信的 signal)。
    • robust
      :基于新 seeds 取到的平均值,而不是幸运的最佳 render。
    • alt_zs
      :最接近哪一种 confusion。
    • 将 spectrograms 与 references 并排比较:
      ffmpeg -i x.wav -lavfi showspectrumpic=s=900x360:scale=log:legend=0 x.png
      。
    在你选择或据此引导之前,report.json 中的 AudioSet tags 会保持 held out。先确定一条 selection rule(例如使用 robust mean),然后再查看这些 tags,并在事后报告它们。
  4. 针对问题修改 recipe 的结构,而不只是 ranges(例如缺少 release tick、出现 metallic ring、tail 太长)。然后重复此过程。为每轮改动和数值保留一份 LOG。
  5. 使用同一个 critic 对真实 references 进行评分,并在旁边诚实报告结果(
    report.json
    ref_scores,leave-one-out)。
要直白说明 Goodhart 定律:
  • 搜索优化的是 earshot 自己的 models。制作出来的 sounds 经常能在这些 models 上超过真实 recordings,这只意味着 critic 已被满足,并不代表声音更好。
  • p_real 很容易被欺骗:modal resonators 加上 room 和 mic noise floor 就会呈现为“real”。
  • Typicality 会奖励取 references 的平均值。
  • 模型检查会饱和:经过搜索后,所有 model checks、held-out phrasings 和 independent real sets 都会将制作的声音归入真实声音范围。只有 measurements 和耳朵仍能区分它们。
  • 应根据与 references 的 measured closeness 进行判断:tonal balance、超出所有 references 的 bands、tails 和 lengths。同时使用 robust re-renders 与 spectrograms。
  • 在称制作的声音“与真实声音一样好”之前,应要求进行 human blind test(随机顺序、响度匹配、隐藏 key)。
在第一次测试(demo/forge-test)中,一名独立 judge 发现 key press 的真实 tonal balance 偏差了 8–13 dB,pops 没有 band 限制且带有很长的 hissy tails,而所有 model checks 都称其为 real。通过不依赖模型的 check 进行引导并重新制作后,它们现在已落在真实 recordings 的 measured spread 内。whoosh 被重新制作成真正快速的版本。impact(更暗、以 swell 为主)和 click(短 tails)没有重新制作。目前还没有人进行试听。

Loop 5: make a film's sound kit (earshot sfx / earshot kit)

循环 5:为影片制作 sound kit(earshot sfx / earshot kit)

Use this when a code-made film (a cinetic film, any cue sheet) needs its effects: render them from earshot's shipped bank instead of writing synth voices. No models load; a whole kit renders in about a minute and re-renders in seconds.
  1. Start from a preset:
    earshot kit init --preset calm -o audio/kit.json
    (calm for text-led films, crisp for energetic product films, minimal for designed effects-only films). Each role's
    note
    says why its sound was chosen; riser, swell and suck are off: a reveal resolves on one element, and the lockup is one clean hit.
  2. Fit it to the film:
    earshot sfx list --kind hit
    (or
    --category
    ) shows the candidates with lengths, peak times and knobs. Change a role's
    sound
    , set
    edits
    (
    pitch
    to the film's root for the hit or drop,
    dur
    /
    apex
    for a fixed move),
    takes
    (12 or more for typing, 2-4 elsewhere),
    level_db
    . Audition one candidate with
    earshot sfx render ID -o x.wav [--pitch E5] [--dur 0.8 --apex 0.32]
    and read its measured onset / peak / end.
  3. Render:
    earshot kit render audio/kit.json --out audio/kit
    . The takes and
    kit.lock.json
    (measured onset, peak, end, loudness per take) are what the mixer places on cue frames: onset on the frame for hits and touches, the peak on a whoosh's apex, the end on a riser's hit.
  4. Check:
    earshot kit check audio/kit.json --out audio/kit
    . It refuses what a render cannot use (a knob or pitch the sound cannot take, a level over 0 dBFS, two takes that would share a file). Every warning names a take and a reason (clicks, a cut tail, comb ring, silence, a pitch that climbs more than 4 semitones, a hit with two attacks or a build before it,
    pitch_off
    : a note the knob did not land); swap the sound or the knob rather than keeping a warned take. Read the notes too (a sounded riser, a composite sting).
  5. Listen through the finished film with Loop 2 (
    timeline --cues
    ,
    sheet
    ) and check that each cue landed. Say plainly what the bank is: forge sounds made in code, and 15 sounds fitted as code from CC0 recordings (
    fit/<role>/<name>
    , each with its source; the presets use them for clicks, ticks, keys, touches and the snap), all chosen and checked by measurement. They are not recordings: when the brief asks for recorded sound, use
    skills/real-sound
    instead. To add a fit of your own (
    earshot fit --takes
    , then
    bank add-fit
    ), see
    docs/SFX.md
    ("Add your own fit").
当一部由代码制作的影片(cinetic film、任意 cue sheet)需要 effects 时,使用此功能:从 earshot 自带的 bank 中 render,而不是编写 synth voices。此过程不加载 models;整个 kit 约需一分钟 render,重新 render 只需数秒。
  1. 从 preset 开始:
    earshot kit init --preset calm -o audio/kit.json
    (calm 适用于以文字为主的影片,crisp 适用于充满活力的产品影片,minimal 适用于仅使用设计感 effects 的影片)。每个 role 的
    note
    都会说明为何选择该声音;riser、swell 和 suck 默认关闭:reveal 应由一个 element 完成收束,而 lockup 应是一个 clean hit。
  2. 根据影片调整:
    earshot sfx list --kind hit
    (或
    --category
    )会显示 candidates 的 lengths、peak times 和 knobs。更改某个 role 的
    sound
    ,设置
    edits
    (使用
    pitch
    将 hit 或 drop 对齐到影片的 root;使用
    dur
    /
    apex
    固定 movement)、
    takes
    (typing 使用 12 个或更多,其他情况使用 2–4 个)和
    level_db
    。使用
    earshot sfx render ID -o x.wav [--pitch E5] [--dur 0.8 --apex 0.32]
    试听一个 candidate,并读取测得的 onset / peak / end。
  3. Render:
    earshot kit render audio/kit.json --out audio/kit
    。takes 和
    kit.lock.json
    (每个 take 的 measured onset、peak、end、loudness)供 mixer 在 cue frames 上放置声音:hits 和 touches 对齐 frame 的 onset,whoosh 对齐其 apex 的 peak,riser 则将其 hit 对齐 end。
  4. 检查:
    earshot kit check audio/kit.json --out audio/kit
    。它会拒绝 render 无法使用的内容(sound 无法采用的 knob 或 pitch、超过 0 dBFS 的 level、会共用同一文件的两个 takes)。每条 warning 都会指出具体 take 和原因(clicks、cut tail、comb ring、silence、pitch 攀升超过 4 个 semitones、带两个 attacks 或在 hit 前带有 build 的声音、
    pitch_off
    :knob 未达到目标 note);不要保留有 warning 的 take,应更换 sound 或 knob。还要阅读 notes(例如 sounded riser、composite sting)。
  5. 使用循环 2(
    timeline --cues
    、
    sheet
    )从头到尾审听完成的影片,并检查每个 cue 是否准确落位。
要坦白说明 sound bank 的构成:earshot forge sounds 由代码制作,另有 15 个 sounds 根据 CC0 recordings 以代码方式 fit(
fit/<role>/<name>
,每个都附有 source;presets 使用它们生成 clicks、ticks、keys、touches 和 snap),全部经过测量选择和检查。它们不是 recordings:如果 brief 要求 recorded sound,请改用
skills/real-sound
。要添加自己的 fit(
earshot fit --takes
,然后
bank add-fit
),请参阅
docs/SFX.md
(“Add your own fit”)。

Optional: a second opinion in words (audio LLM)

可选:以文字形式获取第二意见(audio LLM)

earshot llm mix.wav --yes-upload [--with-timeline] [--prompt "Is the riser at 0:12 cheap?"]
asks Google Gemini for a rubric critique (sync, realism, mix, loudness, what sounds cheap, fixes with times). It only runs when the user has set GEMINI_API_KEY (or GOOGLE_API_KEY) AND explicitly agreed that the audio is uploaded to Google; ask first, never pass --yes-upload / consent=true on your own. Only audio is sent (mono 64 kbps). Its timestamps are approximate and its scores are one model's opinion: confirm every fix with timeline / ab.
earshot llm mix.wav --yes-upload [--with-timeline] [--prompt "Is the riser at 0:12 cheap?"]
会请求 Google Gemini 提供基于 rubric 的 critique(sync、realism、mix、loudness、哪些声音显得廉价,以及带时间的修复建议)。只有在用户已设置 GEMINI_API_KEY(或 GOOGLE_API_KEY),并且明确同意将音频上传到 Google 后,它才会运行;必须先询问,绝不能自行传入
--yes-upload
或
consent=true
。它只发送音频(mono 64 kbps)。它给出的 timestamps 是近似值,scores 也只是单个 model 的意见:每项修复都要通过 timeline / ab 确认。

Reading the numbers

如何解读数值

numberwhat it istrust
LUFS, dBTP, LRA, dBFS, ms, Hzmeasurements (BS.1770 meter, spectrum, envelope)exact; use them for levels
z (match / rank / find / describe tags)how far a description stands out among the few hundred vocabulary descriptions scored on the same soundverdicts: z >= 3 strong, 2.5-3 plausible, 2-2.5 weak, < 2 no match (held-out evidence per band in eval/semantics/RESULTS.md)
p_vs_altsuncalibrated, sharp forced choice between your query and your alternativesonly says which wording fits best; judge by z
cosineraw CLAP similaritynever a probability; compare only for the same sound and query
AudioSet labels (0..1)independent per-class probabilities from the AST taggergood for broad classes; hears only up to 8 kHz
p_real / verdictreal or pro-produced vs code-synthesized, from a small fitted modelstrong evidence, not proof; read its evidence list; thresholds differ for clips (<= 6 s) and long files (named in each summary)
digital_silence_fracshare of exact-zero samplesweak alone: edit / fade padding is common in real recordings
typicality z (compare)distance to the reference set vs the refs' own spread>= -1 fits the set, < -2 outlier
sync offset_ms, chancesound minus picture per cut / cue; what random edits would scoretrust when well above chance
critique statusvalue vs the range of 7 professional launch films (loudness: web-delivery practice; true peak <= -1 dBTP for a master, <= 0 dBTP for decoded AAC / MP3, which already holds the codec overshoot)a range, not a target: ok = inside what pros do
Prefer measurements, then verdicts / z / probabilities; never present cosine as confidence.
数值代表什么可信度
LUFS、dBTP、LRA、dBFS、ms、Hzmeasurements(BS.1770 meter、spectrum、envelope)精确;用于 levels
z(match / rank / find / describe tags)在针对同一个 sound 评分的数百条 vocabulary descriptions 中,该描述有多突出verdicts:z >= 3 为 strong,2.5–3 为 plausible,2–2.5 为 weak,< 2 为 no match(各频段的 held-out evidence 见 eval/semantics/RESULTS.md)
p_vs_alts在 query 与 alternatives 之间进行的未校准强制选择只能说明哪种 wording 最合适;应依据 z 判断
cosine原始 CLAP similarity绝不能当作 probability;仅可比较相同 sound 与 query 的结果
AudioSet labels(0..1)AST tagger 给出的各 class 独立 probabilities适合 broad classes;只能听到 8 kHz 以内
p_real / verdict小型拟合 model 给出的 real 或 professionally produced 与 code-synthesized 判定是有力证据,但不是证明;应阅读其 evidence list;clips(<= 6 s)与长文件使用不同 thresholds(每个 summary 都会注明)
digital_silence_fracexact-zero samples 的占比单独使用时很弱:edit / fade padding 在真实 recordings 中很常见
typicality z(compare)与 reference set 的距离相对于 refs 自身 spread 的关系>= -1 表示符合该 set,< -2 表示 outlier
sync offset_ms、chance每个 cut / cue 的 sound minus picture,以及随机 edits 会获得的分数只有明显高于 chance 时才可信
critique status与 7 部专业 launch films 范围相比的数值(loudness:web-delivery practice;master 的 true peak <= -1 dBTP,解码后的 AAC / MP3 <= 0 dBTP,后者已包含 codec overshoot)它是范围而非目标:ok = 位于 professionals 使用的范围内
优先使用 measurements,其次是 verdicts / z / probabilities;绝不能将 cosine 表述为 confidence。

Writing queries

编写 queries

Describe the sound, not its use: source + material + action + character ("a heavy wooden door slamming in a small room", not "a sound for the logo"). Give alternatives that are realistic confusions (thock vs click vs typewriter). When a z is borderline, try two or three phrasings: trust a reading that holds up under all of them.
描述声音本身,而不是它的用途:source + material + action + character(“a heavy wooden door slamming in a small room”,而不是“a sound for the logo”)。给出符合现实情况的 alternatives(thock vs click vs typewriter)。当 z 处于临界状态时,尝试两三种 phrasing:只有各种表述下都能成立的 reading 才值得信任。

Limits (say these plainly when they matter)

限制(相关时应直白说明)

  • Taste is not measured: earshot says what a sound is and how it measures, not whether it is beautiful or right for the story. The user decides on taste; give them the evidence and the shortlist.
  • No speech recognition (it can tell there is speech, not what is said) and no lyric or language judgement.
  • CLAP hears 50 Hz - 14 kHz and AST up to 8 kHz: check "air" and low-pass problems with measure (bandwidth_hz, bands).
  • Very short sounds are padded to a 10 s window; isolated hits read best with find / describe on a trimmed segment.
  • attack_ms / decay_ms come from smoothed envelopes (5 ms / 10 ms RMS): an instant attack reads ~4 ms, and very short clicks cannot read below ~10-20 ms of decay.
  • Picture cuts come from a frame-difference detector: hard cuts and whips are reliable, slow crossfades are missed or found late, and motion inside a shot is not an event, so pass cue times (--cues) for animation.
  • Mixed, dense material blurs tags: describe a stem or a segment rather than the whole mix.
  • Licence, provenance and attribution are not audio questions: earshot cannot check them.
  • 无法测量 taste:earshot 能说明一个 sound 是什么及其测量结果,但不能判断它是否美丽或是否适合故事。由用户决定 taste;应向他提供 evidence 和 shortlist。
  • 不支持 speech recognition(它只能判断存在 speech,不能判断说了什么),也不评估 lyrics 或 language。
  • CLAP 可听到 50 Hz–14 kHz,AST 最高到 8 kHz:请使用 measure(bandwidth_hz、bands)检查“air”和 low-pass 问题。
  • 很短的 sounds 会被 padded 到一个 10 秒 window;对于 isolated hits,最好使用 find / describe 分析 trimmed segment。
  • attack_ms / decay_ms 来自 smoothed envelopes(5 ms / 10 ms RMS):instant attack 会读作约 4 ms,非常短的 clicks 无法读出低于约 10–20 ms 的 decay。
  • Picture cuts 来自 frame-difference detector:hard cuts 和 whips 很可靠,slow crossfades 可能漏检或发现过晚;shot 内的 motion 不属于 event,因此请传入 cue times(
    --cues
    )以处理 animation。
  • Mixed、dense material 会使 tags 变得模糊:请分析 stem 或 segment,而不是整个 mix。
  • Licence、provenance 和 attribution 不属于音频问题:earshot 无法检查这些内容。