@remotion/webcodecs 4.0.315 → 4.0.317

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.
@@ -362,7 +362,7 @@ var normalizeVideoRotation = (rotation) => {
362
362
  var rotateAndResizeVideoFrame = ({
363
363
  frame,
364
364
  rotation,
365
- needsToBeMultipleOfTwo,
365
+ needsToBeMultipleOfTwo = false,
366
366
  resizeOperation
367
367
  }) => {
368
368
  const normalized = (rotation % 360 + 360) % 360;
@@ -5719,6 +5719,7 @@ var WebCodecsInternals = {
5719
5719
  setRemotionImported();
5720
5720
  export {
5721
5721
  webcodecsController,
5722
+ rotateAndResizeVideoFrame,
5722
5723
  getDefaultVideoCodec,
5723
5724
  getDefaultAudioCodec,
5724
5725
  getAvailableVideoCodecs,
package/dist/index.d.ts CHANGED
@@ -26,6 +26,7 @@ export { getDefaultVideoCodec } from './get-default-video-codec';
26
26
  export type { AudioOperation, ConvertMediaOnAudioTrackHandler, } from './on-audio-track-handler';
27
27
  export type { ConvertMediaOnVideoTrackHandler, VideoOperation, } from './on-video-track-handler';
28
28
  export type { ResizeOperation } from './resizing/mode';
29
+ export { rotateAndResizeVideoFrame } from './rotate-and-resize-video-frame';
29
30
  export { createVideoEncoder } from './video-encoder';
30
31
  export type { WebCodecsVideoEncoder } from './video-encoder';
31
32
  export { webcodecsController } from './webcodecs-controller';
@@ -34,8 +35,8 @@ export declare const WebCodecsInternals: {
34
35
  rotateAndResizeVideoFrame: ({ frame, rotation, needsToBeMultipleOfTwo, resizeOperation, }: {
35
36
  frame: VideoFrame;
36
37
  rotation: number;
37
- needsToBeMultipleOfTwo: boolean;
38
38
  resizeOperation: import("./resizing/mode").ResizeOperation | null;
39
+ needsToBeMultipleOfTwo?: boolean;
39
40
  }) => VideoFrame;
40
41
  normalizeVideoRotation: (rotation: number) => number;
41
42
  calculateNewDimensionsFromDimensions: ({ width, height, rotation, resizeOperation, needsToBeMultipleOfTwo, }: {
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.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.rotateAndResizeVideoFrame = 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");
@@ -38,6 +38,8 @@ var get_default_audio_codec_1 = require("./get-default-audio-codec");
38
38
  Object.defineProperty(exports, "getDefaultAudioCodec", { enumerable: true, get: function () { return get_default_audio_codec_1.getDefaultAudioCodec; } });
39
39
  var get_default_video_codec_1 = require("./get-default-video-codec");
40
40
  Object.defineProperty(exports, "getDefaultVideoCodec", { enumerable: true, get: function () { return get_default_video_codec_1.getDefaultVideoCodec; } });
41
+ var rotate_and_resize_video_frame_2 = require("./rotate-and-resize-video-frame");
42
+ Object.defineProperty(exports, "rotateAndResizeVideoFrame", { enumerable: true, get: function () { return rotate_and_resize_video_frame_2.rotateAndResizeVideoFrame; } });
41
43
  var video_encoder_1 = require("./video-encoder");
42
44
  Object.defineProperty(exports, "createVideoEncoder", { enumerable: true, get: function () { return video_encoder_1.createVideoEncoder; } });
43
45
  var webcodecs_controller_1 = require("./webcodecs-controller");
@@ -3,6 +3,6 @@ export declare const normalizeVideoRotation: (rotation: number) => number;
3
3
  export declare const rotateAndResizeVideoFrame: ({ frame, rotation, needsToBeMultipleOfTwo, resizeOperation, }: {
4
4
  frame: VideoFrame;
5
5
  rotation: number;
6
- needsToBeMultipleOfTwo: boolean;
7
6
  resizeOperation: ResizeOperation | null;
7
+ needsToBeMultipleOfTwo?: boolean;
8
8
  }) => VideoFrame;
@@ -6,7 +6,7 @@ const normalizeVideoRotation = (rotation) => {
6
6
  return ((rotation % 360) + 360) % 360;
7
7
  };
8
8
  exports.normalizeVideoRotation = normalizeVideoRotation;
9
- const rotateAndResizeVideoFrame = ({ frame, rotation, needsToBeMultipleOfTwo, resizeOperation, }) => {
9
+ const rotateAndResizeVideoFrame = ({ frame, rotation, needsToBeMultipleOfTwo = false, resizeOperation, }) => {
10
10
  const normalized = ((rotation % 360) + 360) % 360;
11
11
  // No resize, no rotation
12
12
  if (normalized === 0 && resizeOperation === null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/webcodecs",
3
- "version": "4.0.315",
3
+ "version": "4.0.317",
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.315",
23
- "@remotion/licensing": "4.0.315"
22
+ "@remotion/licensing": "4.0.317",
23
+ "@remotion/media-parser": "4.0.317"
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/eslint-config-internal": "4.0.315",
33
- "@remotion/example-videos": "4.0.315"
32
+ "@remotion/example-videos": "4.0.317",
33
+ "@remotion/eslint-config-internal": "4.0.317"
34
34
  },
35
35
  "keywords": [],
36
36
  "publishConfig": {
@@ -1,24 +0,0 @@
1
- import type { MediaParserLogLevel } from '@remotion/media-parser';
2
- import type { WebCodecsController } from './webcodecs-controller';
3
- export type WebCodecsAudioDecoder = {
4
- decode: (audioSample: EncodedAudioChunkInit | EncodedAudioChunk) => void;
5
- close: () => void;
6
- flush: () => Promise<void>;
7
- waitForFinish: () => Promise<void>;
8
- waitForQueueToBeLessThan: (items: number) => Promise<void>;
9
- };
10
- export type CreateAudioDecoderInit = {
11
- onFrame: (frame: AudioData) => Promise<void> | void;
12
- onError: (error: Error) => void;
13
- controller: WebCodecsController | null;
14
- config: AudioDecoderConfig;
15
- logLevel: MediaParserLogLevel;
16
- };
17
- export declare const internalCreateAudioDecoder: ({ onFrame, onError, controller, config, logLevel, }: CreateAudioDecoderInit) => WebCodecsAudioDecoder;
18
- export declare const createAudioDecoder: ({ onFrame, onError, controller, track, logLevel, }: {
19
- track: AudioDecoderConfig;
20
- onFrame: (frame: AudioData) => Promise<void> | void;
21
- onError: (error: Error) => void;
22
- controller?: WebCodecsController | null;
23
- logLevel?: MediaParserLogLevel;
24
- }) => WebCodecsAudioDecoder;
@@ -1,106 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createAudioDecoder = exports.internalCreateAudioDecoder = void 0;
4
- const get_wave_audio_decoder_1 = require("./get-wave-audio-decoder");
5
- const io_synchronizer_1 = require("./io-manager/io-synchronizer");
6
- const internalCreateAudioDecoder = ({ onFrame, onError, controller, config, logLevel, }) => {
7
- if (controller &&
8
- controller._internals._mediaParserController._internals.signal.aborted) {
9
- throw new Error('Not creating audio decoder, already aborted');
10
- }
11
- const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)({
12
- logLevel,
13
- label: 'Audio decoder',
14
- controller,
15
- });
16
- if (config.codec === 'pcm-s16') {
17
- return (0, get_wave_audio_decoder_1.getWaveAudioDecoder)({
18
- onFrame,
19
- config,
20
- sampleFormat: 's16',
21
- logLevel,
22
- ioSynchronizer,
23
- onError,
24
- });
25
- }
26
- const audioDecoder = new AudioDecoder({
27
- async output(frame) {
28
- try {
29
- await onFrame(frame);
30
- }
31
- catch (err) {
32
- frame.close();
33
- onError(err);
34
- }
35
- ioSynchronizer.onOutput(frame.timestamp + (frame.duration ?? 0));
36
- },
37
- error(error) {
38
- onError(error);
39
- },
40
- });
41
- const close = () => {
42
- if (controller) {
43
- controller._internals._mediaParserController._internals.signal.removeEventListener('abort',
44
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
45
- onAbort);
46
- }
47
- if (audioDecoder.state === 'closed') {
48
- return;
49
- }
50
- audioDecoder.close();
51
- };
52
- const onAbort = () => {
53
- close();
54
- };
55
- if (controller) {
56
- controller._internals._mediaParserController._internals.signal.addEventListener('abort', onAbort);
57
- }
58
- audioDecoder.configure(config);
59
- const processSample = (audioSample) => {
60
- if (audioDecoder.state === 'closed') {
61
- return;
62
- }
63
- // Don't flush, it messes up the audio
64
- const chunk = audioSample instanceof EncodedAudioChunk
65
- ? audioSample
66
- : new EncodedAudioChunk(audioSample);
67
- audioDecoder.decode(chunk);
68
- // https://test-streams.mux.dev/x36xhzz/url_0/url_525/193039199_mp4_h264_aac_hd_7.ts
69
- // has a 16 byte audio sample at the end which chrome does not decode
70
- // Might be empty audio
71
- // For now only reporting chunks that are bigger than that
72
- // 16 was chosen arbitrarily, can be improved
73
- if (chunk.byteLength > 16) {
74
- ioSynchronizer.inputItem(chunk.timestamp);
75
- }
76
- };
77
- return {
78
- decode: (sample) => {
79
- processSample(sample);
80
- },
81
- waitForFinish: async () => {
82
- // Firefox might throw "Needs to be configured first"
83
- try {
84
- await audioDecoder.flush();
85
- }
86
- catch { }
87
- await ioSynchronizer.waitForFinish();
88
- },
89
- close,
90
- flush: async () => {
91
- await audioDecoder.flush();
92
- },
93
- waitForQueueToBeLessThan: ioSynchronizer.waitForQueueSize,
94
- };
95
- };
96
- exports.internalCreateAudioDecoder = internalCreateAudioDecoder;
97
- const createAudioDecoder = ({ onFrame, onError, controller, track, logLevel, }) => {
98
- return (0, exports.internalCreateAudioDecoder)({
99
- onFrame,
100
- onError,
101
- controller: controller ?? null,
102
- config: track,
103
- logLevel: logLevel ?? 'error',
104
- });
105
- };
106
- exports.createAudioDecoder = createAudioDecoder;
@@ -1,8 +0,0 @@
1
- export declare const extractFrames: ({ fromSeconds, toSeconds, width, height, src, onFrame, }: {
2
- fromSeconds: number;
3
- toSeconds: number;
4
- width: number;
5
- height: number;
6
- src: string;
7
- onFrame: (frame: VideoFrame) => void;
8
- }) => Promise<void>;
@@ -1,69 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.extractFrames = void 0;
4
- const media_parser_1 = require("@remotion/media-parser");
5
- const worker_1 = require("@remotion/media-parser/worker");
6
- const create_video_decoder_1 = require("./create-video-decoder");
7
- const extractFrames = async ({ fromSeconds, toSeconds, width, height, src, onFrame, }) => {
8
- const controller = (0, media_parser_1.mediaParserController)();
9
- controller.seek(fromSeconds);
10
- const segmentDuration = toSeconds - fromSeconds;
11
- const expectedFrames = [];
12
- try {
13
- await (0, worker_1.parseMediaOnWebWorker)({
14
- src: new URL(src, window.location.href).toString(),
15
- acknowledgeRemotionLicense: true,
16
- controller,
17
- onVideoTrack: ({ track }) => {
18
- const aspectRatio = track.width / track.height;
19
- const framesFitInWidth = Math.ceil(width / (height * aspectRatio));
20
- const timestampTargets = [];
21
- for (let i = 0; i < framesFitInWidth; i++) {
22
- timestampTargets.push(fromSeconds +
23
- ((segmentDuration * media_parser_1.WEBCODECS_TIMESCALE) / framesFitInWidth) *
24
- (i + 0.5));
25
- }
26
- const decoder = (0, create_video_decoder_1.createVideoDecoder)({
27
- onFrame: (frame) => {
28
- if (frame.timestamp >= expectedFrames[0] - 1) {
29
- expectedFrames.shift();
30
- onFrame(frame);
31
- }
32
- frame.close();
33
- },
34
- onError: console.error,
35
- track,
36
- });
37
- const queued = [];
38
- return async (sample) => {
39
- const nextTimestampWeWant = timestampTargets[0];
40
- if (nextTimestampWeWant === undefined) {
41
- throw new Error('this should not happen');
42
- }
43
- if (sample.type === 'key') {
44
- queued.length = 0;
45
- }
46
- queued.push(sample);
47
- if (sample.timestamp > nextTimestampWeWant) {
48
- expectedFrames.push(timestampTargets.shift());
49
- while (queued.length > 0) {
50
- const sam = queued.shift();
51
- await decoder.waitForQueueToBeLessThan(10);
52
- await decoder.decode(sam);
53
- }
54
- if (timestampTargets.length === 0) {
55
- await decoder.flush();
56
- controller.abort();
57
- }
58
- }
59
- };
60
- },
61
- });
62
- }
63
- catch (e) {
64
- if (!(0, media_parser_1.hasBeenAborted)(e)) {
65
- throw e;
66
- }
67
- }
68
- };
69
- exports.extractFrames = extractFrames;
@@ -1,23 +0,0 @@
1
- import type { MediaParserLogLevel, MediaParserVideoSample } from '@remotion/media-parser';
2
- import type { WebCodecsController } from './webcodecs-controller';
3
- export type WebCodecsVideoDecoder = {
4
- decode: (videoSample: MediaParserVideoSample | EncodedVideoChunk) => void;
5
- close: () => void;
6
- flush: () => Promise<void>;
7
- waitForFinish: () => Promise<void>;
8
- waitForQueueToBeLessThan: (items: number) => Promise<void>;
9
- };
10
- export declare const internalCreateVideoDecoder: ({ onFrame, onError, controller, config, logLevel, }: {
11
- onFrame: (frame: VideoFrame) => Promise<void> | void;
12
- onError: (error: Error) => void;
13
- controller: WebCodecsController | null;
14
- config: VideoDecoderConfig;
15
- logLevel: MediaParserLogLevel;
16
- }) => WebCodecsVideoDecoder;
17
- export declare const createVideoDecoder: ({ onFrame, onError, controller, track, logLevel, }: {
18
- track: VideoDecoderConfig;
19
- onFrame: (frame: VideoFrame) => Promise<void> | void;
20
- onError: (error: Error) => void;
21
- controller?: WebCodecsController;
22
- logLevel?: MediaParserLogLevel;
23
- }) => WebCodecsVideoDecoder;
@@ -1,80 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createVideoDecoder = exports.internalCreateVideoDecoder = void 0;
4
- const io_synchronizer_1 = require("./io-manager/io-synchronizer");
5
- const log_1 = require("./log");
6
- const internalCreateVideoDecoder = ({ onFrame, onError, controller, config, logLevel, }) => {
7
- const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)({
8
- logLevel,
9
- label: 'Video decoder',
10
- controller,
11
- });
12
- const videoDecoder = new VideoDecoder({
13
- async output(frame) {
14
- try {
15
- await onFrame(frame);
16
- }
17
- catch (err) {
18
- onError(err);
19
- frame.close();
20
- }
21
- ioSynchronizer.onOutput(frame.timestamp);
22
- },
23
- error(error) {
24
- onError(error);
25
- },
26
- });
27
- const close = () => {
28
- if (controller) {
29
- controller._internals._mediaParserController._internals.signal.removeEventListener('abort',
30
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
31
- onAbort);
32
- }
33
- if (videoDecoder.state === 'closed') {
34
- return;
35
- }
36
- videoDecoder.close();
37
- };
38
- const onAbort = () => {
39
- close();
40
- };
41
- if (controller) {
42
- controller._internals._mediaParserController._internals.signal.addEventListener('abort', onAbort);
43
- }
44
- videoDecoder.configure(config);
45
- const decode = (sample) => {
46
- if (videoDecoder.state === 'closed') {
47
- return;
48
- }
49
- const encodedChunk = sample instanceof EncodedVideoChunk
50
- ? sample
51
- : new EncodedVideoChunk(sample);
52
- videoDecoder.decode(encodedChunk);
53
- ioSynchronizer.inputItem(sample.timestamp);
54
- };
55
- return {
56
- decode,
57
- waitForFinish: async () => {
58
- await videoDecoder.flush();
59
- log_1.Log.verbose(logLevel, 'Flushed video decoder');
60
- await ioSynchronizer.waitForFinish();
61
- log_1.Log.verbose(logLevel, 'IO synchro finished');
62
- },
63
- close,
64
- flush: async () => {
65
- await videoDecoder.flush();
66
- },
67
- waitForQueueToBeLessThan: ioSynchronizer.waitForQueueSize,
68
- };
69
- };
70
- exports.internalCreateVideoDecoder = internalCreateVideoDecoder;
71
- const createVideoDecoder = ({ onFrame, onError, controller, track, logLevel, }) => {
72
- return (0, exports.internalCreateVideoDecoder)({
73
- onFrame,
74
- onError,
75
- controller: controller ?? null,
76
- config: track,
77
- logLevel: logLevel ?? 'info',
78
- });
79
- };
80
- exports.createVideoDecoder = createVideoDecoder;