Claude-skill-registry dev-assets-audio-loading

Audio loading patterns for R3F/Three.js. Use when adding sound effects.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dev-assets-audio-loading" ~/.claude/skills/majiayu000-claude-skill-registry-dev-assets-audio-loading && rm -rf "$T"
manifest: skills/data/dev-assets-audio-loading/SKILL.md
source content

Audio Loading

Sound and music loading for React Three Fiber.

When to Use

Use when:

  • Adding sound effects
  • Playing background music
  • Positional audio for 3D scenes

Quick Start

import { useRef, useEffect } from 'react';
import { PositionalAudio } from '@react-three/drei';

function SoundEffect({ url, volume = 1 }) {
  const audioRef = useRef();

  useEffect(() => {
    if (!audioRef.current) return;

    const audio = audioRef.current;
    audio.load(url);
    audio.setVolume(volume);
    audio.setRefDistance(1);
    audio.setMaxDistance(20);

    return () => {
      audio.stop();
    };
  }, [url, volume]);

  return (
    <PositionalAudio
      ref={audioRef}
      position={[0, 0, 0]}
      autoplay={false}
    />
  );
}

HTML Audio (Simple)

function SimpleSound({ url, volume = 1 }) {
  const audioRef = useRef<HTMLAudioElement>(null);

  useEffect(() => {
    const audio = new Audio(url);
    audio.volume = volume;
    audio.loop = false;

    audio.onended = () => {
      audio.currentTime = 0;
    };

    audio.play().catch(err => {
      console.error('Audio play error:', err);
    });

    return () => {
      audio.pause();
      audio.src = '';
    };
  }, [url, volume]);

  return null;
}

Three.js Positional Audio

import { PositionalAudio } from '@react-three/drei';

function PositionalSound() {
  return (
    <PositionalAudio
      url="/sounds/footstep.ogg"
      distance={5}
      loop={false}
      autoplay={false}
    />
  );
}

Audio Listener

import { AudioListener } from '@react-three/drei';

function Scene() {
  return (
    <>
      <AudioListener />
      <PositionalAudio url="/sounds/explosion.ogg" position={[0, 0, 0]} />
    </>
  );
}

Audio Manager

class AudioManager {
  private sounds: Map<string, HTMLAudioElement> = new Map();
  private volume: number = 1;

  preload(url: string, id: string) {
    const audio = new Audio(url);
    audio.preload = 'auto';
    this.sounds.set(id, audio);
  }

  play(id: string) {
    const audio = this.sounds.get(id);
    if (audio) {
      audio.currentTime = 0;
      audio.play();
    }
  }

  stop(id: string) {
    const audio = this.sounds.get(id);
    if (audio) {
      audio.pause();
      audio.currentTime = 0;
    }
  }

  setVolume(volume: number) {
    this.volume = volume;
    this.sounds.forEach(audio => {
      audio.volume = volume;
    });
  }
}

Audio Formats

FormatBrowser SupportUse Case
MP3UniversalMusic, long sounds
OGGGoodSound effects
AACExcellent (Apple)Mobile
WAVPoorShort effects (uncompressed)

Common Mistakes

❌ Wrong✅ Right
Not cleaning up audioAlways pause/cleanup in useEffect
Using uncompressed WAVUse MP3/OGG for production
No volume controlAdd volume slider
Loading on every playPreload common sounds

Mobile Considerations

// iOS requires user interaction to play audio
const [audioEnabled, setAudioEnabled] = useState(false);

function EnableAudioButton() {
  const enable = () => {
    // Play silent sound to unlock audio
    const audio = new Audio('/sounds/silent.mp3');
    audio.play();
    setAudioEnabled(true);
  };

  return <button onClick={enable}>Enable Audio</button>;
}

Reference