agentsclimarketplace

Roblox audio

Skill nonlooped/roblox-suite/roblox-audio

Stop shipping outdated Luau. Production-grade, opinionated skill set for AI agents and developers. Accurate Roblox guidance + reusable scripts, grounded in official docs.

Install
npx -y skills add nonlooped/roblox-suite --skill roblox-audio

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 9 stars9 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Roblox audio — the modern modular audio graph (AudioPlayer, AudioEmitter, AudioListener, Wire, AudioTextToSpeech) and the legacy Sound/SoundGroup system. Covers 2D vs 3D audio, spatial attenuation, effects (Equalizer, Compressor, Reverb, Echo, Distortion), TTS/STT, acoustic simulation, asset permissions and the 2022 privacy changes, concurrent-voice limits, preloading, and looping. Use for any sound, music, voice, or audio-driven feedback.

SKILL.md

16.6 KB, as published. Nobody here has run it

roblox-audio

Official sources (always check these for the latest):

This skill covers both the modern modular audio graph (the recommended system) and the legacy Sound/SoundGroup/SoundEffect system. The official docs now state that Sound, SoundGroup, and SoundEffect are discouraged in favor of the more robust functionality of audio objects. New work should use the graph; legacy code can keep using Sound where the graph offers no advantage.

Cross-reference:

When to use this skill

Activate when:

  • Playing music, SFX, ambient audio, UI feedback, or voice in an experience.
  • Setting up 3D positional audio (footsteps, gunshots, environmental ambience).
  • Building an audio bus / routing / mixing architecture (music ducking, group volume).
  • Applying effects (muffling underwater, reverb in a cave, compression for consistent VO volume).
  • Implementing text-to-speech (accessibility, NPC dialogue) or speech-to-text (voice commands).
  • Migrating legacy Sound code to the new audio graph.
  • Diagnosing audio that doesn't play, cuts out, or sounds wrong on mobile.
  • Understanding audio asset permissions and the Creator Store audio library.

The two systems

Modern audio graph (recommended for new work)

Modular instances that mirror real-world audio devices. Each object produces, consumes, modifies, or carries an audio stream. You wire them together with Wire instances (SourceInstanceTargetInstance).

ObjectRoleReal-world analog
AudioPlayerProduces a stream from an audio asset IDA audio file player
AudioEmitterEmits a stream into the 3D environment (parent position = emission point)A speaker in the world
AudioListenerPicks up streams from the environment (parent = camera or character)A microphone in the world
AudioDeviceOutputPlays a stream to the player's physical speaker/headphonesThe player's hardware output
AudioDeviceInputCaptures audio from the player's physical microphoneThe player's hardware mic
AudioTextToSpeechConverts text to audio with an artificial voiceA TTS engine
AudioSpeechToTextConverts spoken audio to textA transcription engine
WireCarries a stream from SourceInstance to TargetInstanceAn audio cable

Effects (all "modify" category): AudioEqualizer, AudioCompressor, AudioReverb, AudioChorus, AudioDistortion, AudioEcho, AudioFlanger, AudioPitchShifter, AudioTremolo, AudioFader, AudioAnalyzer. See references/audio-effects.md.

Legacy Sound system (still works, discouraged)

Sound parented to a BasePart or Attachment emits from that position with built-in Doppler and distance rolloff (RollOffMode, RollOffMaxDistance, RollOffMinDistance, EmitterSize). A "global" Sound (not parented to a part/attachment) plays at constant volume everywhere. SoundGroup controls group volume and effects; SoundEffect subclasses (EqualizerSoundEffect, ReverbSoundEffect, etc.) apply per-group effects. SoundService exposes global properties (AmbientReverb, DistanceFactor, DopplerScale, RespectFilteringEnabled) that affect Sound playback.

SoundService.AmbientReverb and the Doppler/distance properties affect only legacy Sound, not the audio graph. The graph has its own effect objects and per-emitter DistanceAttenuation curves.

Decision tree: which system?

  • New experience, greenfield audio → audio graph. It's the path Roblox is investing in (TTS, STT, acoustic simulation, robust routing).
  • Simple 2D SFX or music with no routing/effectsSound is acceptable and simpler. Don't rewrite working legacy code just to migrate.
  • 3D positional audio with custom attenuation curves → audio graph (AudioEmitter.DistanceAttenuation).
  • Multiple sources through one effect (e.g. all gunfire through one compressor) → audio graph (one effect, many players wired in).
  • Text-to-speech or speech-to-text → audio graph (only the graph has AudioTextToSpeech / AudioSpeechToText).
  • Voice chat / spatial voiceVoiceChatService (separate from in-experience audio; uses AudioDeviceInput under the hood when UseAudioApi is enabled).
  • Acoustic simulation (occlusion, diffraction, reverb) → audio graph with SoundService.AcousticSimulationEnabled = true and per-instance AcousticSimulationEnabled on emitters/listeners.
  • Quick prototype / one-shot UI click soundSound is fine.

