@remotion/webcodecs 4.0.331 → 4.0.333

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.
@@ -95,7 +95,11 @@ const createMatroskaMedia = async ({ writer, onBytesProgress, onMillisecondsProg
95
95
  isVideo,
96
96
  chunk,
97
97
  })) {
98
- return { cluster: currentCluster, isNew: false, smallestProgress };
98
+ return {
99
+ cluster: currentCluster,
100
+ isNew: false,
101
+ smallestProgress,
102
+ };
99
103
  }
100
104
  currentCluster = await (0, cluster_1.makeCluster)({
101
105
  writer: w,
@@ -103,7 +107,11 @@ const createMatroskaMedia = async ({ writer, onBytesProgress, onMillisecondsProg
103
107
  timescale,
104
108
  logLevel,
105
109
  });
106
- return { cluster: currentCluster, isNew: true, smallestProgress };
110
+ return {
111
+ cluster: currentCluster,
112
+ isNew: true,
113
+ smallestProgress,
114
+ };
107
115
  };
108
116
  const updateDuration = async (newDuration) => {
109
117
  const blocks = (0, make_duration_with_padding_1.makeDurationWithPadding)(newDuration);
@@ -111,6 +119,7 @@ const createMatroskaMedia = async ({ writer, onBytesProgress, onMillisecondsProg
111
119
  onBytesProgress(w.getWrittenByteCount());
112
120
  };
113
121
  const addSample = async ({ chunk, trackNumber, isVideo, }) => {
122
+ const offset = w.getWrittenByteCount();
114
123
  const { cluster, isNew, smallestProgress } = await getClusterOrMakeNew({
115
124
  chunk,
116
125
  isVideo,
@@ -119,11 +128,13 @@ const createMatroskaMedia = async ({ writer, onBytesProgress, onMillisecondsProg
119
128
  await updateDuration(newDuration);
120
129
  const { timecodeRelativeToCluster } = await cluster.addSample(chunk, trackNumber);
121
130
  if (isNew) {
122
- const newCluster = w.getWrittenByteCount();
131
+ if (offset === null) {
132
+ throw new Error('offset is null');
133
+ }
123
134
  cues.push({
124
135
  time: (0, cluster_1.timestampToClusterTimestamp)(smallestProgress, timescale) +
125
136
  timecodeRelativeToCluster,
126
- clusterPosition: newCluster - seekHeadOffset,
137
+ clusterPosition: offset - seekHeadOffset,
127
138
  trackNumber,
128
139
  });
129
140
  }
@@ -18,11 +18,11 @@ export type CreateAudioDecoderInit = {
18
18
  config: AudioDecoderConfig;
19
19
  logLevel: MediaParserLogLevel;
20
20
  };
21
- export declare const internalCreateAudioDecoder: ({ onFrame, onError, controller, config, logLevel, }: CreateAudioDecoderInit) => WebCodecsAudioDecoder;
21
+ export declare const internalCreateAudioDecoder: ({ onFrame, onError, controller, config, logLevel, }: CreateAudioDecoderInit) => Promise<WebCodecsAudioDecoder>;
22
22
  export declare const createAudioDecoder: ({ track, onFrame, onError, controller, logLevel, }: {
23
23
  track: AudioDecoderConfig;
24
24
  onFrame: (frame: AudioData) => Promise<void> | void;
25
25
  onError: (error: Error) => void;
26
26
  controller?: WebCodecsController | null;
27
27
  logLevel?: MediaParserLogLevel;
28
- }) => WebCodecsAudioDecoder;
28
+ }) => Promise<WebCodecsAudioDecoder>;
@@ -4,7 +4,8 @@ exports.createAudioDecoder = exports.internalCreateAudioDecoder = void 0;
4
4
  const flush_pending_1 = require("./flush-pending");
5
5
  const get_wave_audio_decoder_1 = require("./get-wave-audio-decoder");
6
6
  const io_synchronizer_1 = require("./io-manager/io-synchronizer");
7
- const internalCreateAudioDecoder = ({ onFrame, onError, controller, config, logLevel, }) => {
7
+ const undecodable_error_1 = require("./undecodable-error");
8
+ const internalCreateAudioDecoder = async ({ onFrame, onError, controller, config, logLevel, }) => {
8
9
  if (controller &&
9
10
  controller._internals._mediaParserController._internals.signal.aborted) {
10
11
  throw new Error('Not creating audio decoder, already aborted');
@@ -57,6 +58,13 @@ const internalCreateAudioDecoder = ({ onFrame, onError, controller, config, logL
57
58
  if (controller) {
58
59
  controller._internals._mediaParserController._internals.signal.addEventListener('abort', onAbort);
59
60
  }
61
+ const isConfigSupported = await AudioDecoder.isConfigSupported(config);
62
+ if (!isConfigSupported) {
63
+ throw new undecodable_error_1.AudioUndecodableError({
64
+ message: 'Audio cannot be decoded by this browser',
65
+ config,
66
+ });
67
+ }
60
68
  audioDecoder.configure(config);
61
69
  const decode = async (audioSample) => {
62
70
  if (audioDecoder.state === 'closed') {
@@ -17,11 +17,11 @@ export declare const internalCreateVideoDecoder: ({ onFrame, onError, controller
17
17
  controller: WebCodecsController | null;
18
18
  config: VideoDecoderConfig;
19
19
  logLevel: MediaParserLogLevel;
20
- }) => WebCodecsVideoDecoder;
20
+ }) => Promise<WebCodecsVideoDecoder>;
21
21
  export declare const createVideoDecoder: ({ onFrame, onError, controller, track, logLevel, }: {
22
22
  track: VideoDecoderConfig;
23
23
  onFrame: (frame: VideoFrame) => Promise<void> | void;
24
24
  onError: (error: Error) => void;
25
25
  controller?: WebCodecsController;
26
26
  logLevel?: MediaParserLogLevel;
27
- }) => WebCodecsVideoDecoder;
27
+ }) => Promise<WebCodecsVideoDecoder>;
@@ -3,7 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createVideoDecoder = exports.internalCreateVideoDecoder = void 0;
4
4
  const flush_pending_1 = require("./flush-pending");
5
5
  const io_synchronizer_1 = require("./io-manager/io-synchronizer");
6
- const internalCreateVideoDecoder = ({ onFrame, onError, controller, config, logLevel, }) => {
6
+ const undecodable_error_1 = require("./undecodable-error");
7
+ const internalCreateVideoDecoder = async ({ onFrame, onError, controller, config, logLevel, }) => {
7
8
  if (controller &&
8
9
  controller._internals._mediaParserController._internals.signal.aborted) {
9
10
  throw new Error('Not creating audio decoder, already aborted');
@@ -46,6 +47,13 @@ const internalCreateVideoDecoder = ({ onFrame, onError, controller, config, logL
46
47
  if (controller) {
47
48
  controller._internals._mediaParserController._internals.signal.addEventListener('abort', onAbort);
48
49
  }
50
+ const isConfigSupported = await VideoDecoder.isConfigSupported(config);
51
+ if (!isConfigSupported) {
52
+ throw new undecodable_error_1.VideoUndecodableError({
53
+ message: 'Video cannot be decoded by this browser',
54
+ config,
55
+ });
56
+ }
49
57
  videoDecoder.configure(config);
50
58
  const decode = async (sample) => {
51
59
  if (videoDecoder.state === 'closed') {
@@ -23,7 +23,8 @@ const defaultOnVideoTrackHandler = async ({ track, defaultVideoCodec, logLevel,
23
23
  return Promise.resolve({
24
24
  type: 'reencode',
25
25
  videoCodec: defaultVideoCodec,
26
- rotate: rotate - track.rotation,
26
+ // By default, will remove rotation when re-encoding
27
+ rotate: undefined,
27
28
  resize: resizeOperation,
28
29
  });
29
30
  }
@@ -3751,7 +3751,11 @@ var createMatroskaMedia = async ({
3751
3751
  isVideo,
3752
3752
  chunk
3753
3753
  })) {
3754
- return { cluster: currentCluster, isNew: false, smallestProgress };
3754
+ return {
3755
+ cluster: currentCluster,
3756
+ isNew: false,
3757
+ smallestProgress
3758
+ };
3755
3759
  }
3756
3760
  currentCluster = await makeCluster({
3757
3761
  writer: w,
@@ -3759,7 +3763,11 @@ var createMatroskaMedia = async ({
3759
3763
  timescale,
3760
3764
  logLevel
3761
3765
  });
3762
- return { cluster: currentCluster, isNew: true, smallestProgress };
3766
+ return {
3767
+ cluster: currentCluster,
3768
+ isNew: true,
3769
+ smallestProgress
3770
+ };
3763
3771
  };
3764
3772
  const updateDuration = async (newDuration) => {
3765
3773
  const blocks = makeDurationWithPadding(newDuration);
@@ -3771,6 +3779,7 @@ var createMatroskaMedia = async ({
3771
3779
  trackNumber,
3772
3780
  isVideo
3773
3781
  }) => {
3782
+ const offset = w.getWrittenByteCount();
3774
3783
  const { cluster, isNew, smallestProgress } = await getClusterOrMakeNew({
3775
3784
  chunk,
3776
3785
  isVideo
@@ -3779,10 +3788,12 @@ var createMatroskaMedia = async ({
3779
3788
  await updateDuration(newDuration);
3780
3789
  const { timecodeRelativeToCluster } = await cluster.addSample(chunk, trackNumber);
3781
3790
  if (isNew) {
3782
- const newCluster = w.getWrittenByteCount();
3791
+ if (offset === null) {
3792
+ throw new Error("offset is null");
3793
+ }
3783
3794
  cues.push({
3784
3795
  time: timestampToClusterTimestamp(smallestProgress, timescale) + timecodeRelativeToCluster,
3785
- clusterPosition: newCluster - seekHeadOffset,
3796
+ clusterPosition: offset - seekHeadOffset,
3786
3797
  trackNumber
3787
3798
  });
3788
3799
  }
@@ -4253,8 +4264,39 @@ var getWaveAudioDecoder = ({
4253
4264
  };
4254
4265
  };
4255
4266
 
4267
+ // src/undecodable-error.ts
4268
+ class VideoUndecodableError extends Error {
4269
+ config;
4270
+ constructor({
4271
+ message,
4272
+ config
4273
+ }) {
4274
+ super(message);
4275
+ this.name = "VideoUndecodableError";
4276
+ this.config = config;
4277
+ if (Error.captureStackTrace) {
4278
+ Error.captureStackTrace(this, VideoUndecodableError);
4279
+ }
4280
+ }
4281
+ }
4282
+
4283
+ class AudioUndecodableError extends Error {
4284
+ config;
4285
+ constructor({
4286
+ message,
4287
+ config
4288
+ }) {
4289
+ super(message);
4290
+ this.name = "AudioUndecodableError";
4291
+ this.config = config;
4292
+ if (Error.captureStackTrace) {
4293
+ Error.captureStackTrace(this, AudioUndecodableError);
4294
+ }
4295
+ }
4296
+ }
4297
+
4256
4298
  // src/create-audio-decoder.ts
4257
- var internalCreateAudioDecoder = ({
4299
+ var internalCreateAudioDecoder = async ({
4258
4300
  onFrame,
4259
4301
  onError,
4260
4302
  controller,
@@ -4309,6 +4351,13 @@ var internalCreateAudioDecoder = ({
4309
4351
  if (controller) {
4310
4352
  controller._internals._mediaParserController._internals.signal.addEventListener("abort", onAbort);
4311
4353
  }
4354
+ const isConfigSupported = await AudioDecoder.isConfigSupported(config);
4355
+ if (!isConfigSupported) {
4356
+ throw new AudioUndecodableError({
4357
+ message: "Audio cannot be decoded by this browser",
4358
+ config
4359
+ });
4360
+ }
4312
4361
  audioDecoder.configure(config);
4313
4362
  const decode = async (audioSample) => {
4314
4363
  if (audioDecoder.state === "closed") {
@@ -4547,7 +4596,7 @@ var reencodeAudioTrack = async ({
4547
4596
  newAudioData.close();
4548
4597
  }
4549
4598
  });
4550
- const audioDecoder = internalCreateAudioDecoder({
4599
+ const audioDecoder = await internalCreateAudioDecoder({
4551
4600
  onFrame: async (audioData) => {
4552
4601
  await controller._internals._mediaParserController._internals.checkForAbortAndPause();
4553
4602
  await audioProcessingQueue.ioSynchronizer.waitForQueueSize(10);
@@ -4700,7 +4749,7 @@ var defaultOnVideoTrackHandler = async ({
4700
4749
  return Promise.resolve({
4701
4750
  type: "reencode",
4702
4751
  videoCodec: defaultVideoCodec,
4703
- rotate: rotate - track.rotation,
4752
+ rotate: undefined,
4704
4753
  resize: resizeOperation
4705
4754
  });
4706
4755
  }
@@ -4730,7 +4779,7 @@ var arrayBufferToUint8Array = (buffer) => {
4730
4779
  };
4731
4780
 
4732
4781
  // src/create-video-decoder.ts
4733
- var internalCreateVideoDecoder = ({
4782
+ var internalCreateVideoDecoder = async ({
4734
4783
  onFrame,
4735
4784
  onError,
4736
4785
  controller,
@@ -4775,6 +4824,13 @@ var internalCreateVideoDecoder = ({
4775
4824
  if (controller) {
4776
4825
  controller._internals._mediaParserController._internals.signal.addEventListener("abort", onAbort);
4777
4826
  }
4827
+ const isConfigSupported = await VideoDecoder.isConfigSupported(config);
4828
+ if (!isConfigSupported) {
4829
+ throw new VideoUndecodableError({
4830
+ message: "Video cannot be decoded by this browser",
4831
+ config
4832
+ });
4833
+ }
4778
4834
  videoDecoder.configure(config);
4779
4835
  const decode = async (sample) => {
4780
4836
  if (videoDecoder.state === "closed") {
@@ -5172,7 +5228,7 @@ var reencodeVideoTrack = async ({
5172
5228
  videoProcessingQueue.input(frame);
5173
5229
  }
5174
5230
  });
5175
- const videoDecoder = createVideoDecoder({
5231
+ const videoDecoder = await createVideoDecoder({
5176
5232
  track: videoDecoderConfig,
5177
5233
  onFrame: async (frame) => {
5178
5234
  await frameSorter.waitUntilProcessed();
@@ -5641,7 +5697,7 @@ var internalExtractFrames = ({
5641
5697
  throw new Error("expected at least one timestamp to extract but found zero");
5642
5698
  }
5643
5699
  controller.seek(timestampTargets[0]);
5644
- const decoder = createVideoDecoder({
5700
+ const decoder = await createVideoDecoder({
5645
5701
  onFrame: (frame) => {
5646
5702
  Log.trace(logLevel, "Received frame with timestamp", frame.timestamp);
5647
5703
  if (expectedFrames.length === 0) {
@@ -5655,13 +5711,10 @@ var internalExtractFrames = ({
5655
5711
  lastFrame = frame;
5656
5712
  return;
5657
5713
  }
5658
- if (expectedFrames[0] + 6667 < frame.timestamp && lastFrame) {
5714
+ if (expectedFrames[0] + 6667 < frame.timestamp && lastFrame && lastFrame !== lastFrameEmitted) {
5659
5715
  onFrame(lastFrame);
5660
5716
  lastFrameEmitted = lastFrame;
5661
5717
  expectedFrames.shift();
5662
- if (lastFrame) {
5663
- lastFrame.close();
5664
- }
5665
5718
  lastFrame = frame;
5666
5719
  return;
5667
5720
  }
@@ -5836,11 +5889,11 @@ var getPartialAudioData = async ({
5836
5889
  acknowledgeRemotionLicense: true,
5837
5890
  src,
5838
5891
  controller,
5839
- onAudioTrack: ({ track }) => {
5892
+ onAudioTrack: async ({ track }) => {
5840
5893
  if (signal.aborted) {
5841
5894
  return null;
5842
5895
  }
5843
- const audioDecoder = createAudioDecoder({
5896
+ const audioDecoder = await createAudioDecoder({
5844
5897
  track,
5845
5898
  onFrame: (sample) => {
5846
5899
  if (signal.aborted) {
@@ -5940,5 +5993,7 @@ export {
5940
5993
  canReencodeAudioTrack,
5941
5994
  canCopyVideoTrack,
5942
5995
  canCopyAudioTrack,
5943
- WebCodecsInternals
5996
+ WebCodecsInternals,
5997
+ VideoUndecodableError,
5998
+ AudioUndecodableError
5944
5999
  };
@@ -231,8 +231,39 @@ var makeIoSynchronizer = ({
231
231
  };
232
232
  };
233
233
 
234
+ // src/undecodable-error.ts
235
+ class VideoUndecodableError extends Error {
236
+ config;
237
+ constructor({
238
+ message,
239
+ config
240
+ }) {
241
+ super(message);
242
+ this.name = "VideoUndecodableError";
243
+ this.config = config;
244
+ if (Error.captureStackTrace) {
245
+ Error.captureStackTrace(this, VideoUndecodableError);
246
+ }
247
+ }
248
+ }
249
+
250
+ class AudioUndecodableError extends Error {
251
+ config;
252
+ constructor({
253
+ message,
254
+ config
255
+ }) {
256
+ super(message);
257
+ this.name = "AudioUndecodableError";
258
+ this.config = config;
259
+ if (Error.captureStackTrace) {
260
+ Error.captureStackTrace(this, AudioUndecodableError);
261
+ }
262
+ }
263
+ }
264
+
234
265
  // src/create-video-decoder.ts
235
- var internalCreateVideoDecoder = ({
266
+ var internalCreateVideoDecoder = async ({
236
267
  onFrame,
237
268
  onError,
238
269
  controller,
@@ -277,6 +308,13 @@ var internalCreateVideoDecoder = ({
277
308
  if (controller) {
278
309
  controller._internals._mediaParserController._internals.signal.addEventListener("abort", onAbort);
279
310
  }
311
+ const isConfigSupported = await VideoDecoder.isConfigSupported(config);
312
+ if (!isConfigSupported) {
313
+ throw new VideoUndecodableError({
314
+ message: "Video cannot be decoded by this browser",
315
+ config
316
+ });
317
+ }
280
318
  videoDecoder.configure(config);
281
319
  const decode = async (sample) => {
282
320
  if (videoDecoder.state === "closed") {
@@ -387,7 +425,7 @@ var internalExtractFrames = ({
387
425
  throw new Error("expected at least one timestamp to extract but found zero");
388
426
  }
389
427
  controller.seek(timestampTargets[0]);
390
- const decoder = createVideoDecoder({
428
+ const decoder = await createVideoDecoder({
391
429
  onFrame: (frame) => {
392
430
  Log.trace(logLevel, "Received frame with timestamp", frame.timestamp);
393
431
  if (expectedFrames.length === 0) {
@@ -401,13 +439,10 @@ var internalExtractFrames = ({
401
439
  lastFrame = frame;
402
440
  return;
403
441
  }
404
- if (expectedFrames[0] + 6667 < frame.timestamp && lastFrame) {
442
+ if (expectedFrames[0] + 6667 < frame.timestamp && lastFrame && lastFrame !== lastFrameEmitted) {
405
443
  onFrame(lastFrame);
406
444
  lastFrameEmitted = lastFrame;
407
445
  expectedFrames.shift();
408
- if (lastFrame) {
409
- lastFrame.close();
410
- }
411
446
  lastFrame = frame;
412
447
  return;
413
448
  }
@@ -69,11 +69,11 @@ const getPartialAudioData = async ({ src, fromSeconds, toSeconds, channelIndex,
69
69
  acknowledgeRemotionLicense: true,
70
70
  src,
71
71
  controller,
72
- onAudioTrack: ({ track }) => {
72
+ onAudioTrack: async ({ track }) => {
73
73
  if (signal.aborted) {
74
74
  return null;
75
75
  }
76
- const audioDecoder = (0, create_audio_decoder_1.createAudioDecoder)({
76
+ const audioDecoder = await (0, create_audio_decoder_1.createAudioDecoder)({
77
77
  track,
78
78
  onFrame: (sample) => {
79
79
  if (signal.aborted) {
package/dist/index.d.ts CHANGED
@@ -28,6 +28,7 @@ export type { AudioOperation, ConvertMediaOnAudioTrackHandler, } from './on-audi
28
28
  export type { ConvertMediaOnVideoTrackHandler, VideoOperation, } from './on-video-track-handler';
29
29
  export type { ResizeOperation } from './resizing/mode';
30
30
  export { rotateAndResizeVideoFrame } from './rotate-and-resize-video-frame';
31
+ export { AudioUndecodableError, VideoUndecodableError, } from './undecodable-error';
31
32
  export { createVideoEncoder } from './video-encoder';
32
33
  export type { WebCodecsVideoEncoder } from './video-encoder';
33
34
  export { webcodecsController } from './webcodecs-controller';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WebCodecsInternals = exports.webcodecsController = exports.createVideoEncoder = exports.rotateAndResizeVideoFrame = exports.getPartialAudioData = exports.getDefaultVideoCodec = exports.getDefaultAudioCodec = exports.getAvailableVideoCodecs = exports.getAvailableContainers = exports.getAvailableAudioCodecs = exports.extractFrames = exports.defaultOnVideoTrackHandler = exports.defaultOnAudioTrackHandler = exports.createVideoDecoder = exports.createAudioDecoder = exports.convertMedia = exports.convertAudioData = exports.canReencodeVideoTrack = exports.canReencodeAudioTrack = exports.canCopyVideoTrack = exports.canCopyAudioTrack = exports.createAudioEncoder = void 0;
3
+ exports.WebCodecsInternals = exports.webcodecsController = exports.createVideoEncoder = exports.VideoUndecodableError = exports.AudioUndecodableError = exports.rotateAndResizeVideoFrame = exports.getPartialAudioData = exports.getDefaultVideoCodec = exports.getDefaultAudioCodec = exports.getAvailableVideoCodecs = exports.getAvailableContainers = exports.getAvailableAudioCodecs = exports.extractFrames = exports.defaultOnVideoTrackHandler = exports.defaultOnAudioTrackHandler = exports.createVideoDecoder = exports.createAudioDecoder = exports.convertMedia = exports.convertAudioData = exports.canReencodeVideoTrack = exports.canReencodeAudioTrack = exports.canCopyVideoTrack = exports.canCopyAudioTrack = exports.createAudioEncoder = void 0;
4
4
  const rotate_and_resize_video_frame_1 = require("./rotate-and-resize-video-frame");
5
5
  const rotation_1 = require("./rotation");
6
6
  const set_remotion_imported_1 = require("./set-remotion-imported");
@@ -42,6 +42,9 @@ var get_partial_audio_data_1 = require("./get-partial-audio-data");
42
42
  Object.defineProperty(exports, "getPartialAudioData", { enumerable: true, get: function () { return get_partial_audio_data_1.getPartialAudioData; } });
43
43
  var rotate_and_resize_video_frame_2 = require("./rotate-and-resize-video-frame");
44
44
  Object.defineProperty(exports, "rotateAndResizeVideoFrame", { enumerable: true, get: function () { return rotate_and_resize_video_frame_2.rotateAndResizeVideoFrame; } });
45
+ var undecodable_error_1 = require("./undecodable-error");
46
+ Object.defineProperty(exports, "AudioUndecodableError", { enumerable: true, get: function () { return undecodable_error_1.AudioUndecodableError; } });
47
+ Object.defineProperty(exports, "VideoUndecodableError", { enumerable: true, get: function () { return undecodable_error_1.VideoUndecodableError; } });
45
48
  var video_encoder_1 = require("./video-encoder");
46
49
  Object.defineProperty(exports, "createVideoEncoder", { enumerable: true, get: function () { return video_encoder_1.createVideoEncoder; } });
47
50
  var webcodecs_controller_1 = require("./webcodecs-controller");
@@ -38,7 +38,7 @@ const internalExtractFrames = ({ src, onFrame, signal, timestampsInSeconds, ackn
38
38
  throw new Error('expected at least one timestamp to extract but found zero');
39
39
  }
40
40
  controller.seek(timestampTargets[0]);
41
- const decoder = (0, create_video_decoder_1.createVideoDecoder)({
41
+ const decoder = await (0, create_video_decoder_1.createVideoDecoder)({
42
42
  onFrame: (frame) => {
43
43
  log_1.Log.trace(logLevel, 'Received frame with timestamp', frame.timestamp);
44
44
  if (expectedFrames.length === 0) {
@@ -55,13 +55,12 @@ const internalExtractFrames = ({ src, onFrame, signal, timestampsInSeconds, ackn
55
55
  // A WebM might have a timestamp of 67000 but we request 66666
56
56
  // See a test with this problem in it-tests/rendering/frame-accuracy.test.ts
57
57
  // Solution: We allow a 10.000ms - 3.333ms = 6.667ms difference between the requested timestamp and the actual timestamp
58
- if (expectedFrames[0] + 6667 < frame.timestamp && lastFrame) {
58
+ if (expectedFrames[0] + 6667 < frame.timestamp &&
59
+ lastFrame &&
60
+ lastFrame !== lastFrameEmitted) {
59
61
  onFrame(lastFrame);
60
62
  lastFrameEmitted = lastFrame;
61
63
  expectedFrames.shift();
62
- if (lastFrame) {
63
- lastFrame.close();
64
- }
65
64
  lastFrame = frame;
66
65
  return;
67
66
  }
@@ -129,7 +129,7 @@ const reencodeAudioTrack = async ({ audioOperation, track, logLevel, abortConver
129
129
  newAudioData.close();
130
130
  },
131
131
  });
132
- const audioDecoder = (0, create_audio_decoder_1.internalCreateAudioDecoder)({
132
+ const audioDecoder = await (0, create_audio_decoder_1.internalCreateAudioDecoder)({
133
133
  onFrame: async (audioData) => {
134
134
  await controller._internals._mediaParserController._internals.checkForAbortAndPause();
135
135
  await audioProcessingQueue.ioSynchronizer.waitForQueueSize(10);
@@ -111,7 +111,7 @@ const reencodeVideoTrack = async ({ videoOperation, rotate, track, logLevel, abo
111
111
  videoProcessingQueue.input(frame);
112
112
  },
113
113
  });
114
- const videoDecoder = (0, create_video_decoder_1.createVideoDecoder)({
114
+ const videoDecoder = await (0, create_video_decoder_1.createVideoDecoder)({
115
115
  track: videoDecoderConfig,
116
116
  onFrame: async (frame) => {
117
117
  await frameSorter.waitUntilProcessed();
@@ -0,0 +1,14 @@
1
+ export declare class VideoUndecodableError extends Error {
2
+ config: VideoDecoderConfig;
3
+ constructor({ message, config, }: {
4
+ message: string;
5
+ config: VideoDecoderConfig;
6
+ });
7
+ }
8
+ export declare class AudioUndecodableError extends Error {
9
+ config: AudioDecoderConfig;
10
+ constructor({ message, config, }: {
11
+ message: string;
12
+ config: AudioDecoderConfig;
13
+ });
14
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AudioUndecodableError = exports.VideoUndecodableError = void 0;
4
+ class VideoUndecodableError extends Error {
5
+ constructor({ message, config, }) {
6
+ super(message);
7
+ this.name = 'VideoUndecodableError';
8
+ this.config = config;
9
+ if (Error.captureStackTrace) {
10
+ Error.captureStackTrace(this, VideoUndecodableError);
11
+ }
12
+ }
13
+ }
14
+ exports.VideoUndecodableError = VideoUndecodableError;
15
+ class AudioUndecodableError extends Error {
16
+ constructor({ message, config, }) {
17
+ super(message);
18
+ this.name = 'AudioUndecodableError';
19
+ this.config = config;
20
+ if (Error.captureStackTrace) {
21
+ Error.captureStackTrace(this, AudioUndecodableError);
22
+ }
23
+ }
24
+ }
25
+ exports.AudioUndecodableError = AudioUndecodableError;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/webcodecs",
3
- "version": "4.0.331",
3
+ "version": "4.0.333",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/esm/index.mjs",
@@ -19,8 +19,8 @@
19
19
  "author": "Jonny Burger <jonny@remotion.dev>",
20
20
  "license": "Remotion License (See https://remotion.dev/docs/webcodecs#license)",
21
21
  "dependencies": {
22
- "@remotion/media-parser": "4.0.331",
23
- "@remotion/licensing": "4.0.331"
22
+ "@remotion/licensing": "4.0.333",
23
+ "@remotion/media-parser": "4.0.333"
24
24
  },
25
25
  "peerDependencies": {},
26
26
  "devDependencies": {
@@ -29,8 +29,8 @@
29
29
  "vite": "5.4.19",
30
30
  "@playwright/test": "1.51.1",
31
31
  "eslint": "9.19.0",
32
- "@remotion/example-videos": "4.0.331",
33
- "@remotion/eslint-config-internal": "4.0.331"
32
+ "@remotion/eslint-config-internal": "4.0.333",
33
+ "@remotion/example-videos": "4.0.333"
34
34
  },
35
35
  "keywords": [],
36
36
  "publishConfig": {