@djangocfg/ui-nextjs 2.1.81 → 2.1.83

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.
Files changed (36) hide show
  1. package/package.json +4 -4
  2. package/src/tools/AudioPlayer/@refactoring3/00-IMPLEMENTATION-ROADMAP.md +1146 -0
  3. package/src/tools/AudioPlayer/@refactoring3/01-WAVESURFER-STREAMING-ANALYSIS.md +611 -0
  4. package/src/tools/AudioPlayer/@refactoring3/02-MEDIA-VIEWER-ANALYSIS.md +560 -0
  5. package/src/tools/AudioPlayer/@refactoring3/03-HYBRID-ARCHITECTURE-PROPOSAL.md +769 -0
  6. package/src/tools/AudioPlayer/@refactoring3/04-CRACKLING-ISSUE-DIAGNOSIS.md +373 -0
  7. package/src/tools/AudioPlayer/README.md +177 -205
  8. package/src/tools/AudioPlayer/components/AudioPlayer.tsx +9 -4
  9. package/src/tools/AudioPlayer/components/HybridAudioPlayer.tsx +251 -0
  10. package/src/tools/AudioPlayer/components/HybridSimplePlayer.tsx +291 -0
  11. package/src/tools/AudioPlayer/components/HybridWaveform.tsx +279 -0
  12. package/src/tools/AudioPlayer/components/SimpleAudioPlayer.tsx +16 -26
  13. package/src/tools/AudioPlayer/components/index.ts +6 -1
  14. package/src/tools/AudioPlayer/context/AudioProvider.tsx +16 -8
  15. package/src/tools/AudioPlayer/context/HybridAudioProvider.tsx +121 -0
  16. package/src/tools/AudioPlayer/context/index.ts +14 -2
  17. package/src/tools/AudioPlayer/hooks/index.ts +11 -0
  18. package/src/tools/AudioPlayer/hooks/useHybridAudio.ts +387 -0
  19. package/src/tools/AudioPlayer/hooks/useHybridAudioAnalysis.ts +95 -0
  20. package/src/tools/AudioPlayer/hooks/useSharedWebAudio.ts +6 -3
  21. package/src/tools/AudioPlayer/index.ts +31 -0
  22. package/src/tools/AudioPlayer/progressive/ProgressiveAudioPlayer.tsx +8 -0
  23. package/src/tools/ImageViewer/hooks/useImageLoading.ts +33 -9
  24. package/src/tools/VideoPlayer/hooks/useVideoPositionCache.ts +13 -6
  25. package/src/tools/VideoPlayer/providers/StreamProvider.tsx +38 -22
  26. package/src/tools/index.ts +22 -0
  27. package/src/tools/AudioPlayer/@refactoring/00-PLAN.md +0 -148
  28. package/src/tools/AudioPlayer/@refactoring/01-TYPES.md +0 -301
  29. package/src/tools/AudioPlayer/@refactoring/02-HOOKS.md +0 -281
  30. package/src/tools/AudioPlayer/@refactoring/03-CONTEXT.md +0 -328
  31. package/src/tools/AudioPlayer/@refactoring/04-COMPONENTS.md +0 -251
  32. package/src/tools/AudioPlayer/@refactoring/05-EFFECTS.md +0 -427
  33. package/src/tools/AudioPlayer/@refactoring/06-UTILS-AND-INDEX.md +0 -193
  34. package/src/tools/AudioPlayer/@refactoring/07-EXECUTION-CHECKLIST.md +0 -146
  35. package/src/tools/AudioPlayer/@refactoring2/ISSUE_ANALYSIS.md +0 -187
  36. package/src/tools/AudioPlayer/@refactoring2/PLAN.md +0 -372
@@ -1,264 +1,225 @@
1
1
  # AudioPlayer
2
2
 
3
- Audio player with waveform visualization, built on WaveSurfer.js.
3
+ Audio player library with multiple player implementations for different use cases.
4
4
 
5
- ## Features
5
+ ## Player Comparison
6
6
 