See references/audio-graph-vs-sound.md for a side-by-side property map and migration notes.

2D audio (non-directional)

Same volume everywhere. Requires: AudioPlayerWireAudioDeviceOutput, all parented under SoundService.

--!strict
local SoundService = game:GetService("SoundService")

local player = Instance.new("AudioPlayer")
player.AssetId = "rbxassetid://YOUR_AUDIO_ID"
player.Looping = true
player.Volume = 1
player.Parent = SoundService

local output = Instance.new("AudioDeviceOutput")
output.Parent = SoundService

local wire = Instance.new("Wire")
wire.SourceInstance = player
wire.TargetInstance = output
wire.Parent = SoundService

player:Play()

3D audio (positional)

Volume changes with the listener's distance to the emitter. Requires six objects: AudioPlayerWireAudioEmitter (parented to the 3D part), and AudioListenerWireAudioDeviceOutput (under SoundService). Set SoundService.ListenerLocation to Character or Camera (the engine auto-creates the AudioDeviceOutput under SoundService at runtime when you do).

--!strict
local SoundService = game:GetService("SoundService")
SoundService.ListenerLocation = Enum.ListenerLocation.Camera -- or Character

-- On the 3D part that should emit audio:
local part = workspace:WaitForChild("NoisyPart")
local player = Instance.new("AudioPlayer")
player.AssetId = "rbxassetid://YOUR_AUDIO_ID"
player.Looping = true
player.Parent = part

local emitter = Instance.new("AudioEmitter")
-- DistanceAttenuation is a NumberSequence: x = distance (studs), y = volume (0..1)
emitter.DistanceAttenuation = NumberSequence.new({
    NumberSequenceKeypoint.new(0, 1),    -- full volume at 0 studs
    NumberSequenceKeypoint.new(50, 0.5), -- half volume at 50 studs
    NumberSequenceKeypoint.new(70, 0),   -- silent at 70 studs
})
emitter.Parent = part

local wire = Instance.new("Wire")
wire.SourceInstance = player
wire.TargetInstance = emitter
wire.Parent = part

player:Play()

The emitter's parent position determines where audio emits from. AudioEmitter ignores its own orientation; rotate the parent part/attachment to steer emission.

Listener location

SoundService.ListenerLocation (a ListenerLocation enum) controls where the AudioListener is auto-created:

  • Default — camera in experiences with voice chat.
  • None — no auto-listener; create one via script.
  • Character — parented to the local player's character (Humanoid.RootPart).
  • Camera — parented to workspace.CurrentCamera.

When set to Character or Camera, the engine auto-creates an AudioDeviceOutput under SoundService at runtime. The AudioListener picks up audio from AudioEmitters based on distance and the emitter's DistanceAttenuation curve.

Triggering audio from scripts

local audio = script.Parent :: AudioPlayer
someEvent:Connect(function()
    audio:Play()
end)

AudioPlayer:Play(), :Pause(), :Stop(), :SeekTime(...). AudioPlayer.TimeVolume is tweenable — see references/audio-effects.md for tweening volume and effect parameters.

Preloading audio

Preload prominent audio assets before they're needed (loading screen, round start) to avoid first-play hitches on lower-end devices:

--!strict
local ContentProvider = game:GetService("ContentProvider")
local audioPlayer = workspace:WaitForChild("MusicPlayer") :: AudioPlayer
ContentProvider:PreloadAsync({ audioPlayer })

For the legacy Sound system, preload the Sound instance the same way.

Performance limits

  • Concurrent voices (simultaneously playing audio streams) are capped; the cap varies by device. Mobile is significantly lower than desktop.
  • Effects cost CPU per active stream routed through them. Reverb and acoustic simulation are the heaviest.
  • Acoustic simulation (SoundService.AcousticSimulationEnabled) adds per-emitter occlusion/diffraction/reverb cost; disable on low-end clients or when not needed.
  • Mobile throttling: the engine may drop or degrade audio effects on low-memory clients (e.g. flipbooks were dropped on older phones; the same applies to some audio effects). Test at low quality levels.
  • AudioAnalyzer is for inspection only; don't chain it into audible paths unnecessarily.

Profile audio with the MicroProfiler (audio appears under worker threads) and the Developer Console Memory tab.

Script context (client vs server)

  • Playback of AudioPlayer, Sound, and effects is client-side — each client plays its own audio. The server does not mix audio for clients.
  • Replication: AudioPlayer state (playing/paused/stopped) replicates from server to clients if the instance is in a replicated location, but per-client volume/effects are local. For one-shot SFX, prefer client-authoritative emission: server signals "this event happened" via RemoteEvent, each affected client plays the sound locally. This avoids replicating per-burst timing and respects each client's quality settings (same pattern as VFX — see roblox-vfx skill).
  • Music/ambience that should be synchronized across all clients can be server-driven (the AudioPlayer lives in ReplicatedStorage or SoundService and the server calls :Play()), but be aware each client still renders locally and may drift.
  • AudioDeviceInput (microphone) is client-only — it captures the local player's mic. Pair with VoiceChatService for spatial voice.
  • Never trust client audio state for gameplay. A client claiming "I played the reload sound" tells you nothing authoritative; validate gameplay effects on the server (see roblox-networking).

