roblox-audio — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited roblox-audio (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Official sources (always check these for the latest):
Sound)AudioPlayer, AudioEmitter, AudioListener, AudioDeviceOutput, AudioDeviceInput, AudioTextToSpeech, AudioSpeechToText, Wire, AudioEqualizer, AudioCompressor, AudioReverb, AudioChorus, AudioDistortion, AudioEcho, AudioFlanger, AudioPitchShifter, AudioTremolo, AudioFader, AudioAnalyzerThis 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:
Activate when:
Sound code to the new audio graph.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 (SourceInstance → TargetInstance).
| Object | Role | Real-world analog |
|---|---|---|
AudioPlayer | Produces a stream from an audio asset ID | A audio file player |
AudioEmitter | Emits a stream into the 3D environment (parent position = emission point) | A speaker in the world |
AudioListener | Picks up streams from the environment (parent = camera or character) | A microphone in the world |
AudioDeviceOutput | Plays a stream to the player's physical speaker/headphones | The player's hardware output |
AudioDeviceInput | Captures audio from the player's physical microphone | The player's hardware mic |
AudioTextToSpeech | Converts text to audio with an artificial voice | A TTS engine |
AudioSpeechToText | Converts spoken audio to text | A transcription engine |
Wire | Carries a stream from SourceInstance to TargetInstance | An audio cable |
Effects (all "modify" category): AudioEqualizer, AudioCompressor, AudioReverb, AudioChorus, AudioDistortion, AudioEcho, AudioFlanger, AudioPitchShifter, AudioTremolo, AudioFader, AudioAnalyzer. See references/audio-effects.md.
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.
Sound is acceptable and simpler. Don't rewrite working legacy code just to migrate.AudioEmitter.DistanceAttenuation).AudioTextToSpeech / AudioSpeechToText).VoiceChatService (separate from in-experience audio; uses AudioDeviceInput under the hood when UseAudioApi is enabled).SoundService.AcousticSimulationEnabled = true and per-instance AcousticSimulationEnabled on emitters/listeners.Sound is fine.See references/audio-graph-vs-sound.md for a side-by-side property map and migration notes.
Same volume everywhere. Requires: AudioPlayer → Wire → AudioDeviceOutput, 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()Volume changes with the listener's distance to the emitter. Requires six objects: AudioPlayer → Wire → AudioEmitter (parented to the 3D part), and AudioListener → Wire → AudioDeviceOutput (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.
SoundService.ListenerLocation (a ListenerLocation enum) controls where the AudioListener is auto-created:
Humanoid.RootPart).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.
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.
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.
SoundService.AcousticSimulationEnabled) adds per-emitter occlusion/diffraction/reverb cost; disable on low-end clients or when not needed.Profile audio with the MicroProfiler (audio appears under worker threads) and the Developer Console Memory tab.
AudioPlayer, Sound, and effects is client-side — each client plays its own audio. The server does not mix audio for clients.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).AudioPlayer lives in ReplicatedStorage or SoundService and the server calls :Play()), but be aware each client still renders locally and may drift.VoiceChatService for spatial voice.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, AudioTextToSpeech → Wire → AudioDeviceOutput; for 3D, AudioTextToSpeech → Wire → AudioEmitter (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.
AudioSpeechToText converts speech captured by AudioDeviceInput into text. Requires VoiceChatService.UseAudioApi = Enabled. Wire: AudioDeviceInput → Wire → AudioSpeechToText. 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.
Looping = true (graph) or Looped = true (legacy). For finite loops N times, use the DidLoop event (legacy Sound) or count plays on the graph.AudioPlayer.Volume (graph) or Sound.Volume (legacy). AudioFader is the graph-native way to control multiple streams' volume at once.AudioFader or SoundGroup so you can mute music independently and apply ducking (SFX ducks music via AudioCompressor sidechain).AudioEmitter); if it's UI/global, use 2D (AudioDeviceOutput direct).AudioPlayer/Sound instances for frequent one-shots rather than creating/destroying per shot.Sound/SoundGroup/SoundEffect for new work when the graph is the recommended path.AudioEmitter to SoundService (it must be parented to a 3D part/attachment for 3D audio).Wire (audio won't flow from player to output/emitter).SoundService.AmbientReverb to affect the audio graph (it only affects legacy Sound).DistanceAttenuation as a single number instead of a NumberSequence (it's a curve, not a scalar).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.Sound for simple/legacy.AudioFader or SoundGroup.DistanceAttenuation per emitter.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.