7
- - Waveform visualization with interactive seeking
8
- - Audio-reactive cover effects (glow, orbs, spotlight, mesh)
9
- - Real-time frequency equalizer
10
- - Keyboard shortcuts
11
- - Volume control with mute
12
- - Skip forward/backward
13
- - Playback speed control
7
+ | Feature | HybridSimplePlayer | SimpleAudioPlayer | ProgressiveAudioPlayer |
8
+ |---------|-------------------|-------------------|------------------------|
9
+ | **Recommended for** | Streaming, general use | Local files, full waveform | Large streaming files |
10
+ | **Audio Engine** | HTML5 `<audio>` | WaveSurfer.js | HTML5 `<audio>` |
11
+ | **Visualization** | Real-time frequency bars | Static waveform | Progressive waveform |
12
+ | **Reactive Effects** | ✅ Full support | ✅ Full support | ❌ No |
13
+ | **Streaming Support** | ✅ Native | ⚠️ Requires prefetch | ✅ Native |
14
+ | **Seek Any Position** | ✅ Yes | ⚠️ Limited by buffer | ✅ Yes |
15
+ | **No Crackling** | ✅ Guaranteed | ⚠️ Fixed in v2.1.82 | ✅ Yes |
16
+ | **Memory Usage** | Low | High (full file) | Low |
17
+
18
+ ---
14
19
 
15
20
  ## Quick Start (Recommended)
16
21
 
22
+ ### HybridSimplePlayer — Best for Most Cases
23
+
17
24
  ```tsx
18
- import { SimpleAudioPlayer } from '@djangocfg/ui-nextjs';
25
+ import { HybridSimplePlayer } from '@djangocfg/ui-nextjs';
19
26
 
20
27
  // Minimal
21
- <SimpleAudioPlayer src="https://example.com/audio.mp3" />
28
+ <HybridSimplePlayer src="https://example.com/audio.mp3" />
22
29
 
23
- // With metadata
24
- <SimpleAudioPlayer
30
+ // With metadata and reactive cover
31
+ <HybridSimplePlayer
25
32
  src={audioUrl}
26
33
  title="Track Title"
27
34
  artist="Artist Name"
28
35
  coverArt="/path/to/cover.jpg"
36
+ reactiveCover
37
+ variant="spotlight"
29
38
  />
30
39
 
31
40
  // Full customization
32
- <SimpleAudioPlayer
41
+ <HybridSimplePlayer
33
42
  src={audioUrl}
34
43
  title="Track Title"
35
44
  coverArt={coverUrl}
36
45
  showWaveform
37
- showEqualizer={false}
38
46
  reactiveCover
39
47
  variant="spotlight"
48
+ intensity="medium"
49
+ colorScheme="vibrant"
40
50
  layout="horizontal"
41
51
  />
42
52
  ```
43
53
 
44
- ### SimpleAudioPlayer Props
54
+ ### HybridSimplePlayer Props
45
55
 
46
56
  | Prop | Type | Default | Description |
47
57
  |------|------|---------|-------------|
48
58
  | `src` | `string` | required | Audio URL |
49
- | `prefetch` | `boolean` | `true` | Pre-fetch audio as blob (required for streaming URLs to enable seek) |
50
59
  | `title` | `string` | - | Track title |
51
60
  | `artist` | `string` | - | Artist name |
52
61
  | `coverArt` | `string \| ReactNode` | - | Cover image URL or custom element |
53
62
  | `coverSize` | `'sm' \| 'md' \| 'lg'` | `'md'` | Cover art size |
54
- | `showWaveform` | `boolean` | `true` | Show waveform |
55
- | `showEqualizer` | `boolean` | `false` | Show equalizer bars |
63
+ | `showWaveform` | `boolean` | `true` | Show frequency visualization |
64
+ | `waveformMode` | `'frequency' \| 'static'` | `'frequency'` | Visualization mode |
65
+ | `waveformHeight` | `number` | `64` | Waveform height in pixels |
56
66
  | `showTimer` | `boolean` | `true` | Show time display |
57
67
  | `showVolume` | `boolean` | `true` | Show volume control |
58
68
  | `showLoop` | `boolean` | `true` | Show loop/repeat button |
59
69
  | `reactiveCover` | `boolean` | `true` | Enable reactive effects |
60
- | `variant` | `VisualizationVariant` | - | Effect variant |
61
- | `intensity` | `EffectIntensity` | - | Effect intensity |
62
- | `colorScheme` | `EffectColorScheme` | - | Effect colors |
70
+ | `variant` | `VisualizationVariant` | `'spotlight'` | Effect variant |
71
+ | `intensity` | `EffectIntensity` | `'medium'` | Effect intensity |
72
+ | `colorScheme` | `EffectColorScheme` | `'primary'` | Effect colors |
63
73
  | `autoPlay` | `boolean` | `false` | Auto-play on load |
