@remotion/media-utils 4.0.279 → 4.0.280

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.
@@ -5,15 +5,18 @@ const fetch_with_cors_catch_1 = require("./fetch-with-cors-catch");
5
5
  const probe_wave_file_1 = require("./probe-wave-file");
6
6
  const getPartialWaveData = async ({ dataOffset, src, bitsPerSample, channelIndex, sampleRate, fromSeconds, toSeconds, blockAlign, fileSize, signal, }) => {
7
7
  const startByte = dataOffset + Math.floor(fromSeconds * sampleRate) * blockAlign;
8
- const endByte = Math.min(fileSize - 1, dataOffset + Math.floor(toSeconds * sampleRate - 1) * blockAlign);
8
+ const endByte = Math.min(fileSize, (dataOffset + Math.floor(toSeconds * sampleRate)) * blockAlign) - 1;
9
9
  const response = await (0, fetch_with_cors_catch_1.fetchWithCorsCatch)(src, {
10
10
  headers: {
11
11
  range: `bytes=${startByte}-${endByte}`,
12
12
  },
13
13
  signal,
14
14
  });
15
+ if (response.status === 416) {
16
+ throw new Error(`Tried to read bytes ${startByte}-${endByte} from ${src}, but the response status code was 416 "Range Not Satisfiable". Were too many bytes requested? The file is ${fileSize} bytes long.`);
17
+ }
15
18
  if (response.status !== 206) {
16
- throw new Error(`Tried to read bytes ${startByte}-${endByte} from ${src}, but the response status code was not 206. This means the server might not support returning a partial response.`);
19
+ throw new Error(`Tried to read bytes ${startByte}-${endByte} from ${src}, but the response status code was ${response.status} (expected was 206). This means the server might not support returning a partial response.`);
17
20
  }
18
21
  const arrayBuffer = await response.arrayBuffer();
19
22
  const uintArray = new Uint8Array(arrayBuffer);
@@ -1,6 +1,7 @@
1
1
  export type SampleOutputRange = 'minus-one-to-one' | 'zero-to-one';
2
- export declare const getWaveformSamples: ({ audioBuffer, numberOfSamples, outputRange, }: {
2
+ export declare const getWaveformSamples: ({ audioBuffer, numberOfSamples, outputRange, normalize, }: {
3
3
  audioBuffer: Float32Array;
4
4
  numberOfSamples: number;
5
5
  outputRange: SampleOutputRange;
6
+ normalize: boolean;
6
7
  }) => number[];
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getWaveformSamples = void 0;
4
- const getWaveformSamples = ({ audioBuffer, numberOfSamples, outputRange, }) => {
4
+ const normalize_data_1 = require("./normalize-data");
5
+ const getWaveformSamples = ({ audioBuffer, numberOfSamples, outputRange, normalize, }) => {
5
6
  const blockSize = Math.floor(audioBuffer.length / numberOfSamples); // the number of samples in each subdivision
6
7
  if (blockSize === 0) {
7
8
  return [];
@@ -13,8 +14,26 @@ const getWaveformSamples = ({ audioBuffer, numberOfSamples, outputRange, }) => {
13
14
  for (let j = 0; j < blockSize; j++) {
14
15
  sum += Math.abs(audioBuffer[blockStart + j]); // find the sum of all the samples in the block
15
16
  }
16
- filteredData.push((sum / blockSize) *
17
- (i % 2 === 0 && outputRange === 'minus-one-to-one' ? -1 : 1)); // divide the sum by the block size to get the average
17
+ filteredData.push(sum / blockSize); // divide the sum by the block size to get the average
18
+ }
19
+ if (normalize) {
20
+ if (outputRange === 'minus-one-to-one') {
21
+ return (0, normalize_data_1.normalizeData)(filteredData).map((n, i) => {
22
+ if (i % 2 === 0) {
23
+ return n * -1;
24
+ }
25
+ return n;
26
+ });
27
+ }
28
+ return (0, normalize_data_1.normalizeData)(filteredData);
29
+ }
30
+ if (outputRange === 'minus-one-to-one') {
31
+ return filteredData.map((n, i) => {
32
+ if (i % 2 === 0) {
33
+ return n * -1;
34
+ }
35
+ return n;
36
+ });
18
37
  }
19
38
  return filteredData;
20
39
  };
@@ -12,6 +12,7 @@ export type GetWaveformPortion = {
12
12
  channel?: number;
13
13
  outputRange?: SampleOutputRange;
14
14
  dataOffsetInSeconds?: number;
15
+ normalize?: boolean;
15
16
  };
16
- export declare const getWaveformPortion: ({ audioData, startTimeInSeconds, durationInSeconds, numberOfSamples, channel, outputRange, dataOffsetInSeconds, }: GetWaveformPortion) => Bar[];
17
+ export declare const getWaveformPortion: ({ audioData, startTimeInSeconds, durationInSeconds, numberOfSamples, channel, outputRange, dataOffsetInSeconds, normalize, }: GetWaveformPortion) => Bar[];
17
18
  export { Bar };
@@ -21,7 +21,7 @@ const concatArrays = (arrays) => {
21
21
  * @description Takes bulky waveform data (for example fetched by getAudioData()) and returns a trimmed and simplified version of it, for simpler visualization
22
22
  * @see [Documentation](https://remotion.dev/docs/get-waveform-portion)
23
23
  */
24
- const getWaveformPortion = ({ audioData, startTimeInSeconds, durationInSeconds, numberOfSamples, channel = 0, outputRange = 'zero-to-one', dataOffsetInSeconds, }) => {
24
+ const getWaveformPortion = ({ audioData, startTimeInSeconds, durationInSeconds, numberOfSamples, channel = 0, outputRange = 'zero-to-one', dataOffsetInSeconds, normalize = true, }) => {
25
25
  (0, validate_channel_1.validateChannel)(channel, audioData.numberOfChannels);
26
26
  const waveform = audioData.channelWaveforms[channel];
27
27
  const startSample = Math.floor((startTimeInSeconds - (dataOffsetInSeconds !== null && dataOffsetInSeconds !== void 0 ? dataOffsetInSeconds : 0)) * audioData.sampleRate);
@@ -45,6 +45,7 @@ const getWaveformPortion = ({ audioData, startTimeInSeconds, durationInSeconds,
45
45
  audioBuffer,
46
46
  numberOfSamples,
47
47
  outputRange,
48
+ normalize,
48
49
  }).map((w, i) => {
49
50
  return {
50
51
  index: i,
@@ -0,0 +1 @@
1
+ export declare const normalizeData: (filteredData: number[]) => number[];
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeData = void 0;
4
+ const normalizeData = (filteredData) => {
5
+ const max = Math.max(...filteredData);
6
+ const multiplier = max === 0 ? 0 : max ** -1;
7
+ return filteredData.map((n) => n * multiplier);
8
+ };
9
+ exports.normalizeData = normalizeData;
@@ -37,8 +37,11 @@ const probeWaveFile = async (src) => {
37
37
  range: 'bytes=0-256',
38
38
  },
39
39
  });
40
+ if (response.status === 416) {
41
+ throw new Error(`Tried to read bytes 0-256 from ${src}, but the response status code was 416 "Range Not Satisfiable". Is the file at least 256 bytes long?`);
42
+ }
40
43
  if (response.status !== 206) {
41
- throw new Error(`Tried to read bytes 0-256 from ${src}, but the response status code was not 206. This means the server might not support returning a partial response.`);
44
+ throw new Error(`Tried to read bytes 0-256 from ${src}, but the response status code was ${response.status} (expected was 206). This means the server might not support returning a partial response.`);
42
45
  }
43
46
  const buffer = await response.arrayBuffer();
44
47
  const uintArray = new Uint8Array(buffer);
@@ -55,7 +55,10 @@ const useWindowedAudioData = ({ src, frame, fps, windowInSeconds, channelIndex =
55
55
  if (!waveProbe) {
56
56
  return [];
57
57
  }
58
- const maxWindowIndex = Math.floor(waveProbe.durationInSeconds / windowInSeconds);
58
+ const maxWindowIndex = Math.floor(
59
+ // If an audio is exactly divisible by windowInSeconds, we need to
60
+ // subtract 0.000000000001 to avoid fetching an extra window.
61
+ waveProbe.durationInSeconds / windowInSeconds - 0.000000000001);
59
62
  // needs to be in order because we rely on the concatenation below
60
63
  return [
61
64
  currentWindowIndex === 0 ? null : currentWindowIndex - 1,
@@ -7,5 +7,6 @@ export type VisualizeAudioWaveformOptions = {
7
7
  numberOfSamples: number;
8
8
  channel?: number;
9
9
  dataOffsetInSeconds?: number;
10
+ normalize?: boolean;
10
11
  };
11
12
  export declare const visualizeAudioWaveform: (parameters: VisualizeAudioWaveformOptions) => number[];
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.visualizeAudioWaveform = void 0;
4
4
  const get_waveform_portion_1 = require("./get-waveform-portion");
5
5
  const cache = {};
6
- const visualizeAudioWaveformFrame = ({ audioData, frame, fps, numberOfSamples, windowInSeconds, channel, dataOffsetInSeconds, }) => {
6
+ const visualizeAudioWaveformFrame = ({ audioData, frame, fps, numberOfSamples, windowInSeconds, channel, dataOffsetInSeconds, normalize = false, }) => {
7
7
  if (windowInSeconds * audioData.sampleRate < numberOfSamples) {
8
8
  throw new TypeError(windowInSeconds +
9
9
  's audiodata does not have ' +
@@ -29,6 +29,7 @@ const visualizeAudioWaveformFrame = ({ audioData, frame, fps, numberOfSamples, w
29
29
  outputRange: 'minus-one-to-one',
30
30
  channel,
31
31
  dataOffsetInSeconds,
32
+ normalize,
32
33
  });
33
34
  };
34
35
  const visualizeAudioWaveform = (parameters) => {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/media-utils"
4
4
  },
5
5
  "name": "@remotion/media-utils",
6
- "version": "4.0.279",
6
+ "version": "4.0.280",
7
7
  "description": "Utilities for working with media files",
8
8
  "main": "dist/index.js",
9
9
  "sideEffects": false,
@@ -13,7 +13,7 @@
13
13
  "url": "https://github.com/remotion-dev/remotion/issues"
14
14
  },
15
15
  "dependencies": {
16
- "remotion": "4.0.279"
16
+ "remotion": "4.0.280"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "react": ">=16.8.0",
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "devDependencies": {
23
23
  "eslint": "9.19.0",
24
- "@remotion/eslint-config-internal": "4.0.279"
24
+ "@remotion/eslint-config-internal": "4.0.280"
25
25
  },
26
26
  "keywords": [
27
27
  "remotion",