Audio asset permissions

  • Audio assets uploaded before the 2022 audio privacy changes may be private or have restricted use. Assets you upload to your own experience are usable by that experience.
  • The Creator Store has a library of free-to-use audio assets — these are safe to reference by asset ID in any experience.
  • Audio uploaded by other creators may be unusable in your experience unless they've marked it for public use. If you reference a third-party audio asset ID and it doesn't play, permissions are the usual cause.
  • For new audio, upload through the Creator Dashboard's asset manager or the Open Cloud Assets API (see roblox-open-cloud skill for programmatic upload).

Text-to-speech (TTS)

AudioTextToSpeech converts text (≤300 chars per request) to audio with an artificial voice (VoiceId 1–11, plus locale-specific voices like 101/Spanish, 201/German, etc.). Wire it like an AudioPlayer: for 2D, AudioTextToSpeechWireAudioDeviceOutput; for 3D, AudioTextToSpeechWireAudioEmitter (plus the listener→output wire). Set Text, VoiceId, Volume on the AudioTextToSpeech. All text must comply with Roblox Community Standards and Terms of Use.

Use cases: accessibility (reading UI text aloud), NPC voiceover without recorded audio, dynamic announcements.

Speech-to-text (STT)

AudioSpeechToText converts speech captured by AudioDeviceInput into text. Requires VoiceChatService.UseAudioApi = Enabled. Wire: AudioDeviceInputWireAudioSpeechToText. Set audioDeviceInput.Player = Players.LocalPlayer at runtime to target the local player's mic. Roblox auto-detects the spoken language (17 supported: Arabic, Chinese Simplified/Traditional, English, French, German, Indonesian, Italian, Japanese, Korean, Polish, Portuguese, Spanish, Russian, Turkish, Thai, Vietnamese).

To use STT without broadcasting voice to other players, disable VoiceChatService.EnableDefaultVoice. All audio for AudioSpeechToText must comply with Community Standards and Terms of Use.

Best practices

  • Preload prominent audio (music, common SFX) during loading. One-shot UI sounds can lazy-load.
  • Loop ambient/music with Looping = true (graph) or Looped = true (legacy). For finite loops N times, use the DidLoop event (legacy Sound) or count plays on the graph.
  • Fade in/out by tweening AudioPlayer.Volume (graph) or Sound.Volume (legacy). AudioFader is the graph-native way to control multiple streams' volume at once.
  • Music vs SFX: route music and SFX through separate AudioFader or SoundGroup so you can mute music independently and apply ducking (SFX ducks music via AudioCompressor sidechain).
  • 3D vs 2D: if the sound has a world position, use 3D (AudioEmitter); if it's UI/global, use 2D (AudioDeviceOutput direct).
  • Accessibility: offer TTS for important text, provide subtitle/caption options for VO, and never make audio the only cue for gameplay-critical info.
  • Mobile: test at low quality. The engine may drop effects; design so the experience still works without them.
  • Concurrency: pool AudioPlayer/Sound instances for frequent one-shots rather than creating/destroying per shot.

Common mistakes this skill prevents

  • Using Sound/SoundGroup/SoundEffect for new work when the graph is the recommended path.
  • Parenting an AudioEmitter to SoundService (it must be parented to a 3D part/attachment for 3D audio).
  • Forgetting the Wire (audio won't flow from player to output/emitter).
  • Expecting SoundService.AmbientReverb to affect the audio graph (it only affects legacy Sound).
  • Setting DistanceAttenuation as a single number instead of a NumberSequence (it's a curve, not a scalar).
  • Trusting client audio state for gameplay (reload sounds, hit sounds) instead of server validation.
  • Not preloading, causing first-play hitches on mobile.
  • Hardcoding asset IDs for third-party audio that may be permission-restricted.

Scripts

  • scripts/AudioBus.lua — a small music/SFX bus helper using AudioFader to control group volume and duck music when SFX play. Adapt for your mix.

How to proceed

  1. Pick the system: graph for new/complex work, Sound for simple/legacy.
  2. Lay out your buses (music, SFX, VO) and route through AudioFader or SoundGroup.
  3. Place 3D emitters on the parts that should make sound; set DistanceAttenuation per emitter.
  4. Add effects where they add value (reverb in caves, muffling underwater, ducking).
  5. Preload, then trigger from events (animation markers, UI, gameplay).
  6. Profile concurrent voices and effect cost on the lowest target device.
  7. Verify asset permissions for any third-party audio.
<!-- catalog:references:start -->

Reference index

<!-- catalog:references:end -->

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.