74
+ | `loop` | `boolean` | `false` | Loop playback |
64
75
  | `layout` | `'vertical' \| 'horizontal'` | `'vertical'` | Layout direction |
65
76
 
66
- > **Note:** The `prefetch` option is enabled by default. This fetches the entire audio file as a blob before loading into WaveSurfer, which is required for seeking to work correctly with streaming URLs. For very large files (> 50MB), consider using `prefetch={false}` and the Progressive player mode instead.
67
-
68
77
  ---
69
78
 
70
79
  ## Advanced Usage
71
80
 
72
- For full control, use `AudioProvider` + `AudioPlayer` directly:
81
+ ### Using HybridAudioProvider + HybridAudioPlayer
73
82
 
74
- ```tsx
75
- import { useRef } from 'react';
76
- import { AudioProvider, AudioPlayer } from '@djangocfg/ui-nextjs';
83
+ For full control over the hybrid player:
77
84
 
78
- function MyAudioPlayer({ audioUrl }: { audioUrl: string }) {
79
- const containerRef = useRef<HTMLDivElement>(null);
85
+ ```tsx
86
+ import { HybridAudioProvider, HybridAudioPlayer, useHybridAudioContext } from '@djangocfg/ui-nextjs';
80
87
 
88
+ function MyPlayer({ audioUrl }: { audioUrl: string }) {
81
89
  return (
82
- <AudioProvider
83
- source={{ uri: audioUrl }}
84
- containerRef={containerRef}
85
- >
86
- <AudioPlayer
87
- ref={containerRef}
90
+ <HybridAudioProvider src={audioUrl}>
91
+ <HybridAudioPlayer
88
92
  showControls
89
93
  showWaveform
90
94
  showTimer
91
95
  showVolume
92
96
  />
93
- </AudioProvider>
97
+ <CustomControls />
98
+ </HybridAudioProvider>
94
99
  );
95
100
  }
96
- ```
97
-
98
- ## Components
99
-
100
- ### AudioProvider
101
101
 
102
- Context provider for audio state. Wraps all audio components.
102
+ function CustomControls() {
103
+ const { state, controls, audioLevels } = useHybridAudioContext();
103
104
 
104
- ```tsx
105
- <AudioProvider
106
- source={{
107
- uri: 'https://example.com/audio.mp3',
108
- prefetch: true // Fetch as blob for seek support (default: false)
109
- }}
110
- containerRef={containerRef}
111
- autoPlay={false}
112
- waveformOptions={{
113
- waveColor: 'hsl(217 91% 60% / 0.3)',
114
- progressColor: 'hsl(217 91% 60%)',
115
- height: 64,
116
- barWidth: 3,
117
- barRadius: 3,
118
- barGap: 2,
119
- }}
120
- >
121
- {children}
122
- </AudioProvider>
105
+ return (
106
+ <div>
107
+ <p>Playing: {state.isPlaying ? 'Yes' : 'No'}</p>
108
+ <p>Bass level: {(audioLevels.bass * 100).toFixed(0)}%</p>
109
+ <button onClick={controls.togglePlay}>
110
+ {state.isPlaying ? 'Pause' : 'Play'}
111
+ </button>
112
+ </div>
113
+ );
114
+ }
123
115
  ```
124
116
 
125
- #### AudioSource Options
126
-
127
- | Prop | Type | Default | Description |
128
- |------|------|---------|-------------|
129
- | `uri` | `string` | required | Audio URL |
130
- | `prefetch` | `boolean` | `false` | Pre-fetch as blob (enables seek for streaming URLs) |
117
+ ### Hybrid Hooks
131
118
 
132
- ### AudioPlayer
133
-
134
- Main player component with waveform and controls.
135
-
136
- | Prop | Type | Default | Description |
137
- |------|------|---------|-------------|
138
- | `showControls` | `boolean` | `true` | Show playback controls |
139
- | `showWaveform` | `boolean` | `true` | Show waveform visualization |
140
- | `showEqualizer` | `boolean` | `false` | Show equalizer animation |
141
- | `showTimer` | `boolean` | `true` | Show time display |
142
- | `showVolume` | `boolean` | `true` | Show volume slider |
143
- | `className` | `string` | - | Additional CSS class |
144
-
145
- ### AudioEqualizer
119
+ #### useHybridAudioContext
146
120
 
147
- Real-time frequency visualizer with animated bars.
121
+ Full access to audio state, controls, and Web Audio API:
148
122
 
149
123
  ```tsx
