threejs-impl-audio について
Three.js の 3D シーンに音声を実装するためのリファレンススキルです。通常再生、空間音声、ファイル読み込み、周波数解析に加え、ブラウザーでのユーザー操作要件も説明します。
主な機能
- 01オーディオリスナーと再生の設定
- 02通常音声と 3D 空間音声
- 03音声ファイルの読み込みと再生制御
- 04ブラウザーの音声操作要件
- 05可視化向けの周波数解析
活用シーン
- 01BGM や UI 効果音の追加
- 02距離に応じたシーン内音声の配置
- 03音声周波数データの可視化
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ impertio-studio/ three.js-claude-skill-package --skill threejs-impl-audioインストール後、Claude Code で/threejs-impl-audioを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/anti-patterns.mdexamples.mdmethods.md詳細
threejs-impl-audio
クイックリファレンス
クラス階層
EventDispatcher
└── Object3D
├── AudioListener (receiver — attach to camera)
├── Audio (non-positional — background music, UI sounds)
└── PositionalAudio (3D spatial — attached to scene objects)
サポートクラス:
AudioLoader— オーディオファイルをAudioBufferに読み込みますAudioAnalyser— ビジュアライゼーション用のリアルタイム周波数分析を行います
アーキテクチャの概要
| コンポーネント | 役割 | 取り付け先 |
|---|---|---|
AudioListener | 仮想の耳(Web Audio APIの出力先) | カメラ(必須) |
Audio | 非位置依存のサウンド(どこでも同じ音量) | 任意のObject3Dまたはシーン |
PositionalAudio | 3D空間サウンド(音量は距離に応じて変化) | シーン内のMeshまたはObject3D |
AudioLoader | オーディオファイルの非同期ローダー | 該当なし(ユーティリティ) |
AudioAnalyser | FFT周波数データの抽出器 | Audioインスタンスをラップ |
重要な警告
ユーザー操作後にAudioContextが再開されていることを確認せずに、絶対にsound.play()を呼び出さないでください。最新のブラウザーでは、ユーザーのジェスチャー(クリック、タップ、キー入力)が発生するまで、AudioContextは必ず一時停止状態になります。
シーンごとに複数のAudioListenerを作成することは絶対に避けてください。複数のリスナーを使用すると、空間化の動作が未定義になります。
ユーザー操作なしで再生されることを期待して、autoplay = trueを設定することは絶対に避けてください。ブラウザーは再生を必ずブロックし、そのことを通知しません。
AudioListenerは必ずカメラに取り付けてください。別のオブジェクトに取り付けると、空間オーディオの計算で誤った基準位置が使われます。
オーディオを再生する前に、ユーザー操作のハンドラー内でlistener.context.resume()を必ず呼び出してください。
AudioLoader.load()のonErrorコールバックを必ず処理してください。エラー処理がない場合、オーディオファイルが見つからなくてもエラーは通知されません。
AudioListenerのセットアップ
AudioListenerはシーンの仮想マイクです。Web Audio APIのAudioContextとAudioDestinationNodeをラップします。
import * as THREE from 'three';
const listener = new THREE.AudioListener();
camera.add( listener ); // ALWAYS add to camera
マスターボリュームの制御
listener.setMasterVolume( 0.8 ); // range [0, 1]
const vol = listener.getMasterVolume(); // returns 0.8
グローバルオーディオフィルター
const filter = listener.context.createBiquadFilter();
filter.type = 'lowpass';
filter.frequency.value = 1000;
listener.setFilter( filter );
// Later: listener.removeFilter();
Audio(非位置依存)
バックグラウンドミュージック、環境音、UIのフィードバック音にはAudioを使用します。リスナーの位置にかかわらず、音量は一定です。
読み込みと再生
const sound = new THREE.Audio( listener );
const audioLoader = new THREE.AudioLoader();
audioLoader.load( 'music.mp3', ( buffer ) => {
sound.setBuffer( buffer );
sound.setLoop( true );
sound.setVolume( 0.5 );
// Do NOT call sound.play() here — wait for user interaction
});
自動再生ポリシーへの準拠(必須)
document.addEventListener( 'click', () => {
if ( listener.context.state === 'suspended' ) {
listener.context.resume();
}
if ( !sound.isPlaying ) {
sound.play();
}
}, { once: true } );
再生の制御
sound.play(); // start playback
sound.pause(); // pause (resume with play())
sound.stop(); // stop and reset to beginning
sound.setPlaybackRate( 1.5 ); // 1.5x speed
sound.setDetune( -100 ); // pitch down 1 semitone (100 cents)
代替ソース
// HTML5 media element (for streaming large files)
const audioEl = new Audio( 'long-track.mp3' );
sound.setMediaElementSource( audioEl );
// Microphone input
navigator.mediaDevices.getUserMedia( { audio: true } ).then( ( stream ) => {
sound.setMediaStreamSource( stream );
});
PositionalAudio(3D空間オーディオ)
シーン内の位置に存在するサウンドにはPositionalAudioを使用します。音量とステレオパンニングは、リスナーとの距離や向きに応じて変化します。
基本設定
const positionalSound = new THREE.PositionalAudio( listener );
audioLoader.load( 'engine.ogg', ( buffer ) => {
positionalSound.setBuffer( buffer );
positionalSound.setRefDistance( 20 );
positionalSound.setRolloffFactor( 1 );
positionalSound.setDistanceModel( 'inverse' );
positionalSound.setLoop( true );
positionalSound.setVolume( 0.5 );
});
mesh.add( positionalSound ); // sound position follows the mesh
距離モデルの選択ツリー
| モデル | 使用する場面 | 動作 |
|---|---|---|
'inverse'(デフォルト) | 現実的な環境 | 徐々に減衰しますが、音量がゼロになることはありません |
'linear' | 制御された範囲(例:部屋単位) | maxDistanceで音量がゼロになります |
'exponential' | 近距離と遠距離で大きな差をつける場合 | 急激に減衰します |
パラメーターの選び方:
refDistance— 音量が100%になる距離です。シーンの単位で「快適に聴こえる範囲」に設定します。一般的な値:1~20。maxDistance—'linear'モデルの場合にのみ関係します。'inverse'と'exponential'では無視されます。rolloffFactor— 音量が低下する速さです。'inverse'では、1が現実的な設定です。'linear'では、1が全範囲を使う設定です。値を大きくすると減衰が速くなります。
指向性オーディオコーン
positionalSound.setDirectionalCone( 180, 360, 0.1 );
// coneInnerAngle: 180° — full volume zone
// coneOuterAngle: 360° — transition zone
// coneOuterGain: 0.1 — volume outside outer cone (10%)
AudioLoader
オーディオファイルの読み込みには、必ずAudioLoaderを使用してください。コールバック経由でAudioBufferを返します。
const loader = new THREE.AudioLoader();
loader.load(
'sound.ogg',
( buffer ) => { sound.setBuffer( buffer ); }, // onLoad
( xhr ) => { console.log( (xhr.loaded / xhr.total * 100) + '% loaded' ); }, // onProgress
( err ) => { console.error( 'Audio load failed:', err ); } // onError — ALWAYS handle
);
対応フォーマット: MP3、OGG、WAV、AAC。OGGは圧縮率と音質のバランスに最も優れていますが、Safariではサポートされていません。クロスブラウザー互換性を確保するため、MP3も必ず用意してください。
AudioAnalyser
Web Audio APIのAnalyserNodeをラップし、リアルタイムの周波数ビジュアライゼーションを行います。
const analyser = new THREE.AudioAnalyser( sound, 256 );
// fftSize MUST be a power of 2: 32, 64, 128, 256, 512, 1024, 2048
function animate() {
requestAnimationFrame( animate );
const data = analyser.getFrequencyData(); // Uint8Array, length = fftSize / 2
const avg = analyser.getAverageFrequency(); // number (0-255)
// Drive visuals from audio data
mesh.scale.y = 1 + avg / 128;
renderer.render( scene, camera );
}
周波数データの詳細
getFrequencyData()は、fftSize / 2個の要素を持つUint8Arrayを返します- 各要素の値は
0から255の範囲です(デシベル振幅) - インデックス
0は最も低い周波数、最後のインデックスは最も高い周波数です getAverageFrequency()はすべてのビンの算術平均を返します
統合チェックリスト
AudioListenerを1つ作成し、カメラに追加します- リスナーを指定して
AudioまたはPositionalAudioを作成します AudioLoaderで音声を読み込みます- バッファー、音量、ループ、距離のプロパティを設定します
AudioContextを再開するユーザー操作のハンドラーを追加します- ユーザー操作の後にのみ
play()を呼び出します - 空間オーディオの場合:
PositionalAudioを対象のメッシュの子として追加します
参考リンク
- references/methods.md -- AudioListener、Audio、PositionalAudio、AudioLoader、AudioAnalyser の完全な API シグネチャー
- references/examples.md -- 一般的なオーディオのシナリオで使えるコード例
- references/anti-patterns.md -- Three.js オーディオで避けるべきこと