godot-audio — Claude Code skill: audio setup in Godot 4.7
Sets up playback, mixing and beat-aware timing for Godot 4.7 audio. Use it when a project needs music, SFX, audio buses or positional sound.
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-audio -a claude-codeWhat godot-audio does
The skill covers AudioStreamPlayer for music, UI sounds and global effects, plus AudioStreamPlayer2D and AudioStreamPlayer3D for positional playback. It explains assigning .ogg or .wav streams, calling play(), enabling autoplay and routing players to named Music and SFX buses.
It includes patterns for changing bus volume and mute state through AudioServer, crossfading between music tracks, and letting short sound effects overlap. volume_db is measured in decibels, so 0.5 is close to full volume. That is a reason to map sliders with linear_to_db or use the linear player and AudioServer helpers.
For rhythm events, the skill calculates playback time using the latest audio mix time and output latency. It also covers cut-off SFX, mistyped bus names, music loops, and silent 3D audio when AudioListener3D or Camera3D is missing.
What it helps with
- play music and short SFX in Godot
- route
AudioStreamPlayernodes toMusicandSFXbuses - change bus volume and mute state with
AudioServer - crossfade between music tracks
- sync gameplay events to a beat
Example prompts for the agent
- Set up music playback through
AudioStreamPlayerand theMusicbus in my Godot 4.7 project. - Write code for an
SFXvolume slider usingAudioServerwithout assigning directly tovolume_db. - Fix beat timing for a gameplay event by accounting for audio output latency.
How to install godot-audio
1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-audio -a claude-code2Manually: put the files in place
~/.claude/skills/godot-audio/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/godot-audio/
1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-audio -a codex2Manually: put the files in place
.agents/skills/godot-audio/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-audio -a cursor2Manually: put the files in place
.cursor/skills/godot-audio/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install gamedev-skills/awesome-gamedev-agent-skills godot-audio2Manually: put the files in place
.github/skills/godot-audio/SKILL.md1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-audio -a gemini-cli2Platform CLI
gemini skills install https://github.com/gamedev-skills/awesome-gamedev-agent-skills --path skills/godot/godot-audioManually: put the files in place
.devin/skills/godot-audio/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-audio -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about godot-audio
How do I install godot-audio in Claude Code?
Run npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-audio -a claude-code, then run npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-audio -a claude-code again. The skill file is at ~/.claude/skills/godot-audio/SKILL.md.
What does godot-audio do?
It provides guidance for playing and mixing audio in Godot 4.7. Coverage includes player nodes, buses, decibel volume, effects, music, SFX and beat timing.
Why should a slider not write directly to volume_db?
volume_db uses decibels rather than a linear scale. Map slider values with linear_to_db, or use linear helpers on players and AudioServer.
Source text
SKILL.md · Apache-2.0
---
name: godot-audio
description: >
Play and mix audio in Godot 4.7: AudioStreamPlayer (2D/3D variants), audio buses
with volume/mute and effects, music vs SFX routing, db/linear volume, and precise
sync-to-beat playback timing. Use when playing sounds or music in a Godot project,
routing AudioStreamPlayer nodes to buses, adjusting bus volume via AudioServer, or
syncing gameplay to the beat.
---
# Godot Audio (4.x)
Play SFX and music, route them through buses, control volume in decibels, and time
gameplay to the beat. Targets **Godot 4.7**.
## When to use
- Use when playing sound effects or music, routing audio to buses (Master/Music/SFX),
adjusting volume/mute from code, adding bus effects (reverb, compressor), positional 3D
audio, or syncing events to music.
**When *not* to use:** engine-agnostic audio *design* (adaptive music structure, mixing
philosophy, ducking patterns) → `audio-design`; importing/encoding assets outside Godot.
## Core workflow
1. **Pick the player node:**
- `AudioStreamPlayer` — non-positional (music, UI, global SFX).
- `AudioStreamPlayer2D` / `AudioStreamPlayer3D` — positional; volume/pan from distance.
2. **Assign an `AudioStream`** to `stream` (`.ogg` for music/loops, `.wav` for short SFX)
and `play()`. Set `autoplay` for music that starts with the scene.
3. **Route to a bus.** Set the player's `bus` to a named bus (e.g. `"Music"`, `"SFX"`).
Define buses in the Audio panel (bottom dock); each can have volume, mute, solo, and
effects.
4. **Control volume in dB**, not linear (audio is logarithmic). `0 dB` = unchanged,
`-80 dB` ≈ silent. Convert with `linear_to_db`/`db_to_linear`, or use the linear helpers
(`volume_linear` on players, `AudioServer.set_bus_volume_linear()`), which convert for you.
5. **Drive volume/mute from code** with `AudioServer` by bus index.
6. **For rhythm**, compute precise playback time using output latency compensation.
## Patterns
### 1. One-shot SFX (fire-and-forget)
```gdscript
@onready var sfx: AudioStreamPlayer = $Sfx # stream assigned in the editor
func play_jump() -> void:
sfx.pitch_scale = randf_range(0.95, 1.05) # slight variation avoids fatigue
sfx.play()
# For overlapping copies, raise sfx.max_polyphony (default 1), use an
# AudioStreamPolyphonic stream, or spawn short-lived players and free on `finished`.
```
### 2. Set a bus's volume and mute via AudioServer
```gdscript
func set_music_volume(linear_0_to_1: float) -> void:
var bus := AudioServer.get_bus_index("Music")
# Convert a 0..1 slider to decibels; clamp avoids -inf at 0.
AudioServer.set_bus_volume_db(bus, linear_to_db(maxf(linear_0_to_1, 0.0001)))
func toggle_sfx(muted: bool) -> void:
AudioServer.set_bus_mute(AudioServer.get_bus_index("SFX"), muted)
```
### 3. Crossfade between two music tracks
```gdscript
@onready var a: AudioStreamPlayer = $MusicA
@onready var b: AudioStreamPlayer = $MusicB
func crossfade_to(stream: AudioStream, secs := 1.5) -> void:
b.stream = stream
b.volume_db = -40.0
b.play()
var tw := create_tween().set_parallel(true)
tw.tween_property(a, "volume_db", -40.0, secs) # fade out current
tw.tween_property(b, "volume_db", 0.0, secs) # fade in next
tw.chain().tween_callback(a.stop)
var tmp := a; a = b; b = tmp # swap roles
```
### 4. Beat-accurate timing (compensate for output latency)
```gdscript
@onready var music: AudioStreamPlayer = $Music
func get_playback_time() -> float:
# Add time since the last audio mix, subtract output latency, for sub-frame accuracy.
var t := music.get_playback_position() + AudioServer.get_time_since_last_mix()
return t - AudioServer.get_output_latency()
```
## Pitfalls
- **Treating volume as linear.** `volume_db`/`set_bus_volume_db` are decibels. Setting
`volume_db = 0.5` is nearly full volume, not half. Map sliders with `linear_to_db`.
- **`linear_to_db(0.0)` is `-inf`.** It is silent, but tweening or doing math from `-inf`
produces NaN. Clamp the linear value to a small minimum (e.g. `0.0001`) before converting,
or special-case 0 → mute. `set_bus_volume_linear(bus, 0.0)` stores `-inf` too.
- **Bus name typos fail quietly.** `get_bus_index("Muisc")` returns `-1`; calls then error
or no-op. Match the exact bus name from the Audio panel.
- **Short SFX cut off** when the same player is retriggered → `max_polyphony` defaults to 1.
Raise it (e.g. 4) so `play()` overlaps copies, or use an `AudioStreamPolyphonic` /
separate players freed on `finished`.
- **Music doesn't loop** unless the import/stream loop is enabled (`.ogg` import has a
Loop option; `AudioStreamWAV` has `loop_mode`).
- **Syncing to `get_playback_position()` alone is jittery** — it updates per audio mix,
not per frame; add `get_time_since_last_mix()` and subtract `get_output_latency()`.
- **3D audio inaudible** → no `AudioListener3D`/`Camera3D` to hear it, or `max_distance`/
attenuation too tight, or wrong bus muted.
## References
- For the bus layout (`.tres`), adding effects (reverb/compressor/EQ) and side-chain
ducking, `AudioStreamPolyphonic`/`AudioStreamInteractive`, microphone capture, and
procedural audio with `AudioStreamGenerator`, read `references/buses-and-effects.md`.
## Related skills
- `audio-design` — engine-agnostic adaptive music, mixing, and ducking practice.
- `godot-animation` — syncing animation/Tween to `get_playback_position()`.
- `godot-ui-control` — volume sliders wired to `AudioServer`.
© gamedev-skills · Apache-2.0 · gamedev-skills/awesome-gamedev-agent-skills