@remotion/webcodecs 4.0.286 → 4.0.288

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 (81) hide show
  1. package/dist/audio-data/data-types.d.ts +1 -0
  2. package/dist/audio-data/data-types.js +26 -0
  3. package/dist/audio-data/is-planar-format.d.ts +1 -0
  4. package/dist/audio-data/is-planar-format.js +7 -0
  5. package/dist/audio-encoder.js +5 -1
  6. package/dist/can-reencode-audio-track.d.ts +2 -1
  7. package/dist/can-reencode-audio-track.js +2 -2
  8. package/dist/convert-audiodata.d.ts +10 -0
  9. package/dist/convert-audiodata.js +85 -0
  10. package/dist/convert-media.d.ts +2 -1
  11. package/dist/convert-media.js +2 -1
  12. package/dist/create/iso-base-media/codec-specific/create-codec-specific-data.js +8 -0
  13. package/dist/create/iso-base-media/create-iso-base-media.js +2 -0
  14. package/dist/create/iso-base-media/example-stts.js +620 -0
  15. package/dist/create/matroska/create-matroska-media.js +1 -1
  16. package/dist/create/matroska/matroska-utils.d.ts +1 -1
  17. package/dist/default-on-audio-track-handler.js +2 -0
  18. package/dist/esm/index.mjs +183 -24
  19. package/dist/esm/web-fs.mjs +2 -4
  20. package/dist/get-wave-audio-decoder.js +29 -1
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.js +3 -1
  23. package/dist/on-audio-track-handler.d.ts +1 -0
  24. package/dist/on-audio-track.js +3 -3
  25. package/dist/resample-audiodata.d.ts +4 -0
  26. package/dist/resample-audiodata.js +35 -0
  27. package/dist/wav-audio-encoder.d.ts +1 -1
  28. package/dist/wav-audio-encoder.js +11 -4
  29. package/package.json +12 -7
  30. package/dist/test/avc1.test.d.ts +0 -1
  31. package/dist/test/avc1.test.js +0 -39
  32. package/dist/test/avcc.test.d.ts +0 -1
  33. package/dist/test/avcc.test.js +0 -15
  34. package/dist/test/avi-to-mp4.test.d.ts +0 -1
  35. package/dist/test/avi-to-mp4.test.js +0 -15
  36. package/dist/test/cmt.test.d.ts +0 -1
  37. package/dist/test/cmt.test.js +0 -13
  38. package/dist/test/colr.test.d.ts +0 -1
  39. package/dist/test/colr.test.js +0 -16
  40. package/dist/test/correct-byte-length.test.d.ts +0 -1
  41. package/dist/test/correct-byte-length.test.js +0 -23
  42. package/dist/test/create-ftyp.test.d.ts +0 -1
  43. package/dist/test/create-ftyp.test.js +0 -47
  44. package/dist/test/create-mvhd.test.d.ts +0 -1
  45. package/dist/test/create-mvhd.test.js +0 -108
  46. package/dist/test/ctts.test.d.ts +0 -1
  47. package/dist/test/ctts.test.js +0 -49
  48. package/dist/test/dinf.test.d.ts +0 -1
  49. package/dist/test/dinf.test.js +0 -12
  50. package/dist/test/ilst.test.d.ts +0 -1
  51. package/dist/test/ilst.test.js +0 -22
  52. package/dist/test/mdhd.test.d.ts +0 -1
  53. package/dist/test/mdhd.test.js +0 -17
  54. package/dist/test/meta.test.d.ts +0 -1
  55. package/dist/test/meta.test.js +0 -26
  56. package/dist/test/mp4-header-length.test.d.ts +0 -1
  57. package/dist/test/mp4-header-length.test.js +0 -12
  58. package/dist/test/mp4a.test.d.ts +0 -1
  59. package/dist/test/mp4a.test.js +0 -24
  60. package/dist/test/pasp.test.d.ts +0 -1
  61. package/dist/test/pasp.test.js +0 -12
  62. package/dist/test/remux-serverside.test.d.ts +0 -1
  63. package/dist/test/remux-serverside.test.js +0 -23
  64. package/dist/test/stbl.test.d.ts +0 -0
  65. package/dist/test/stbl.test.js +0 -176
  66. package/dist/test/stco.test.d.ts +0 -1
  67. package/dist/test/stco.test.js +0 -34
  68. package/dist/test/stsc.test.d.ts +0 -1
  69. package/dist/test/stsc.test.js +0 -63
  70. package/dist/test/stss.test.d.ts +0 -1
  71. package/dist/test/stss.test.js +0 -14
  72. package/dist/test/stsz.test.d.ts +0 -1
  73. package/dist/test/stsz.test.js +0 -43
  74. package/dist/test/stts.test.d.ts +0 -1
  75. package/dist/test/stts.test.js +0 -12
  76. package/dist/test/tkhd.test.d.ts +0 -1
  77. package/dist/test/tkhd.test.js +0 -175
  78. package/dist/test/too.test.d.ts +0 -1
  79. package/dist/test/too.test.js +0 -12
  80. package/dist/test/url.test.d.ts +0 -1
  81. package/dist/test/url.test.js +0 -11
