AI 클라이언트가 비파괴적 편집과 고급 플러그인을 사용하여 오디오 파일을 편집, 분석 및 변환할 수 있도록 합니다.
다른 이름 audiojs/audio
- 스타
- 334
- Tools
- —
- 다운로드, 30일
- —
- 최신 버전
- 2.10.0
- 마지막 커밋
- 2026년 11월 10일
- 라이선스
- MIT
Audio MCP란?
Audio은(는) MCP server입니다. AI 클라이언트가 비파괴적 편집과 고급 플러그인을 사용하여 오디오 파일을 편집, 분석 및 변환할 수 있도록 합니다.
프로젝트 README에서 생성된 요약
Audio MCP server 정보
Audio는 개발자와 AI 에이전트가 로드, 재생, 분석 및 편집을 포함한 고급 오디오 조작을 수행할 수 있도록 지원합니다. 노이즈 제거, 이퀄라이제이션, 리버브, 음악 분석 등의 작업을 위한 140개 이상의 플러그인을 지원합니다. 시스템은 비파괴적 가상 편집을 사용하여 원본 소스를 변경하지 않고도 무한 실행 취소와 파일의 즉각적인 복제를 지원합니다. 스트림 우선 및 페이지 기반 방식이므로 표준 2GB 메모리 제한을 초과하는 10GB 이상의 대용량 파일도 처리할 수 있습니다.
사용자는 이 서버를 Node, Bun, Deno 및 브라우저를 포함한 다양한 환경에 통합할 수 있습니다. MCP 브릿지를 통해 Claude Code, Cursor, Gemini CLI와 같은 AI 클라이언트와 함께 작동하도록 설계되었습니다. 이 서버는 Apple Podcast 사양에 맞춰 음량과 트루 피크를 확인하는 등 측정 작업을 위한 특정 도구를 제공합니다. 또한 수학적 함수를 사용하여 오디오를 생성하거나 사용자 정의 샘플 함수를 통해 데이터를 소니피케이션(sonification)하는 고급 기능도 지원합니다.
활용 사례
- 1팟캐스트 오디오 준비AI 에이전트가 녹음 파일을 다듬고, 노멀라이즈하며, 팟캐스트 플랫폼의 특정 음량 규칙에 맞는지 확인할 수 있습니다.
- 2음악적 특징 분석개발자가 오디오 파일에서 음표, 코드, 음악적 키와 같은 기술적 데이터를 추출할 수 있습니다.
- 3오디오 마스터링 자동화참조 트랙의 톤과 음량에 맞춰 믹스를 마스터링하도록 에이전트에게 지시할 수 있습니다.
프로젝트의 README를 바탕으로 작성되었습니다. 모든 활용 사례는 해당 내용의 인용문과 대조하여 확인합니다.
Audio MCP 설치 방법
형식 확인: 2026년 11월 10일Cursor에 추가Goose에 추가Claude Code에 Audio MCP 설치
$ claude mcp add audio -- npx -y audioCursor에 Audio MCP 설치
~/.cursor/mcp.json
{
"mcpServers": {
"audio": {
"command": "npx",
"args": [
"-y",
"audio"
]
}
}
}VS Code에 Audio MCP 설치
.vscode/mcp.json
{
"servers": {
"audio": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"audio"
]
}
}
}VS Code CLI에 Audio MCP 설치
$ code --add-mcp '{"name":"audio","type":"stdio","command":"npx","args":["-y","audio"]}'Claude Desktop에 Audio MCP 설치
claude_desktop_config.json
{
"mcpServers": {
"audio": {
"command": "npx",
"args": [
"-y",
"audio"
]
}
}
}Codex에 Audio MCP 설치
$ codex mcp add audio -- npx -y audioCodex config.toml에 Audio MCP 설치
~/.codex/config.toml
[mcp_servers.audio] command = "npx" args = ["-y", "audio"]
Gemini CLI에 Audio MCP 설치
$ gemini mcp add -s user audio npx -- -y audioGemini settings.json에 Audio MCP 설치
~/.gemini/settings.json
{
"mcpServers": {
"audio": {
"command": "npx",
"args": [
"-y",
"audio"
]
}
}
}구성
ANTHROPIC_BASE_URL
| 이름 | 설명 | 유형 |
|---|---|---|
| ANTHROPIC_BASE_URL | — |
자동 검사
2026년 11월 12일에 실행됨전체 보고서 →자동 검사를 통과했습니다. 이는 보안 감사가 아닙니다. 코드를 직접 읽고 서버에 필요한 최소한의 권한만 부여하십시오. 검사 방식
- 소스 저장소 연결 및 접근 가능통과
- 오픈 소스 라이선스 (OSI)통과
- 최근 1년 내 커밋 또는 릴리스통과
- 패키지 이름이 인기 패키지와 유사하지 않음통과
- 원격 엔드포인트가 HTTPS 사용검사되지 않음
- 파괴적인 도구에 라벨 표시됨검사되지 않음
- 모델에 대한 숨겨진 지침 없음통과
- 패키지 및 해당 종속성에 중요한 보안 권고 없음통과
README
GitHub에서 보기audio