150
- <AudioEqualizer
151
- barCount={24}
152
- height={48}
153
- gap={2}
154
- showPeaks
155
- barColor="hsl(217 91% 60%)"
156
- peakColor="hsl(217 91% 70%)"
157
- />
124
+ const {
125
+ state, // { isReady, isPlaying, currentTime, duration, volume, isMuted, isLooping, buffered }
126
+ controls, // { play, pause, togglePlay, seek, seekTo, skip, setVolume, toggleMute, toggleLoop, restart }
127
+ audioLevels, // { bass, mid, high, overall } - for reactive effects
128
+ webAudio, // { context, analyser, sourceNode } - for custom visualizations
129
+ audioRef, // React ref to HTMLAudioElement
130
+ } = useHybridAudioContext();
158
131
  ```
159
132
 
160
- ### AudioReactiveCover
161
-
162
- Album art wrapper with audio-reactive effects.
133
+ #### Specialized Hooks
163
134
 
164
135
  ```tsx
165
- <AudioReactiveCover
166
- variant="spotlight" // 'glow' | 'orbs' | 'spotlight' | 'mesh'
167
- intensity="medium" // 'subtle' | 'medium' | 'strong'
168
- colorScheme="primary" // 'primary' | 'vibrant' | 'cool' | 'warm'
169
- onClick={() => nextVariant()}
170
- >
171
- <img src={coverArt} alt="Album cover" />
172
- </AudioReactiveCover>
173
- ```
136
+ // State only (read-only)
137
+ const { isPlaying, currentTime, duration } = useHybridAudioState();
174
138
 
175
- ### VisualizationToggle
139
+ // Controls only (no re-render on time updates)
140
+ const { play, pause, togglePlay, seek } = useHybridAudioControls();
176
141
 
177
- Button to cycle through visualization variants.
142
+ // Audio levels for reactive effects
143
+ const { bass, mid, high, overall } = useHybridAudioLevels();
178
144
 
179
- ```tsx
180
- <VisualizationToggle compact />
145
+ // Web Audio API access
146
+ const { context, analyser, sourceNode } = useHybridWebAudio();
181
147
  ```
182
148
 
183
- ## Hooks
149
+ ---
184
150
 
185
- ### useAudio
151
+ ## WaveSurfer-based Player (Legacy)
186
152
 
187
- Access full audio state and controls.
153
+ For cases where you need the static waveform visualization:
188
154
 
189
155
  ```tsx
190
- const {
191
- isReady,
192
- isPlaying,
193
- currentTime,
194
- duration,
195
- volume,
196
- isMuted,
197
- audioLevels, // { bass, mid, high, overall }
198
- play,
199
- pause,
200
- togglePlay,
201
- seek,
202
- seekTo,
203
- skip,
204
- setVolume,
205
- toggleMute,
206
- restart,
207
- } = useAudio();
208
- ```
209
-
210
- ### useAudioControls
211
-
212
- Controls only (no re-render on time updates).
156
+ import { SimpleAudioPlayer } from '@djangocfg/ui-nextjs';
213
157
 
214
- ```tsx
215
- const { play, pause, togglePlay, skip, restart } = useAudioControls();
158
+ <SimpleAudioPlayer
159
+ src={audioUrl}
160
+ prefetch={true} // Required for streaming URLs
161
+ title="Track Title"
162
+ showWaveform
163
+ reactiveCover
164
+ />
216
165
  ```
217
166
 
218
- ### useAudioState
167
+ > **Note:** `prefetch={true}` downloads the entire file before playing. For large files or streaming, use `HybridSimplePlayer` instead.
219
168
 
220
- Read-only playback state.
169
+ ---
221
170
 
222
- ```tsx
223
- const { isPlaying, currentTime, duration, volume } = useAudioState();
224
- ```
171
+ ## Components
225
172
 
226
- ### useAudioElement
173
+ ### HybridWaveform
227
174
 
228
- Access audio element for custom visualizations.
175
+ Real-time frequency visualization canvas:
229
176
 
230
177
  ```tsx
