@exode-team/react-recorder 1.1.11 → 1.1.12

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.
package/dist/index.js CHANGED
@@ -182,6 +182,8 @@ const revokeObjectURL = (url) => {
182
182
  * @author: exode <hello@exode.ru>
183
183
  */
184
184
  const AUDIO_LEVEL_BARS = 40;
185
+ /** Waveform decoding resamples to this rate — only the amplitude envelope matters */
186
+ const WAVEFORM_SAMPLE_RATE = 44100;
185
187
  const createInitialLevels = () => Array.from({ length: AUDIO_LEVEL_BARS }, () => 0);
186
188
  const TIMELINE_SAMPLE_INTERVAL = 150;
187
189
  const TIMELINE_BAR_WIDTH = 3;
@@ -288,32 +290,33 @@ const decodeSkippingJunk = async (context, blob) => {
288
290
  }
289
291
  };
290
292
  const decodeAudioLevels = async (blob, barCount = AUDIO_LEVEL_BARS) => {
291
- const context = new AudioContext();
292
- try {
293
- const audioBuffer = await decodeSkippingJunk(context, blob);
294
- const channelData = audioBuffer.getChannelData(0);
295
- if (!channelData.length) {
296
- return Array.from({ length: barCount }, () => 0);
297
- }
298
- const levels = [];
299
- const segmentLength = Math.max(1, Math.floor(channelData.length / barCount));
300
- for (let i = 0; i < barCount; i += 1) {
301
- const segmentStart = i * segmentLength;
302
- let sum = 0;
303
- for (let j = 0; j < segmentLength; j += 1) {
304
- const sample = channelData[segmentStart + j];
305
- if (sample !== undefined) {
306
- sum += Math.abs(sample);
307
- }
293
+ /**
294
+ * Offline context stays out of the audio session. A realtime AudioContext
295
+ * registers as a WebAudio source, which pins WebKit to the AmbientSound
296
+ * category and leaves media playback silent inside iOS apps — including
297
+ * iPad apps running on macOS.
298
+ */
299
+ const context = new OfflineAudioContext(1, 1, WAVEFORM_SAMPLE_RATE);
300
+ const audioBuffer = await decodeSkippingJunk(context, blob);
301
+ const channelData = audioBuffer.getChannelData(0);
302
+ if (!channelData.length) {
303
+ return Array.from({ length: barCount }, () => 0);
304
+ }
305
+ const levels = [];
306
+ const segmentLength = Math.max(1, Math.floor(channelData.length / barCount));
307
+ for (let i = 0; i < barCount; i += 1) {
308
+ const segmentStart = i * segmentLength;
309
+ let sum = 0;
310
+ for (let j = 0; j < segmentLength; j += 1) {
311
+ const sample = channelData[segmentStart + j];
312
+ if (sample !== undefined) {
313
+ sum += Math.abs(sample);
308
314
  }
309
- const average = sum / segmentLength;
310
- levels.push(Math.min(100, average * 200));
311
315
  }
312
- return levels;
313
- }
314
- finally {
315
- await context.close();
316
+ const average = sum / segmentLength;
317
+ levels.push(Math.min(100, average * 200));
316
318
  }
319
+ return levels;
317
320
  };
318
321
 
319
322
  /**