High-level audio manipulations: loading, playback, analysis and editing. 140+ plugins: denoise, dynamics, EQ, filters, effects, reverb, time and pitch, spatial, synthesis, music analysis.
- Any Format — fast wasm codecs, no ffmpeg.
- Non-destructive — virtual edits, infinite undo, instant clone.
- Stream-first — playback/encode during decode, realtime editing.
- Paged — no 2Gb memory limit, open 10Gb+ files.
- Analysis — loudness, spectrum, beats, pitch, chords, key.
- Modular – pluggable ops, tree-shakable.
- CLI — playback, batch processing, scripting, unix pipes, tab completion.
- Cross-platform — browsers, node, deno, bun.
Start Recipes API CLI FAQ Plugins Architecture Comparison RX 12
Start
Node
npm i audio
import audio from 'audio'
let song = audio('song.mp3')
song.play() // the speakers, as a page plays it: no ffmpeg, no player to spawn
song.pause(); song.seek(60); song.resume()
let voice = audio('voice.wav').trim().normalize('podcast')
await voice.save('clean.mp3')
let { pass, rules } = await voice.check('podcast') // each rule of Apple's spec, measured
Browser
<script type="module">
import audio from 'https://esm.sh/audio'
audio('./song.mp3').trim().normalize().fade(0.5, 2).clip({ at: 60, duration: 30 }).play()
</script>
Audio anywhere
import 'audio/polyfill' // the page's HTMLAudioElement, in Node, Bun and Deno
let song = new Audio('song.mp3')
song.onended = () => console.log('done')
await song.play()
song.currentTime = 30; song.volume = 0.5; song.loop = true
Events, their order, promises and errors as Chromium's own element has them, compared observation by observation (test/polyfill.js). import { Audio } from 'audio/polyfill' leaves the global alone.
CLI
npm i -g audio # or: npx audio …
audio voice.wav trim normalize podcast save clean.mp3
audio clean.mp3 check podcast
# Apple Podcasts https://podcasters.apple.com/support/893-audio-requirements
# ✓ Loudness -16.44 LUFS -17 to -15
# ✓ True peak -1.18 dBTP ≤ -1
# pass
A fail exits 1, so the same line guards a build: Check in CI.
Skill
npx skills add audiojs/audio
MCP
npx add-mcp "npx -y audio --mcp" # asks which of your agents: Claude Code, Codex, Cursor, Gemini CLI, Kimi Code, Pi, OpenCode, Zed…
Prompt: make ~/Desktop/interview.m4a podcast-ready and tell me the loudness before and after
One agent at a time: claude mcp add audio -- npx -y audio --mcp, qwen mcp add audio npx -y audio --mcp, droid mcp add audio "npx -y audio --mcp".
The repl and agents
npx audio --bridge
# audio bridge on http://127.0.0.1:7777
#
# key 3e37b8c61acf5b50f010852168f4843d
# agents Claude Code, Codex, Pi, Kimi Code
#
# In the repl opened with ?ui={"agent":true}, paste the key in the line under the code, then Connect. It stays the same next time.
Open the repl with its agent line, every edit of it a line of audio code, and connect it to the bridge with the key (once: the bridge keeps it), and the line under its code runs an agent of yours, which measures, looks at, edits and plays the sound open there, and finds which edit did what: it measures the sound before and after each, and what each took out; its conversations are kept, each with the agent, and its model, picked under the line. The bridge finds Claude Code, Codex, Pi, Gemini CLI, Qwen Code, Kimi Code, OpenCode, Kilo Code, Cline, Goose, Factory Droid, Cursor, Augment, Kiro and Mistral Vibe on PATH; any other that speaks ACP runs by its command line, --agent "my-agent --acp".
Any MCP agent gets the repl's tools (state, measure, look, edit, select, play, check, …), the running bridge found by itself: npx add-mcp "npx -y audio --mcp --repl".
An agent thinks with the model its own settings name: Pi takes local ones for good from ollama launch pi --config; Claude Code takes any Anthropic-compatible endpoint from the bridge's environment:
ANTHROPIC_BASE_URL=http://localhost:11434 ANTHROPIC_AUTH_TOKEN=ollama ANTHROPIC_API_KEY= ANTHROPIC_MODEL=qwen3-coder npx audio --bridge
| Models | ANTHROPIC_BASE_URL, with the provider's key as ANTHROPIC_AUTH_TOKEN |
|---|---|
| Ollama | http://localhost:11434, token ollama (docs) |
| Z.ai GLM | https://api.z.ai/api/anthropic (docs) |
| Kimi | https://api.moonshot.ai/anthropic (docs) |
| Qwen | https://coding-intl.dashscope.aliyuncs.com/apps/anthropic, Coding Plan (docs) |
| DeepSeek | https://api.deepseek.com/anthropic (docs) |
Embed
The repl in any page, its script the element's own text: it runs where the reader scrolls to it, plays, takes edits, and opens whole in the repl. Nothing of the reader's is kept.
<script type="module" src="https://audio.js.org/embed.js"></script>
<audio-repl panel="code" display="wave" height="320">
<pre><code>audio('chime.wav')
.trim()
.normalize(-1)</code></pre>
</audio-repl>
What it shows, the frame takes as one JSON: the element's ui attribute, with these attributes over it, each a key of it. panel: code (default), edits (its steps, each with its settings) or none; display: wave or spec; controls: the parts shown, each in its own place: over the picture sound (its name, a menu of its ways in: a file, a take, a sample), link and name (the way to the repl), ruler (the time row; left out, none: the big time says it), look (a band's dropdown of how it draws); in the bar play record loop clock history message heard, a level (level, or what it reads: peak rms loudness), rate channels depth before, view (a switch: the waveform, the spectrogram), open and save (a file of the reader's in; the result out, in the format picked from its menu) — without it, all but sound, view, open and save; ops: edits a press away, one button after the history, a menu of them with their values, as trim normalize(-1) stretch(1.25) reverse (a call's own arguments, or the defaults the menus write); background: the ground it sits on and fades into, a CSS colour, or page, the page's own under the element (the element reads it; a frame can't); height in px. A sound named by its path from the site's root (audio('/sounds/take.mp3')) is that site's file. The <pre> shows until the frame comes, and where scripts don't run. Every key, zoom and overshoot too: repl/README.md.
Recipes
Clean up
// master a raw take
let a = audio('raw-take.wav')
a.trim(-30).normalize('podcast').fade(0.3, 0.5)
await a.save('clean.wav')
// full restoration chain via ecosystem plugins (see API › Plugins)
a.gate(-45).dehum().deesser().compressor({ threshold: -18 }).limiter({ ceiling: -1 })
// cut 2:00–2:15, smooth the splice
a.remove({ at: 120, duration: 15 }).fade(0.1, { at: 120 })
// find clipped blocks
let clips = await a.stat('clipping')
// does it pass? each rule of the spec, measured
let { pass, rules } = await a.check('podcast') // acx, podcast, spotify, broadcast, netflix
Master & deliver
// master a song to a reference track: its tone (mid and side), width and loudness, under -1 dBTP
audio('mix.wav').master(await audio('reference.wav')).save('master.wav')
// audiobook chapter for ACX: RMS -23..-18 dB, peaks under -3 dB, floor under -60 dB, room tone at each end, 44.1 kHz
let ch = audio('chapter-01.wav')
.highpass(80).omlsa({ gMin: -12 }).compressor({ threshold: -24, ratio: 2.5 })
.normalize(-20, 'rms', { ceiling: -3.5 })
.trim().pad(1.5, 2).roomtone() // room tone, not digital silence
.resample(44100)
console.log(await ch.check('acx')) // passed 10 of 10 real narrations (.work/pro.md)
await ch.save('chapter-01.mp3', { bitrate: 192 })
// tighten pauses in a talking-head video, then hand the cuts to the video editor
let talk = audio('talk.mp4').shrink(0.3)
await talk.save('talk.m4a') // the sound, cut
await talk.save('talk.edl') // the same cuts for the picture (Premiere, Resolve)
Compose
// podcast montage
let ep = audio([intro, interview.trim().normalize('podcast'), outro], { crossfade: 0.5 })
await ep.save('episode.mp3')
// voiceover over music
music.gain(-12).mix(voice, { at: 2 })
// ringtone: the chorus + fades
audio('song.mp3').crop({ at: 45, duration: 30 }).fade(0.5, 2).normalize().save('ringtone.mp3')
// split an audiobook into chapters
let [ch1, ch2, ch3] = audio('audiobook.mp3').split(1800, 3600)
// glitch: stutter + reverse
let v = a.clip({ at: 1, duration: 0.25 })
audio([v, v, v, v]).reverse({ at: 0.25, duration: 0.25 })
Analyze
// waveform bars — and progressively, as it decodes
let [mins, peaks] = await a.stat(['min', 'max'], { bins: canvas.width })
a.on('data', ({ delta }) => appendBars(delta.max[0], delta.min[0]))
// features for ML
let mfcc = await a.stat('cepstrum', { bins: 13 })
let [loud, rms] = await a.stat(['loudness', 'rms'])
// notes, chords, key
let notes = await a.stat('notes') // [{time, duration, freq, midi, note, clarity}]
let chords = await a.stat('chords') // [{time, duration, label, root, quality, confidence}]
let key = await a.stat('key') // {tonic, mode, label, confidence}
Record & generate
// mic take
let a = audio()
a.record()
// …later
a.stop()
a.trim().normalize()
// tone — any t => sample function
let tone = audio.from(t => Math.sin(440 * Math.PI * 2 * t), { duration: 2 })
// sonify data
let s = audio.from(t => Math.sin((200 + data[t / 0.2 | 0]) * Math.PI * 2 * t) * 0.5, { duration: data.length * 0.2 })
Automate
a.gain(t => -12 * (0.5 + 0.5 * Math.cos(t * Math.PI * 4))) // 2Hz tremolo in dB
a.lowpass(t => 400 + 4000 * t) // filter sweep
a.pan({ t: [0, 2, 4], v: [-1, 1, -1] }) // curve L→R→L over 4s, serializable
music.ducker({ key: voice }) // sidechain (plugin)
Stream & persist
// stream to network — encode/playback during decode
for await (let chunk of audio('2hour-mix.flac').highpass(40)) socket.send(chunk[0].buffer)
// serialize edits, restore later
let json = JSON.stringify(a) // { source, edits, ... }
let b = audio(JSON.parse(json)) // re-decode + replay edits
API
Create
| Method | Description |
|---|---|
audio(source, opts?) |
decode from file, URL, bytes, or a byte stream. Returns instantly — decodes in background; streams decode as they arrive. |
audio.from(source, opts?) |
wrap existing PCM, AudioBuffer, silence, or function. Sync, no I/O. |
let a = audio('voice.mp3') // file path
let b = audio('https://cdn.ex/track.mp3') // URL
let c = audio(inputEl.files[0]) // Blob, File, Response, ArrayBuffer
let d = audio() // empty, ready for .push() or .record()
let e = audio([intro, body, outro]) // concat (virtual, no copy)
let f = audio([a, b, c], { crossfade: 2 }) // concat with 2s crossfade
let g = audio(process.stdin) // byte stream: pipe, socket, fetch body – decodes as it arrives
// opts: { sampleRate, channels, crossfade, curve, storage: 'memory' | 'persistent' | 'auto' }
await a // await for decode — if you need .duration, full stats etc
let a = audio.from([left, right]) // Float32Array[] channels
let b = audio.from(3, { channels: 2 }) // 3s silence
let c = audio.from(t => Math.sin(440*TAU*t), { duration: 2 }) // generator
let d = audio.from(audioBuffer) // Web Audio AudioBuffer
let e = audio.from(int16arr, { format: 'int16' }) // typed array + format
let f = audio.from(store, { length, channels, sampleRate }) // pages in a store ({ read(i), has(i), write(i, page) }), read as needed
Properties
| Property | Description |
|---|---|
.duration |
total seconds, after edits. |
.channels |
channel count. |
.sampleRate |
sample rate. |
.length |
samples per channel. |
.currentTime |
what the speakers play now, in seconds: their latency compensated, smooth; at pause it holds where playback resumes. |
.playing |
true during playback. |
.paused |
true when paused. |
.volume |
0..1 linear. Settable. |
.muted |
mute, independent of volume. Settable. |
.loop |
settable, mid-playback too: the span repeats, each seam a 10 ms equal-power crossfade. |
.playbackRate |
0.0625..16, settable mid-playback, click-free. The pitch stays (WSOLA, as a browser's media element plays at a speed) unless .preservesPitch is false: then it glides over ~50 ms and the pitch follows, tape-style. .speed() bakes it. |
.preservesPitch |
true: at a rate other than 1, the pitch kept. false: varispeed, the pitch with the speed. Settable mid-playback. |
.ended |
true when playback reached the end, not after stop(). |
.seeking |
true during a seek. |
.played |
promise, resolves when playback sounds. |
.recording |
true during mic recording. |
.ready |
promise, resolves when fully decoded. |
.source |
original source. |
.bitDepth |
stored sample depth of the source: 16, 24, 32 (float); null for lossy or generated audio. Lossless save keeps it. |
.pages |
Float32Array page store. |
.stats |
per-block stats (peak, rms, etc.). |
.edits |
edit list. |
.version |
increments on each edit. |
Structure
| Method | Description |
|---|---|
.trim(threshold?) |
strip leading/trailing silence (dB, default auto). On a live stream a given threshold streams, holding a silent tail until sound resumes; the automatic one reads the whole input, so it waits for the end. |
.shrink(gap?, threshold?) |
shorten silent pauses to gap seconds (default 0.3); 0 removes them. Streams with a given threshold, like trim.≡ FFmpeg silenceremove, Audacity truncate-silence |
.crop({at, duration}) |
keep range, discard rest. |
.remove(at, duration, crossfade?) |
delete range, close gap. crossfade ('10ms') makes the splice an equal-power crossfade centered on the cut; the length stays the same. |
.insert(source, at?, crossfade?) |
insert audio (default: at end), or a number of seconds of silence; crossfade fades both seams. |
.copy({at?, duration?}) |
copy range (default: all) to this instance's clipboard. |
.cut({at?, duration?, crossfade?}) |
copy, then remove. |
.paste({at?, crossfade?}) |
insert the clipboard (default: at end). |
.move({at, duration, to, crossfade?}) |
slide a range to to, over what is there; silence where it was, the length kept (past the end, extended). crossfade crossfades each edge, centered.≡ a DAW's clip moved in slip mode |
.clip({at, duration}) |
zero-copy excerpt as a new instance. |
.split(...offsets) |
zero-copy excerpts between timestamps. |
.pad(before, after?) |
silence at edges (seconds). |
.repeat(n) |
repeat n times. |
.reverse({at?, duration?}) |
reverse audio or range. |
.speed(rate, {type?}) |
changes pitch and duration together; type: 'sinc' reads between samples by a Lanczos sinc (16 zero crossings) instead of linearly, the top octave kept at a rate near 1. |
.stretch(factor, {voice?, method?}) |
changes duration, keeps pitch (phase-locked vocoder). A t => f or {t, v} factor slides the tempo; duration becomes ∫factor dt. A range {at, duration} comes out round(round(duration · sampleRate) · factor) samples long, to the sample; the audio around it as it was. { voice: true } keeps a voice's pulse shape and consonants, which the vocoder makes distant: shortened, its waveform copied a segment at a time (WSOLA, @audio/stretch-wsola); slowed, the vocoder's frames restarted from the waveform where it fits (PVSOLA, @audio/stretch-pvsola), so breath and reverberation are not repeated into a flanger. One voice, not chords. { method } stretches another way, its module loaded only then: 'vocoder', 'pghi', 'wsola', 'psola', 'sms', 'transient', 'hybrid', 'paulstretch' (@audio/stretch-*); 'phase-lock', the default, is the one that streams, slides and takes voice. The others render what they stretch at once, from a constant factor; a range, with a crossfade into the audio either side.≡ Logic Flex Time Monophonic, Ableton Tones |
.warp(markers) |
move moments in time: [[from, to], …] in seconds. Between markers the audio stretches to fit, pitch kept; start and end stay.≡ Logic Flex Time, Ableton warp markers |
.pitch(semitones, {voice?, method?}) |
changes pitch, keeps duration. Semitones may be a curve {t, v} (seconds → semitones, straight between points, flat past the ends, as the gain line's) or t => semitones; where it is zero the audio is as it was. { voice: true } re-spaces a voice's own glottal cycles, found on its pYIN pitch track (TD-PSOLA, the optional @audio/tune-curve): formants and consonants kept, one voice; a range's edges glide as fast as a voice moves its pitch, and its cycles land back on the input's. { method } shifts another way, its module loaded only then (@audio/shift-*): 'vocoder', 'formant' (the voice's tone kept), 'psola', 'wsola', 'lpc', 'transient', 'hybrid', 'hpss', 'sms', 'sample', 'delay', 'ola', 'granular', 'paulstretch', or 'auto' (@audio/shift chooses by the sound, loading them all); 'phase-lock', the default, is the one that streams, follows a curve and takes voice. The others render what they shift at once, by a constant number of semitones; a range crossfades in and out of it over 10 ms.≡ Melodyne pitch drawing |
.intonation(factor) |
a voice's rises and falls wider or flatter about its median pitch: 1 as it was, 0 a monotone, 2 twice as wide. Its own cycles re-spaced (as pitch({ voice: true })): timing, formants and consonants kept, one voice.≡ Praat's pitch range factor |
.modulation(factor) |
each note's vibrato and wobble about its own slow line: 1 as sung, 0 a smooth line, 2 twice as wide, -1 inverted. The notes are Tony's (as stat('notes')); a note's line, its pitch smoothed over its own vibrato period twice. Its cycles re-spaced as intonation's.≡ Melodyne pitch modulation tool |
.drift(factor) |
each note's slow line about its centre: 1 as sung, 0 held at its centre with its vibrato kept, 2 twice the wander.≡ Melodyne pitch drift tool |
.center(factor, {scale?, root?, a4?}) |
each note's centre (the median of its middle half) about the nearest note of scale from root: 1 as sung, 0 on the note, 0.5 half way, all that moves inside it kept; chromatic by default, @audio/note's scale names or degrees. A note is moved from its first frame where it starts after silence; where two meet, the move crosses over 100 ms.≡ Melodyne Correct Pitch, pitch center |
.formant(semitones) |
moves the formants (the spectral envelope: a voice's vowels, the size of its head), keeps the pitch. A number, a curve {t, v} or t => semitones. Any sound; with pitch(), a voice kept its own or made another's.≡ Melodyne formant tool, Praat's formant shift ratio |
.remix(channels) |
channel count (down per ITU-R BS.775: 7.1 → 5.1, stereo, mono), or a map: [1, 0] swaps L/R, null a silent channel. |
Every op takes a trailing {at, duration, channel} range, except channel-changing remix and crossover, and every op that keeps the timeline a mix: how much of its output is heard, the rest its input, 0 to 1 or a curve {t, v} over time ({ mix: { t: [11.99, 12, 14, 14.01], v: [1, 0, 0, 1] } } turns it off from 12 s to 14 s, as RX's Restore Selection; an effect's own mix is its own). Times are seconds or strings ('1:30', '2m'); negative counts from the end. FFmpeg's short names work wherever the long ones do: d for duration, xfade for crossfade (a.remove({ at: 1, d: 0.5, xfade: 0.01 })).
a.trim(-30) // strip silence below -30dB
a.remove({ at: '2m', duration: 15 }) // delete 2:00–2:15, close gap
a.remove(12.3, 0.4, '10ms') // cut a breath, crossfaded: no click
a.insert(intro, { at: 0 }) // prepend; .insert(3) appends 3s silence
a.copy(60, 30).paste(120) // duplicate the chorus at 2:00
a.cut(2, 1).paste(5) // move 2s–3s to 5s of the shortened timeline
a.move({ at: 2, duration: 1, to: 5 }) // slide 2s–3s over 5s–6s, silence left at 2s–3s
let [pt1, pt2] = a.split('30m') // zero-copy parts
let hook = a.clip({ at: 60, duration: 30 }) // zero-copy excerpt
a.stretch(1.1) // 10% longer, same pitch
a.warp([[1, 1], [2, 2.4], [3, 3]]) // the hit at 2s lands at 2.4s; 1s–3s keeps its length
a.pitch(-2) // 2 semitones down, same tempo
a.pitch({ t: [1, 1.2, 2, 2.2], v: [0, 3, 3, 0] }, { voice: true }) // a note drawn 3 semitones up, formants kept
a.intonation(1.5, { at: 2, d: 3 }) // 2s–5s: every rise and fall half as wide again
a.center(0).drift(.5).modulation(.7) // each note on its semitone, half its drift and 70% of its vibrato left
a.formant(-2) // a larger, darker voice on the same notes
a.remix([0, 0]) // L→both; .remix(1) for mono
Audio MCP 질문
Audio MCP를 Claude Code에 추가하려면 어떻게 하나요?
터미널에서 claude mcp add audio -- npx -y audio를 실행합니다. 모든 프로젝트에서 사용할 수 있게 하려면 --scope user를 추가합니다.
Audio MCP를 Cursor에 추가하려면 어떻게 하나요?
~/.cursor/mcp.json를 열고 mcpServers 아래에 서버를 추가합니다. 위 설치 섹션에 표시된 Cursor 구성을 사용합니다.
매우 큰 오디오 파일도 처리할 수 있나요?
네, 페이지 기반 아키텍처를 통해 2GB 메모리 제한에 걸리지 않고 10GB보다 큰 파일도 열 수 있습니다.
편집 과정이 비파괴적인가요?
아니요, 이 서버는 가상 편집과 비파괴적 프로세싱을 사용하므로 무한 실행 취소와 즉각적인 파일 복제가 가능합니다.
어떤 종류의 오디오 분석이 가능한가요?
음량, 스펙트럼, 비트, 피치, 코드 및 키를 분석할 수 있습니다.