231
- const { audioElement, isPlaying, audioLevels } = useAudioElement();
178
+ <HybridWaveform
179
+ mode="frequency" // 'frequency' | 'static'
180
+ height={64}
181
+ barWidth={3}
182
+ barGap={2}
183
+ barRadius={2}
184
+ progressColor="hsl(217 91% 60%)"
185
+ waveColor="hsl(217 91% 60% / 0.3)"
186
+ bufferedColor="hsl(217 91% 60% / 0.15)"
187
+ onSeek={(time) => console.log('Seeked to', time)}
188
+ />
232
189
  ```
233
190
 
234
- ### useAudioVisualization
191
+ ### AudioReactiveCover
235
192
 
236
- Manage visualization settings (persisted in localStorage).
193
+ Album art wrapper with audio-reactive effects:
237
194
 
238
195
  ```tsx
239
- const {
240
- settings, // { enabled, variant, intensity, colorScheme }
241
- toggle,
242
- setSetting,
243
- nextVariant,
244
- nextIntensity,
245
- nextColorScheme,
246
- reset,
247
- } = useAudioVisualization();
196
+ <AudioReactiveCover
197
+ variant="spotlight" // 'glow' | 'orbs' | 'spotlight' | 'mesh'
198
+ intensity="medium" // 'subtle' | 'medium' | 'strong'
199
+ colorScheme="primary" // 'primary' | 'vibrant' | 'cool' | 'warm'
200
+ onClick={() => nextVariant()}
201
+ >
202
+ <img src={coverArt} alt="Album cover" />
203
+ </AudioReactiveCover>
248
204
  ```
249
205
 
250
- ### useAudioHotkeys
206
+ ### AudioEqualizer
251
207
 
252
- Enable keyboard shortcuts.
208
+ Real-time frequency visualizer with animated bars:
253
209
 
254
210
  ```tsx
255
- useAudioHotkeys({
256
- enabled: true,
257
- skipDuration: 10,
258
- volumeStep: 0.1,
259
- });
211
+ <AudioEqualizer
212
+ barCount={24}
213
+ height={48}
214
+ gap={2}
215
+ showPeaks
216
+ barColor="hsl(217 91% 60%)"
217
+ peakColor="hsl(217 91% 70%)"
218
+ />
260
219
  ```
261
220
 
221
+ ---
222
+
262
223
  ## Keyboard Shortcuts
263
224
 
264
225
  | Key | Action |
@@ -271,21 +232,14 @@ useAudioHotkeys({
271
232
  | `M` | Mute/Unmute |
272
233
  | `0-9` | Jump to 0-90% |
273
234
 
274
- ## Waveform Options
275
-
276
- ```typescript
277
- interface WaveformOptions {
278
- waveColor?: string; // Unplayed wave color
279
- progressColor?: string; // Played wave color
280
- cursorColor?: string; // Playhead cursor color
281
- cursorWidth?: number; // Cursor width in px
282
- height?: number; // Waveform height in px
283
- barWidth?: number; // Bar width in px
284
- barRadius?: number; // Bar corner radius
285
- barGap?: number; // Gap between bars
286
- }
235
+ Enable with:
236
+
237
+ ```tsx
238
+ useAudioHotkeys({ enabled: true, skipDuration: 10, volumeStep: 0.1 });
287
239
  ```
288
240
 
241
+ ---
242
+
289
243
  ## Effect Variants
290
244
 
291
245
  | Variant | Description |