@@ -0,0 +1 @@
1
+ export declare const getDataTypeForAudioFormat: (format: AudioSampleFormat) => Uint8ArrayConstructor | Float32ArrayConstructor | Int16ArrayConstructor | Int32ArrayConstructor;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDataTypeForAudioFormat = void 0;
4
+ const getDataTypeForAudioFormat = (format) => {
5
+ switch (format) {
6
+ case 'f32':
7
+ return Float32Array;
8
+ case 'f32-planar':
9
+ return Float32Array;
10
+ case 's16':
11
+ return Int16Array;
12
+ case 's16-planar':
13
+ return Int16Array;
14
+ case 'u8':
15
+ return Uint8Array;
16
+ case 'u8-planar':
17
+ return Uint8Array;
18
+ case 's32':
19
+ return Int32Array;
20
+ case 's32-planar':
21
+ return Int32Array;
22
+ default:
23
+ throw new Error(`Unsupported audio format: ${format}`);
24
+ }
25
+ };
26
+ exports.getDataTypeForAudioFormat = getDataTypeForAudioFormat;
@@ -0,0 +1 @@
1
+ export declare const isPlanarFormat: (format: AudioSampleFormat) => boolean;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isPlanarFormat = void 0;
4
+ const isPlanarFormat = (format) => {
5
+ return format.includes('-planar');
6
+ };
7
+ exports.isPlanarFormat = isPlanarFormat;
@@ -9,7 +9,11 @@ const createAudioEncoder = ({ onChunk, onError, codec, controller, config: audio
9
9
  throw new media_parser_1.MediaParserAbortError('Not creating audio encoder, already aborted');
10
10
  }
11
11
  if (codec === 'wav') {
12
- return (0, wav_audio_encoder_1.getWaveAudioEncoder)({ onChunk, controller });
12
+ return (0, wav_audio_encoder_1.getWaveAudioEncoder)({
13
+ onChunk,
14
+ controller,
15
+ config: audioEncoderConfig,
16
+ });
13
17
  }
14
18
  const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)({
15
19
  logLevel,
@@ -1,7 +1,8 @@
1
1
  import type { AudioTrack } from '@remotion/media-parser';
2
2
  import type { ConvertMediaAudioCodec } from './get-available-audio-codecs';
3
- export declare const canReencodeAudioTrack: ({ track, audioCodec, bitrate, }: {
3
+ export declare const canReencodeAudioTrack: ({ track, audioCodec, bitrate, sampleRate, }: {
4
4
  track: AudioTrack;
5
5
  audioCodec: ConvertMediaAudioCodec;
6
6
  bitrate: number;
7
+ sampleRate: number | null;
7
8
  }) => Promise<boolean>;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.canReencodeAudioTrack = void 0;
4
4
  const audio_decoder_config_1 = require("./audio-decoder-config");
5
5
  const audio_encoder_config_1 = require("./audio-encoder-config");
6
- const canReencodeAudioTrack = async ({ track, audioCodec, bitrate, }) => {
6
+ const canReencodeAudioTrack = async ({ track, audioCodec, bitrate, sampleRate, }) => {
7
7
  const audioDecoderConfig = await (0, audio_decoder_config_1.getAudioDecoderConfig)(track);
8
8
  if (audioCodec === 'wav' && audioDecoderConfig) {
9
9
  return true;
@@ -11,7 +11,7 @@ const canReencodeAudioTrack = async ({ track, audioCodec, bitrate, }) => {
11
11
  const audioEncoderConfig = await (0, audio_encoder_config_1.getAudioEncoderConfig)({
12
12
  codec: audioCodec,
13
13
  numberOfChannels: track.numberOfChannels,
14
- sampleRate: track.sampleRate,
14
+ sampleRate: sampleRate ?? track.sampleRate,
15
15
  bitrate,
16
16
  });
17
17
  return Boolean(audioDecoderConfig && audioEncoderConfig);
@@ -0,0 +1,10 @@
1
+ export type ConvertAudioDataOptions = {
2
+ audioData: AudioData;
3
+ newSampleRate?: number;
4
+ format?: AudioSampleFormat | null;
5
+ };
6
+ /**
7
+ * Converts an `AudioData` object to a new `AudioData` object with a different sample rate or format.
8
+ * @see [Documentation](https://remotion.dev/docs/webcodecs/convert-audiodata)
9
+ */
10
+ export declare const convertAudioData: ({ audioData, newSampleRate, format, }: ConvertAudioDataOptions) => AudioData;
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertAudioData = void 0;
4
+ const data_types_1 = require("./audio-data/data-types");
5
+ const is_planar_format_1 = require("./audio-data/is-planar-format");
6
+ const validateRange = (format, value) => {
7
+ if (format === 'f32' || format === 'f32-planar') {
8
+ if (value < -1 || value > 1) {
9
+ throw new Error('All values in a Float32 array must be between -1 and 1');
10
+ }
11
+ }
12
+ };
13
+ /**
14
+ * Converts an `AudioData` object to a new `AudioData` object with a different sample rate or format.
15
+ * @see [Documentation](https://remotion.dev/docs/webcodecs/convert-audiodata)
16
+ */
17
+ const convertAudioData = ({ audioData, newSampleRate = audioData.sampleRate, format = audioData.format, }) => {
18
+ const { numberOfChannels, sampleRate: currentSampleRate, numberOfFrames: currentNumberOfFrames, } = audioData;
19
+ const ratio = currentSampleRate / newSampleRate;
20
+ const newNumberOfFrames = Math.floor(currentNumberOfFrames / ratio);
21
+ if (newNumberOfFrames === 0) {
22
+ throw new Error('Cannot resample - the given sample rate would result in less than 1 sample');
23
+ }
24
+ if (newSampleRate < 3000 || newSampleRate > 768000) {
25
+ throw new Error('newSampleRate must be between 3000 and 768000');
26
+ }
27
+ if (!format) {
28
+ throw new Error('AudioData format is not set');
29
+ }
30
+ if (format === audioData.format &&
31
+ newNumberOfFrames === currentNumberOfFrames) {
32
+ return audioData.clone();
33
+ }
34
+ const DataType = (0, data_types_1.getDataTypeForAudioFormat)(format);
35
+ const isPlanar = (0, is_planar_format_1.isPlanarFormat)(format);
36
+ const planes = isPlanar ? numberOfChannels : 1;
37
+ const srcChannels = new Array(planes)
38
+ .fill(true)
39
+ .map(() => new DataType((isPlanar ? 1 : numberOfChannels) * currentNumberOfFrames));
40
+ for (let i = 0; i < planes; i++) {
41
+ audioData.clone().copyTo(srcChannels[i], {
42
+ planeIndex: i,
43
+ format,
44
+ });
45
+ }
46
+ const data = new DataType(newNumberOfFrames * numberOfChannels);
47
+ const chunkSize = currentNumberOfFrames / newNumberOfFrames;
48
+ for (let newFrameIndex = 0; newFrameIndex < newNumberOfFrames; newFrameIndex++) {
49
+ const start = Math.floor(newFrameIndex * chunkSize);
50
+ const end = Math.max(Math.floor(start + chunkSize), start + 1);
51
+ if (isPlanar) {
52
+ for (let channelIndex = 0; channelIndex < numberOfChannels; channelIndex++) {
53
+ const chunk = srcChannels[channelIndex].slice(start, end);
54
+ const average = chunk.reduce((a, b) => {
55
+ return a + b;
56
+ }, 0) / chunk.length;
57
+ validateRange(format, average);
58
+ data[newFrameIndex + channelIndex * newNumberOfFrames] = average;
59
+ }
60
+ }
61
+ else {
62
+ const sampleCountAvg = end - start;
63
+ for (let channelIndex = 0; channelIndex < numberOfChannels; channelIndex++) {
64
+ const items = [];
65
+ for (let k = 0; k < sampleCountAvg; k++) {
66
+ const num = srcChannels[0][(start + k) * numberOfChannels + channelIndex];
67
+ items.push(num);
68
+ }
69
+ const average = items.reduce((a, b) => a + b, 0) / items.length;
70
+ validateRange(format, average);
71
+ data[newFrameIndex * numberOfChannels + channelIndex] = average;
72
+ }
73
+ }
74
+ }
75
+ const newAudioData = new AudioData({
76
+ data,
77
+ format,
78
+ numberOfChannels,
79
+ numberOfFrames: newNumberOfFrames,
80
+ sampleRate: newSampleRate,
81
+ timestamp: audioData.timestamp,
82
+ });
83
+ return newAudioData;
84
+ };
85
+ exports.convertAudioData = convertAudioData;
@@ -35,7 +35,7 @@ export type ConvertMediaOnAudioData = (options: {
35
35
  audioData: AudioData;
36
36
  track: AudioTrack;
37
37
  }) => Promise<AudioData> | AudioData;
38
- export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller, onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel, writer, progressIntervalInMs, rotate, apiKey, resize, onAudioCodec, onContainer, onDimensions, onDurationInSeconds, onFps, onImages, onInternalStats, onIsHdr, onKeyframes, onLocation, onMetadata, onMimeType, onName, onNumberOfAudioChannels, onRotation, onSampleRate, onSize, onSlowAudioBitrate, onSlowDurationInSeconds, onSlowFps, onSlowKeyframes, onSlowNumberOfFrames, onSlowVideoBitrate, onStructure, onTracks, onUnrotatedDimensions, onVideoCodec, onM3uStreams, selectM3uStream, selectM3uAssociatedPlaylists, expectedDurationInSeconds, ...more }: {
38
+ export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller, onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel, writer, progressIntervalInMs, rotate, apiKey, resize, onAudioCodec, onContainer, onDimensions, onDurationInSeconds, onFps, onImages, onInternalStats, onIsHdr, onKeyframes, onLocation, onMetadata, onMimeType, onName, onNumberOfAudioChannels, onRotation, onSampleRate, onSize, onSlowAudioBitrate, onSlowDurationInSeconds, onSlowFps, onSlowKeyframes, onSlowNumberOfFrames, onSlowVideoBitrate, onStructure, onTracks, onUnrotatedDimensions, onVideoCodec, onM3uStreams, selectM3uStream, selectM3uAssociatedPlaylists, expectedDurationInSeconds, seekingHints, ...more }: {
39
39
  src: ParseMediaOptions<F>["src"];
40
40
  container: ConvertMediaContainer;
41
41
  onVideoFrame?: ConvertMediaOnVideoFrame;
@@ -57,4 +57,5 @@ export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src,
57
57
  resize?: ResizeOperation;
58
58
  apiKey?: string | null;
59
59
  fields?: F;
60
+ seekingHints?: ParseMediaOptions<F>["seekingHints"];
60
61
  } & ParseMediaCallbacks) => Promise<ConvertMediaResult>;
@@ -21,7 +21,7 @@ const select_container_creator_1 = require("./select-container-creator");
21
21
  const send_telemetry_event_1 = require("./send-telemetry-event");
22
22
  const throttled_state_update_1 = require("./throttled-state-update");
23
23
  const webcodecs_controller_1 = require("./webcodecs-controller");
24
- const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller = (0, webcodecs_controller_1.webcodecsController)(), onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel = 'info', writer, progressIntervalInMs, rotate, apiKey, resize, onAudioCodec, onContainer, onDimensions, onDurationInSeconds, onFps, onImages, onInternalStats, onIsHdr, onKeyframes, onLocation, onMetadata, onMimeType, onName, onNumberOfAudioChannels, onRotation, onSampleRate, onSize, onSlowAudioBitrate, onSlowDurationInSeconds, onSlowFps, onSlowKeyframes, onSlowNumberOfFrames, onSlowVideoBitrate, onStructure, onTracks, onUnrotatedDimensions, onVideoCodec, onM3uStreams, selectM3uStream, selectM3uAssociatedPlaylists, expectedDurationInSeconds, ...more }) {
24
+ const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller = (0, webcodecs_controller_1.webcodecsController)(), onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel = 'info', writer, progressIntervalInMs, rotate, apiKey, resize, onAudioCodec, onContainer, onDimensions, onDurationInSeconds, onFps, onImages, onInternalStats, onIsHdr, onKeyframes, onLocation, onMetadata, onMimeType, onName, onNumberOfAudioChannels, onRotation, onSampleRate, onSize, onSlowAudioBitrate, onSlowDurationInSeconds, onSlowFps, onSlowKeyframes, onSlowNumberOfFrames, onSlowVideoBitrate, onStructure, onTracks, onUnrotatedDimensions, onVideoCodec, onM3uStreams, selectM3uStream, selectM3uAssociatedPlaylists, expectedDurationInSeconds, seekingHints, ...more }) {
25
25
  if (controller._internals.signal.aborted) {
26
26
  return Promise.reject(new media_parser_1.MediaParserAbortError('Aborted'));
27
27
  }
@@ -175,6 +175,7 @@ const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgres
175
175
  selectM3uAssociatedPlaylists: selectM3uAssociatedPlaylists ?? media_parser_1.defaultSelectM3uAssociatedPlaylists,
176
176
  makeSamplesStartAtZero: false,
177
177
  mp4HeaderSegment: null,
178
+ seekingHints: seekingHints ?? null,
178
179
  })
179
180
  .then(() => {
180
181
  return state.waitForFinish();
@@ -10,6 +10,10 @@ const mp4a_1 = require("./mp4a");
10
10
  const createCodecSpecificData = (track) => {
11
11
  if (track.type === 'video') {
12
12
  if (track.codec === 'h264') {
13
+ // May not have it initially
14
+ if (!track.codecPrivate) {
15
+ return new Uint8Array([]);
16
+ }
13
17
  return (0, avc1_1.createAvc1Data)({
14
18
  avccBox: (0, create_avcc_1.createAvccBox)(track.codecPrivate),
15
19
  compressorName: 'WebCodecs',
@@ -23,6 +27,10 @@ const createCodecSpecificData = (track) => {
23
27
  });
24
28
  }
25
29
  if (track.codec === 'h265') {
30
+ // May not have it initially
31
+ if (!track.codecPrivate) {
32
+ return new Uint8Array([]);
33
+ }
26
34
  return (0, hvc1_1.createHvc1Data)({
27
35
  hvccBox: (0, create_hvcc_1.createHvccBox)(track.codecPrivate),
28
36
  compressorName: 'WebCodecs',
@@ -127,6 +127,8 @@ const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgr
127
127
  dts: Math.round((chunk.dts / 1000000) * currentTrack.timescale),
128
128
  duration: Math.round(((chunk.duration ?? 0) / 1000000) * currentTrack.timescale),
129
129
  size: chunk.data.length,
130
+ bigEndian: false,
131
+ chunkSize: null,
130
132
  };
131
133
  lastChunkWasVideo = isVideo;
132
134
  samplePositions[trackNumber].push(samplePositionToAdd);