@remotion/webcodecs 4.0.210

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 (64) hide show
  1. package/LICENSE.md +49 -0
  2. package/README.md +18 -0
  3. package/dist/audio-decoder-config.d.ts +2 -0
  4. package/dist/audio-decoder-config.js +13 -0
  5. package/dist/audio-decoder.d.ts +15 -0
  6. package/dist/audio-decoder.js +85 -0
  7. package/dist/audio-encoder-config.d.ts +2 -0
  8. package/dist/audio-encoder-config.js +13 -0
  9. package/dist/audio-encoder.d.ts +16 -0
  10. package/dist/audio-encoder.js +90 -0
  11. package/dist/codec-id.d.ts +2 -0
  12. package/dist/codec-id.js +2 -0
  13. package/dist/convert-media.d.ts +26 -0
  14. package/dist/convert-media.js +86 -0
  15. package/dist/create-audio-decoder.d.ts +7 -0
  16. package/dist/create-audio-decoder.js +18 -0
  17. package/dist/create-decoder.d.ts +6 -0
  18. package/dist/create-decoder.js +32 -0
  19. package/dist/create-encoder.d.ts +9 -0
  20. package/dist/create-encoder.js +46 -0
  21. package/dist/create-video-decoder.d.ts +6 -0
  22. package/dist/create-video-decoder.js +18 -0
  23. package/dist/decoder.d.ts +7 -0
  24. package/dist/decoder.js +44 -0
  25. package/dist/encoder.d.ts +7 -0
  26. package/dist/encoder.js +43 -0
  27. package/dist/error-cause.d.ts +8 -0
  28. package/dist/error-cause.js +3 -0
  29. package/dist/esm/index.mjs +793 -0
  30. package/dist/get-config.d.ts +1 -0
  31. package/dist/get-config.js +21 -0
  32. package/dist/get-description.d.ts +6 -0
  33. package/dist/get-description.js +20 -0
  34. package/dist/get-samples.d.ts +6 -0
  35. package/dist/get-samples.js +24 -0
  36. package/dist/index.d.ts +5 -0
  37. package/dist/index.js +13 -0
  38. package/dist/load-mp4-file.d.ts +8 -0
  39. package/dist/load-mp4-file.js +37 -0
  40. package/dist/on-audio-track.d.ts +15 -0
  41. package/dist/on-audio-track.js +105 -0
  42. package/dist/on-video-track.d.ts +15 -0
  43. package/dist/on-video-track.js +101 -0
  44. package/dist/reencode-video.d.ts +1 -0
  45. package/dist/reencode-video.js +68 -0
  46. package/dist/resolve-audio-action.d.ts +16 -0
  47. package/dist/resolve-audio-action.js +30 -0
  48. package/dist/resolve-video-action.d.ts +15 -0
  49. package/dist/resolve-video-action.js +30 -0
  50. package/dist/video-decoder-config.d.ts +1 -0
  51. package/dist/video-decoder-config.js +24 -0
  52. package/dist/video-decoder.d.ts +14 -0
  53. package/dist/video-decoder.js +87 -0
  54. package/dist/video-encoder-config.d.ts +1 -0
  55. package/dist/video-encoder-config.js +24 -0
  56. package/dist/video-encoder.d.ts +13 -0
  57. package/dist/video-encoder.js +90 -0
  58. package/dist/video-parser.d.ts +1 -0
  59. package/dist/video-parser.js +51 -0
  60. package/dist/wait-for-dequeue.d.ts +5 -0
  61. package/dist/wait-for-dequeue.js +51 -0
  62. package/dist/with-resolvers.d.ts +5 -0
  63. package/dist/with-resolvers.js +13 -0
  64. package/package.json +37 -0
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createVideoDecoder = void 0;
4
+ const createVideoDecoder = ({ onFrame, onError, signal, config, }) => {
5
+ let outputQueue = Promise.resolve();
6
+ let outputQueueSize = 0;
7
+ let dequeueResolver = () => { };
8
+ const videoDecoder = new VideoDecoder({
9
+ output(inputFrame) {
10
+ outputQueueSize++;
11
+ outputQueue = outputQueue
12
+ .then(() => onFrame(inputFrame))
13
+ .then(() => {
14
+ outputQueueSize--;
15
+ dequeueResolver();
16
+ return Promise.resolve();
17
+ });
18
+ },
19
+ error(error) {
20
+ onError(error);
21
+ },
22
+ });
23
+ const close = () => {
24
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
25
+ signal.removeEventListener('abort', onAbort);
26
+ if (videoDecoder.state === 'closed') {
27
+ return;
28
+ }
29
+ videoDecoder.close();
30
+ };
31
+ const onAbort = () => {
32
+ close();
33
+ };
34
+ signal.addEventListener('abort', onAbort);
35
+ const getQueueSize = () => {
36
+ return videoDecoder.decodeQueueSize + outputQueueSize;
37
+ };
38
+ videoDecoder.configure(config);
39
+ const waitForDequeue = async () => {
40
+ await new Promise((r) => {
41
+ dequeueResolver = r;
42
+ videoDecoder.addEventListener('dequeue', () => r(), {
43
+ once: true,
44
+ });
45
+ });
46
+ };
47
+ const waitForFinish = async () => {
48
+ while (getQueueSize() > 0) {
49
+ await waitForDequeue();
50
+ }
51
+ };
52
+ const processSample = async (sample) => {
53
+ if (videoDecoder.state === 'closed') {
54
+ return;
55
+ }
56
+ while (getQueueSize() > 10) {
57
+ await waitForDequeue();
58
+ }
59
+ // @ts-expect-error - can have changed in the meanwhile
60
+ if (videoDecoder.state === 'closed') {
61
+ return;
62
+ }
63
+ if (sample.type === 'key') {
64
+ await videoDecoder.flush();
65
+ }
66
+ videoDecoder.decode(new EncodedVideoChunk(sample));
67
+ };
68
+ let inputQueue = Promise.resolve();
69
+ return {
70
+ processSample: (sample) => {
71
+ inputQueue = inputQueue.then(() => processSample(sample));
72
+ return inputQueue;
73
+ },
74
+ waitForFinish: async () => {
75
+ await videoDecoder.flush();
76
+ await waitForFinish();
77
+ await outputQueue;
78
+ await inputQueue;
79
+ },
80
+ close,
81
+ getQueueSize,
82
+ flush: async () => {
83
+ await videoDecoder.flush();
84
+ },
85
+ };
86
+ };
87
+ exports.createVideoDecoder = createVideoDecoder;
@@ -0,0 +1 @@
1
+ export declare const getVideoEncoderConfig: (config: VideoEncoderConfig) => Promise<VideoEncoderConfig | null>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVideoEncoderConfig = void 0;
4
+ const getVideoEncoderConfig = async (config) => {
5
+ if (typeof VideoEncoder === 'undefined') {
6
+ return null;
7
+ }
8
+ const hardware = {
9
+ ...config,
10
+ hardwareAcceleration: 'prefer-hardware',
11
+ };
12
+ if ((await VideoEncoder.isConfigSupported(hardware)).supported) {
13
+ return hardware;
14
+ }
15
+ const software = {
16
+ ...config,
17
+ hardwareAcceleration: 'prefer-software',
18
+ };
19
+ if ((await VideoEncoder.isConfigSupported(software)).supported) {
20
+ return software;
21
+ }
22
+ return null;
23
+ };
24
+ exports.getVideoEncoderConfig = getVideoEncoderConfig;
@@ -0,0 +1,13 @@
1
+ export type WebCodecsVideoEncoder = {
2
+ encodeFrame: (videoFrame: VideoFrame) => Promise<void>;
3
+ waitForFinish: () => Promise<void>;
4
+ close: () => void;
5
+ getQueueSize: () => number;
6
+ flush: () => Promise<void>;
7
+ };
8
+ export declare const createVideoEncoder: ({ onChunk, onError, signal, config, }: {
9
+ onChunk: (chunk: EncodedVideoChunk) => Promise<void>;
10
+ onError: (error: DOMException) => void;
11
+ signal: AbortSignal;
12
+ config: VideoEncoderConfig;
13
+ }) => WebCodecsVideoEncoder;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createVideoEncoder = void 0;
4
+ const createVideoEncoder = ({ onChunk, onError, signal, config, }) => {
5
+ if (signal.aborted) {
6
+ throw new Error('Not creating video encoder, already aborted');
7
+ }
8
+ let outputQueue = Promise.resolve();
9
+ let outputQueueSize = 0;
10
+ let dequeueResolver = () => { };
11
+ const encoder = new VideoEncoder({
12
+ error(error) {
13
+ onError(error);
14
+ },
15
+ output(chunk) {
16
+ outputQueueSize++;
17
+ outputQueue = outputQueue
18
+ .then(() => onChunk(chunk))
19
+ .then(() => {
20
+ outputQueueSize--;
21
+ dequeueResolver();
22
+ return Promise.resolve();
23
+ });
24
+ },
25
+ });
26
+ const close = () => {
27
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
28
+ signal.removeEventListener('abort', onAbort);
29
+ if (encoder.state === 'closed') {
30
+ return;
31
+ }
32
+ encoder.close();
33
+ };
34
+ const onAbort = () => {
35
+ close();
36
+ };
37
+ signal.addEventListener('abort', onAbort);
38
+ const getQueueSize = () => {
39
+ return encoder.encodeQueueSize + outputQueueSize;
40
+ };
41
+ encoder.configure(config);
42
+ let framesProcessed = 0;
43
+ const waitForDequeue = async () => {
44
+ await new Promise((r) => {
45
+ dequeueResolver = r;
46
+ encoder.addEventListener('dequeue', () => r(), {
47
+ once: true,
48
+ });
49
+ });
50
+ };
51
+ const waitForFinish = async () => {
52
+ while (getQueueSize() > 0) {
53
+ await waitForDequeue();
54
+ }
55
+ };
56
+ const encodeFrame = async (frame) => {
57
+ if (encoder.state === 'closed') {
58
+ return;
59
+ }
60
+ while (getQueueSize() > 10) {
61
+ await waitForDequeue();
62
+ }
63
+ // @ts-expect-error - can have changed in the meanwhile
64
+ if (encoder.state === 'closed') {
65
+ return;
66
+ }
67
+ encoder.encode(frame, {
68
+ keyFrame: framesProcessed % 40 === 0,
69
+ });
70
+ framesProcessed++;
71
+ };
72
+ let inputQueue = Promise.resolve();
73
+ return {
74
+ encodeFrame: (frame) => {
75
+ inputQueue = inputQueue.then(() => encodeFrame(frame));
76
+ return inputQueue;
77
+ },
78
+ waitForFinish: async () => {
79
+ await encoder.flush();
80
+ await outputQueue;
81
+ await waitForFinish();
82
+ },
83
+ close,
84
+ getQueueSize,
85
+ flush: async () => {
86
+ await encoder.flush();
87
+ },
88
+ };
89
+ };
90
+ exports.createVideoEncoder = createVideoEncoder;
@@ -0,0 +1 @@
1
+ export declare const parseVideo: (file: File) => Promise<void>;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseVideo = void 0;
4
+ const media_parser_1 = require("@remotion/media-parser");
5
+ const web_file_1 = require("@remotion/media-parser/web-file");
6
+ const parseVideo = async (file) => {
7
+ const videoDecoder = new VideoDecoder({
8
+ output(inputFrame) {
9
+ console.log('frame', inputFrame);
10
+ inputFrame.close();
11
+ },
12
+ error(error) {
13
+ console.error(error);
14
+ },
15
+ });
16
+ await (0, media_parser_1.parseMedia)({
17
+ src: file,
18
+ reader: web_file_1.webFileReader,
19
+ onVideoTrack: (track) => {
20
+ videoDecoder.configure({
21
+ ...track,
22
+ hardwareAcceleration: 'no-preference',
23
+ });
24
+ return (chunk) => {
25
+ videoDecoder.decode(new EncodedVideoChunk(chunk));
26
+ };
27
+ },
28
+ onAudioTrack: (track) => {
29
+ const audioDecoder = new AudioDecoder({
30
+ output(inputFrame) {
31
+ console.log('audio frame', inputFrame);
32
+ inputFrame.close();
33
+ },
34
+ error(error) {
35
+ console.error(error);
36
+ },
37
+ });
38
+ audioDecoder.configure({
39
+ codec: track.codec,
40
+ sampleRate: track.sampleRate,
41
+ numberOfChannels: track.numberOfChannels,
42
+ description: track.description,
43
+ });
44
+ console.log('audio track', track);
45
+ return (audioSample) => {
46
+ audioDecoder.decode(new EncodedAudioChunk(audioSample));
47
+ };
48
+ },
49
+ });
50
+ };
51
+ exports.parseVideo = parseVideo;
@@ -0,0 +1,5 @@
1
+ /// <reference types="dom-webcodecs" />
2
+ export declare const decoderWaitForDequeue: (videoDecoder: VideoDecoder | AudioDecoder) => Promise<void>;
3
+ export declare const decoderWaitForFinish: (videoDecoder: VideoDecoder | AudioDecoder) => Promise<void>;
4
+ export declare const encoderWaitForDequeue: (videoEncoder: VideoEncoder | AudioEncoder) => Promise<void>;
5
+ export declare const encoderWaitForFinish: (videoEncoder: VideoEncoder | AudioEncoder) => Promise<void>;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.encoderWaitForFinish = exports.encoderWaitForDequeue = exports.decoderWaitForFinish = exports.decoderWaitForDequeue = void 0;
4
+ const decoderWaitForDequeue = async (videoDecoder) => {
5
+ while (videoDecoder.decodeQueueSize > 10) {
6
+ await new Promise((r) => {
7
+ // @ts-expect-error exists
8
+ videoDecoder.addEventListener('dequeue', () => r(), {
9
+ once: true,
10
+ });
11
+ });
12
+ }
13
+ };
14
+ exports.decoderWaitForDequeue = decoderWaitForDequeue;
15
+ const decoderWaitForFinish = async (videoDecoder) => {
16
+ while (videoDecoder.decodeQueueSize > 0) {
17
+ await new Promise((r) => {
18
+ // @ts-expect-error exists
19
+ videoDecoder.addEventListener('dequeue', () => r(), {
20
+ once: true,
21
+ });
22
+ });
23
+ }
24
+ await videoDecoder.flush();
25
+ };
26
+ exports.decoderWaitForFinish = decoderWaitForFinish;
27
+ // Queue goes way higher but this will eat more memory right?
28
+ // But if not done this way, quality is worse
29
+ const encoderWaitForDequeue = async (videoEncoder) => {
30
+ while (videoEncoder.encodeQueueSize > 10) {
31
+ await new Promise((r) => {
32
+ // @ts-expect-error exists
33
+ videoEncoder.addEventListener('dequeue', () => r(), {
34
+ once: true,
35
+ });
36
+ });
37
+ }
38
+ };
39
+ exports.encoderWaitForDequeue = encoderWaitForDequeue;
40
+ const encoderWaitForFinish = async (videoEncoder) => {
41
+ while (videoEncoder.encodeQueueSize > 0) {
42
+ await new Promise((r) => {
43
+ // @ts-expect-error exists
44
+ videoEncoder.addEventListener('dequeue', () => r(), {
45
+ once: true,
46
+ });
47
+ });
48
+ }
49
+ await videoEncoder.flush();
50
+ };
51
+ exports.encoderWaitForFinish = encoderWaitForFinish;
@@ -0,0 +1,5 @@
1
+ export declare const withResolvers: <T>() => {
2
+ promise: Promise<T>;
3
+ resolve: (value: T | PromiseLike<T>) => void;
4
+ reject: (reason?: any) => void;
5
+ };
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withResolvers = void 0;
4
+ const withResolvers = function () {
5
+ let resolve;
6
+ let reject;
7
+ const promise = new Promise((res, rej) => {
8
+ resolve = res;
9
+ reject = rej;
10
+ });
11
+ return { promise, resolve: resolve, reject: reject };
12
+ };
13
+ exports.withResolvers = withResolvers;
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@remotion/webcodecs",
3
+ "version": "4.0.210",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "module": "dist/esm/index.mjs",
7
+ "sideEffects": false,
8
+ "repository": {
9
+ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/webcodecs"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/remotion-dev/remotion/issues"
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "author": "Jonny Burger <jonny@remotion.dev>",
18
+ "license": "SEE LICENSE IN LICENSE.md",
19
+ "dependencies": {
20
+ "@remotion/media-parser": "4.0.210"
21
+ },
22
+ "peerDependencies": {},
23
+ "devDependencies": {
24
+ "@types/dom-webcodecs": "0.1.11"
25
+ },
26
+ "keywords": [],
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "description": "Media conversion in the browser",
31
+ "scripts": {
32
+ "formatting": "prettier src --check",
33
+ "lint": "eslint src --ext ts,tsx",
34
+ "build": "tsc -d && bun --env-file=../.env.bundle bundle.ts",
35
+ "watch": "tsc -w"
36
+ }
37
+ }