@@ -296,45 +250,63 @@ interface WaveformOptions {
296
250
  | `mesh` | Large gradient blobs with movement |
297
251
  | `none` | Effects disabled |
298
252
 
253
+ ---
254
+
299
255
  ## Architecture
300
256
 
301
257
  ```
302
258
  AudioPlayer/
303
259
  ├── index.ts # Public API exports
304
- ├── types/
305
- │ ├── index.ts # Type re-exports
306
- │ ├── audio.ts # Audio state & source types
307
- │ ├── components.ts # Component prop types
308
- │ └── effects.ts # Visualization effect types
260
+ ├── types/ # TypeScript types
309
261
  ├── hooks/
310
- │ ├── index.ts
311
- │ ├── useAudioSource.ts # Audio source loading with prefetch
312
- │ ├── useAudioHotkeys.ts # Keyboard shortcuts
313
- │ ├── useVisualization.tsx # Visualization settings
262
+ │ ├── useHybridAudio.ts # 🆕 HTML5 audio + Web Audio hook
263
+ │ ├── useHybridAudioAnalysis.ts # 🆕 Frequency analysis for hybrid
264
+ │ ├── useSharedWebAudio.ts # Shared AudioContext (WaveSurfer)
314
265
  │ ├── useAudioAnalysis.ts # Web Audio frequency analysis
315
- └── useSharedWebAudio.ts # Shared AudioContext
316
- ├── utils/
317
- │ ├── index.ts
318
- │ └── formatTime.ts # Time formatting
266
+ ├── useAudioHotkeys.ts # Keyboard shortcuts
267
+ │ └── useVisualization.tsx # Visualization settings
319
268
  ├── context/
320
- │ ├── index.ts
321
- │ ├── AudioProvider.tsx # Audio state provider
322
- │ └── selectors.ts # useAudio, useAudioControls hooks
269
+ │ ├── HybridAudioProvider.tsx # 🆕 Hybrid audio context
270
+ │ ├── AudioProvider.tsx # WaveSurfer context
271
+ │ └── selectors.ts # Hook selectors
323
272
  ├── components/
324
- │ ├── index.ts
325
- │ ├── AudioPlayer.tsx # Main player component
326
- │ ├── SimpleAudioPlayer.tsx # All-in-one wrapper
273
+ │ ├── HybridAudioPlayer.tsx # 🆕 Main hybrid player
274
+ │ ├── HybridSimplePlayer.tsx # 🆕 All-in-one hybrid wrapper
275
+ │ ├── HybridWaveform.tsx # 🆕 Frequency visualization
276
+ │ ├── AudioPlayer.tsx # WaveSurfer player
277
+ │ ├── SimpleAudioPlayer.tsx # WaveSurfer wrapper
327
278
  │ ├── AudioEqualizer.tsx # Frequency bars
328
- ├── AudioShortcutsPopover.tsx # Shortcuts help
329
- ├── VisualizationToggle.tsx # Effect toggle button
330
- └── ReactiveCover/
331
- │ ├── index.ts
332
- │ ├── AudioReactiveCover.tsx # Reactive album art
333
- │ └── effects/ # Effect components
334
- │ ├── GlowEffect.tsx
335
- │ ├── OrbsEffect.tsx
336
- │ ├── SpotlightEffect.tsx
337
- │ └── MeshEffect.tsx
338
- └── effects/
339
- └── index.ts # Effect calculations
279
+ └── ReactiveCover/ # Reactive effects
280
+ ├── progressive/ # Progressive/streaming player
281
+ └── effects/ # Effect calculations
340
282
  ```
283
+
284
+ ---
285
+
286
+ ## Migration Guide
287
+
288
+ ### From SimpleAudioPlayer to HybridSimplePlayer
289
+
290
+ ```tsx
291
+ // Before
292
+ <SimpleAudioPlayer
293
+ src={url}
294
+ prefetch={true}
295
+ showWaveform
296
+ reactiveCover
297
+ variant="spotlight"
298
+ />
299
+
300
+ // After
301
+ <HybridSimplePlayer
302
+ src={url}
303
+ showWaveform
304
+ reactiveCover
305
+ variant="spotlight"
306
+ />
307
+ ```
308
+
309
+ Key differences:
310
+ - No `prefetch` prop needed — streaming works natively
311
+ - `waveformMode="frequency"` shows real-time bars instead of static waveform
312
+ - Same reactive effects support
@@ -1,11 +1,16 @@
1
1
  'use client';
2
2
 
3
3
  /**
4
- * AudioPlayer - Audio playback controls and waveform display
4
+ * AudioPlayer - WaveSurfer-based player component (Legacy)
5
5
  *
6
- * Uses AudioContext for state management
7
- * Renders waveform (via container ref), controls, timer, and equalizer
8
- * Supports keyboard shortcuts for playback control
6
+ * @deprecated Consider using `HybridAudioPlayer` instead for better streaming
7
+ * support and guaranteed no audio crackling.
8
+ *
9
+ * Uses AudioContext for state management.
10
+ * Renders waveform (via container ref), controls, timer, and equalizer.
11
+ * Supports keyboard shortcuts for playback control.
12
+ *
13
+ * @see HybridAudioPlayer for the recommended alternative
9
14
  */
10
15
 
11
16
  import { forwardRef } from 'react';