@xrift/world-components 0.21.7 → 0.21.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"useWebAudioVolume.d.ts","sourceRoot":"","sources":["../../src/hooks/useWebAudioVolume.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,cAAc,gBAAgB,GAAG,gBAAgB,GAAG,IAAI,EACxD,QAAQ,MAAM,SA6Gf,CAAA"}
1
+ {"version":3,"file":"useWebAudioVolume.d.ts","sourceRoot":"","sources":["../../src/hooks/useWebAudioVolume.ts"],"names":[],"mappings":"AAYA;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,cAAc,gBAAgB,GAAG,gBAAgB,GAAG,IAAI,EACxD,QAAQ,MAAM,SAgHf,CAAA"}
@@ -1,4 +1,7 @@
1
1
  import { useEffect, useRef } from 'react';
2
+ // グローバルなWeakMapで各MediaElementの接続を追跡
3
+ // 一度createMediaElementSourceで接続したMediaElementは他のAudioContextに再接続できないため
4
+ const audioConnections = new WeakMap();
2
5
  /**
3
6
  * Web Audio API を使用して HTMLMediaElement(video/audio)の音量を制御するフック
4
7
  * iOSでは HTMLMediaElement.volume が読み取り専用のため、GainNode を使用して音量を制御する
@@ -7,48 +10,53 @@ import { useEffect, useRef } from 'react';
7
10
  * @param volume - 音量(0〜1)
8
11
  */
9
12
  export const useWebAudioVolume = (mediaElement, volume) => {
10
- const audioContextRef = useRef(null);
11
13
  const gainNodeRef = useRef(null);
12
- const sourceRef = useRef(null);
13
- const connectedElementRef = useRef(null);
14
14
  // AudioContext のセットアップと接続
15
15
  useEffect(() => {
16
- if (!mediaElement)
17
- return;
18
- // 同じ要素が既に接続されている場合はスキップ
19
- // 一度 createMediaElementSource で接続した要素は再接続できないため
20
- if (connectedElementRef.current === mediaElement) {
16
+ if (!mediaElement) {
17
+ gainNodeRef.current = null;
21
18
  return;
22
19
  }
23
- // 新しい要素の場合、古い AudioContext をクリーンアップ
24
- if (audioContextRef.current) {
25
- audioContextRef.current.close().catch(() => {
26
- // クローズ失敗は無視
27
- });
28
- audioContextRef.current = null;
29
- gainNodeRef.current = null;
30
- sourceRef.current = null;
20
+ // 既存の接続があれば再利用
21
+ const existingConnection = audioConnections.get(mediaElement);
22
+ if (existingConnection) {
23
+ gainNodeRef.current = existingConnection.gainNode;
24
+ // suspended状態なら resume
25
+ if (existingConnection.audioContext.state === 'suspended') {
26
+ existingConnection.audioContext.resume().catch(() => {
27
+ // resume 失敗は無視
28
+ });
29
+ }
30
+ return;
31
31
  }
32
32
  const setupAudioContext = () => {
33
+ // 既に接続済みかもう一度確認
34
+ if (audioConnections.has(mediaElement)) {
35
+ const connection = audioConnections.get(mediaElement);
36
+ gainNodeRef.current = connection.gainNode;
37
+ return;
38
+ }
33
39
  try {
34
40
  // Web Audio API を使用(iOS対応)
35
41
  const AudioContextClass = window.AudioContext ||
36
42
  window
37
43
  .webkitAudioContext;
38
44
  const audioContext = new AudioContextClass();
39
- audioContextRef.current = audioContext;
40
45
  // GainNode で音量制御
41
46
  const gainNode = audioContext.createGain();
42
47
  gainNode.gain.value = volume;
43
48
  gainNodeRef.current = gainNode;
44
49
  // MediaElement をソースとして接続
45
50
  const source = audioContext.createMediaElementSource(mediaElement);
46
- sourceRef.current = source;
47
51
  // 接続: source -> gain -> destination
48
52
  source.connect(gainNode);
49
53
  gainNode.connect(audioContext.destination);
50
- // 接続済みの要素を記録
51
- connectedElementRef.current = mediaElement;
54
+ // 接続情報をWeakMapに保存
55
+ audioConnections.set(mediaElement, {
56
+ audioContext,
57
+ gainNode,
58
+ source,
59
+ });
52
60
  // AudioContext が suspended の場合は resume
53
61
  if (audioContext.state === 'suspended') {
54
62
  audioContext.resume().catch(() => {
@@ -57,16 +65,26 @@ export const useWebAudioVolume = (mediaElement, volume) => {
57
65
  }
58
66
  }
59
67
  catch (error) {
68
+ // 既に接続済みの場合のエラーは無視
69
+ if (error instanceof DOMException && error.name === 'InvalidStateError') {
70
+ // 既存の接続を探す(念のため)
71
+ const connection = audioConnections.get(mediaElement);
72
+ if (connection) {
73
+ gainNodeRef.current = connection.gainNode;
74
+ }
75
+ return;
76
+ }
60
77
  console.error('Failed to setup Web Audio API:', error);
61
78
  }
62
79
  };
63
80
  // ユーザーインタラクション後に AudioContext を開始する必要がある場合がある
64
81
  const handleInteraction = () => {
65
- if (!audioContextRef.current) {
82
+ const connection = audioConnections.get(mediaElement);
83
+ if (!connection) {
66
84
  setupAudioContext();
67
85
  }
68
- else if (audioContextRef.current.state === 'suspended') {
69
- audioContextRef.current.resume().catch(() => {
86
+ else if (connection.audioContext.state === 'suspended') {
87
+ connection.audioContext.resume().catch(() => {
70
88
  // resume 失敗は無視
71
89
  });
72
90
  }
@@ -79,6 +97,8 @@ export const useWebAudioVolume = (mediaElement, volume) => {
79
97
  return () => {
80
98
  document.removeEventListener('click', handleInteraction);
81
99
  document.removeEventListener('touchstart', handleInteraction);
100
+ // 注意: AudioContextはクローズしない(MediaElementが再利用される可能性があるため)
101
+ // WeakMapを使用しているので、MediaElementがGCされれば自動的にクリーンアップされる
82
102
  };
83
103
  }, [mediaElement, volume]);
84
104
  // 音量変更時の処理
@@ -87,19 +107,5 @@ export const useWebAudioVolume = (mediaElement, volume) => {
87
107
  gainNodeRef.current.gain.value = Math.max(0, Math.min(1, volume));
88
108
  }
89
109
  }, [volume]);
90
- // クリーンアップ
91
- useEffect(() => {
92
- return () => {
93
- if (audioContextRef.current) {
94
- audioContextRef.current.close().catch(() => {
95
- // クローズ失敗は無視
96
- });
97
- audioContextRef.current = null;
98
- gainNodeRef.current = null;
99
- sourceRef.current = null;
100
- connectedElementRef.current = null;
101
- }
102
- };
103
- }, []);
104
110
  };
105
111
  //# sourceMappingURL=useWebAudioVolume.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useWebAudioVolume.js","sourceRoot":"","sources":["../../src/hooks/useWebAudioVolume.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useWebAudioVolume.js","sourceRoot":"","sources":["../../src/hooks/useWebAudioVolume.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xrift/world-components",
3
- "version": "0.21.7",
3
+ "version": "0.21.8",
4
4
  "description": "Shared components and utilities for Xrift worlds",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",