@remotion/webcodecs 4.0.254 → 4.0.256
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.
- package/dist/codec-id.d.ts +2 -0
- package/dist/create/matroska/matroska-utils.d.ts +1 -1
- package/dist/resolve-audio-action.d.ts +15 -0
- package/dist/resolve-audio-action.js +30 -0
- package/dist/resolve-video-action.d.ts +15 -0
- package/dist/resolve-video-action.js +33 -0
- package/dist/rotate-video-frame.d.ts +5 -0
- package/dist/rotate-video-frame.js +48 -0
- package/dist/select-container-creator.d.ts +1 -1
- package/dist/with-resolvers.d.ts +5 -0
- package/dist/with-resolvers.js +13 -0
- package/package.json +5 -5
- package/dist/controller.d.ts +0 -16
- package/dist/controller.js +0 -16
- package/dist/emitter.d.ts +0 -20
- package/dist/emitter.js +0 -29
- package/dist/esm/node.mjs +0 -71
- package/dist/test/create-matroska.test.d.ts +0 -1
- package/dist/test/create-matroska.test.js +0 -103
- package/dist/test/stsd.test.d.ts +0 -1
- package/dist/test/stsd.test.js +0 -261
- package/dist/writers/node.d.ts +0 -4
- package/dist/writers/node.js +0 -74
- package/dist/writers/writer.d.ts +0 -15
- /package/dist/{writers/writer.js → codec-id.js} +0 -0
|
@@ -19,7 +19,7 @@ export type EbmlParsedOrUint8Array<T extends Ebml> = {
|
|
|
19
19
|
value: EbmlValueOrUint8Array<T>;
|
|
20
20
|
minVintWidth: number | null;
|
|
21
21
|
};
|
|
22
|
-
export declare const measureEBMLVarInt: (value: number) => 2 | 1 |
|
|
22
|
+
export declare const measureEBMLVarInt: (value: number) => 2 | 1 | 6 | 5 | 3 | 4;
|
|
23
23
|
export declare const getVariableInt: (value: number, minWidth: number | null) => Uint8Array;
|
|
24
24
|
export declare const makeMatroskaBytes: (fields: PossibleEbmlOrUint8Array) => BytesAndOffset;
|
|
25
25
|
export type PossibleEbmlOrUint8Array = Prettify<{
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AudioTrack } from '@remotion/media-parser';
|
|
2
|
+
import type { ConvertMediaAudioCodec } from './codec-id';
|
|
3
|
+
export type AudioOperation = 'reencode' | 'copy' | 'drop';
|
|
4
|
+
export type ResolveAudioActionFn = (options: {
|
|
5
|
+
canReencode: boolean;
|
|
6
|
+
canCopy: boolean;
|
|
7
|
+
}) => AudioOperation | Promise<AudioOperation>;
|
|
8
|
+
export declare const defaultResolveAudioAction: ResolveAudioActionFn;
|
|
9
|
+
export declare const resolveAudioAction: ({ audioDecoderConfig, audioEncoderConfig, track, audioCodec, resolverFunction, }: {
|
|
10
|
+
audioDecoderConfig: AudioDecoderConfig | null;
|
|
11
|
+
audioEncoderConfig: AudioEncoderConfig | null;
|
|
12
|
+
track: AudioTrack;
|
|
13
|
+
audioCodec: ConvertMediaAudioCodec;
|
|
14
|
+
resolverFunction: ResolveAudioActionFn;
|
|
15
|
+
}) => Promise<AudioOperation>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveAudioAction = exports.defaultResolveAudioAction = void 0;
|
|
4
|
+
const canCopyAudioTrack = (inputCodec, outputCodec) => {
|
|
5
|
+
if (outputCodec === 'opus') {
|
|
6
|
+
return inputCodec === 'opus';
|
|
7
|
+
}
|
|
8
|
+
throw new Error(`Unhandled codec: ${outputCodec}`);
|
|
9
|
+
};
|
|
10
|
+
const defaultResolveAudioAction = ({ canReencode, canCopy, }) => {
|
|
11
|
+
if (canCopy) {
|
|
12
|
+
return 'copy';
|
|
13
|
+
}
|
|
14
|
+
if (canReencode) {
|
|
15
|
+
return 'reencode';
|
|
16
|
+
}
|
|
17
|
+
// TODO: Make a fail option?
|
|
18
|
+
return 'drop';
|
|
19
|
+
};
|
|
20
|
+
exports.defaultResolveAudioAction = defaultResolveAudioAction;
|
|
21
|
+
const resolveAudioAction = async ({ audioDecoderConfig, audioEncoderConfig, track, audioCodec, resolverFunction, }) => {
|
|
22
|
+
const canReencode = Boolean(audioDecoderConfig && audioEncoderConfig);
|
|
23
|
+
const canCopy = canCopyAudioTrack(track.codecWithoutConfig, audioCodec);
|
|
24
|
+
const resolved = await resolverFunction({
|
|
25
|
+
canReencode,
|
|
26
|
+
canCopy,
|
|
27
|
+
});
|
|
28
|
+
return resolved;
|
|
29
|
+
};
|
|
30
|
+
exports.resolveAudioAction = resolveAudioAction;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { VideoTrack } from '@remotion/media-parser';
|
|
2
|
+
import type { ConvertMediaVideoCodec } from './codec-id';
|
|
3
|
+
export type VideoOperation = 'reencode' | 'copy' | 'drop';
|
|
4
|
+
export type ResolveVideoActionFn = (options: {
|
|
5
|
+
canReencode: boolean;
|
|
6
|
+
canCopy: boolean;
|
|
7
|
+
}) => VideoOperation | Promise<VideoOperation>;
|
|
8
|
+
export declare const defaultResolveVideoAction: ResolveVideoActionFn;
|
|
9
|
+
export declare const resolveVideoAction: ({ videoDecoderConfig, videoEncoderConfig, track, videoCodec, resolverFunction, }: {
|
|
10
|
+
videoDecoderConfig: VideoDecoderConfig | null;
|
|
11
|
+
videoEncoderConfig: VideoEncoderConfig | null;
|
|
12
|
+
videoCodec: ConvertMediaVideoCodec;
|
|
13
|
+
track: VideoTrack;
|
|
14
|
+
resolverFunction: ResolveVideoActionFn;
|
|
15
|
+
}) => Promise<VideoOperation>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveVideoAction = exports.defaultResolveVideoAction = void 0;
|
|
4
|
+
const canCopyVideoTrack = (inputCodec, outputCodec) => {
|
|
5
|
+
if (outputCodec === 'vp8') {
|
|
6
|
+
return inputCodec === 'vp8';
|
|
7
|
+
}
|
|
8
|
+
if (outputCodec === 'vp9') {
|
|
9
|
+
return inputCodec === 'vp9';
|
|
10
|
+
}
|
|
11
|
+
throw new Error(`Unhandled codec: ${outputCodec}`);
|
|
12
|
+
};
|
|
13
|
+
const defaultResolveVideoAction = ({ canReencode, canCopy, }) => {
|
|
14
|
+
if (canCopy) {
|
|
15
|
+
return 'copy';
|
|
16
|
+
}
|
|
17
|
+
if (canReencode) {
|
|
18
|
+
return 'reencode';
|
|
19
|
+
}
|
|
20
|
+
// TODO: Make a fail option?
|
|
21
|
+
return 'drop';
|
|
22
|
+
};
|
|
23
|
+
exports.defaultResolveVideoAction = defaultResolveVideoAction;
|
|
24
|
+
const resolveVideoAction = async ({ videoDecoderConfig, videoEncoderConfig, track, videoCodec, resolverFunction, }) => {
|
|
25
|
+
const canReencode = Boolean(videoDecoderConfig && videoEncoderConfig);
|
|
26
|
+
const canCopy = canCopyVideoTrack(track.codecWithoutConfig, videoCodec);
|
|
27
|
+
const resolved = await resolverFunction({
|
|
28
|
+
canReencode,
|
|
29
|
+
canCopy,
|
|
30
|
+
});
|
|
31
|
+
return resolved;
|
|
32
|
+
};
|
|
33
|
+
exports.resolveVideoAction = resolveVideoAction;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rotateVideoFrame = exports.normalizeVideoRotation = void 0;
|
|
4
|
+
const rotation_1 = require("./rotation");
|
|
5
|
+
const normalizeVideoRotation = (rotation) => {
|
|
6
|
+
return ((rotation % 360) + 360) % 360;
|
|
7
|
+
};
|
|
8
|
+
exports.normalizeVideoRotation = normalizeVideoRotation;
|
|
9
|
+
const rotateVideoFrame = ({ frame, rotation, }) => {
|
|
10
|
+
var _a;
|
|
11
|
+
const normalized = ((rotation % 360) + 360) % 360;
|
|
12
|
+
if (normalized % 360 === 0) {
|
|
13
|
+
return frame;
|
|
14
|
+
}
|
|
15
|
+
if (normalized % 90 !== 0) {
|
|
16
|
+
throw new Error('Only 90 degree rotations are supported');
|
|
17
|
+
}
|
|
18
|
+
const { height, width } = (0, rotation_1.calculateNewDimensionsFromDimensions)({
|
|
19
|
+
height: frame.displayHeight,
|
|
20
|
+
width: frame.displayWidth,
|
|
21
|
+
rotation,
|
|
22
|
+
});
|
|
23
|
+
const canvas = new OffscreenCanvas(width, height);
|
|
24
|
+
const ctx = canvas.getContext('2d');
|
|
25
|
+
if (!ctx) {
|
|
26
|
+
throw new Error('Could not get 2d context');
|
|
27
|
+
}
|
|
28
|
+
canvas.width = width;
|
|
29
|
+
canvas.height = height;
|
|
30
|
+
if (normalized === 90) {
|
|
31
|
+
ctx.translate(width, 0);
|
|
32
|
+
}
|
|
33
|
+
else if (normalized === 180) {
|
|
34
|
+
ctx.translate(width, height);
|
|
35
|
+
}
|
|
36
|
+
else if (normalized === 270) {
|
|
37
|
+
ctx.translate(0, height);
|
|
38
|
+
}
|
|
39
|
+
ctx.rotate(normalized * (Math.PI / 180));
|
|
40
|
+
ctx.drawImage(frame, 0, 0);
|
|
41
|
+
return new VideoFrame(canvas, {
|
|
42
|
+
displayHeight: height,
|
|
43
|
+
displayWidth: width,
|
|
44
|
+
duration: (_a = frame.duration) !== null && _a !== void 0 ? _a : undefined,
|
|
45
|
+
timestamp: frame.timestamp,
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
exports.rotateVideoFrame = rotateVideoFrame;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ConvertMediaContainer } from './get-available-containers';
|
|
2
|
-
export declare const selectContainerCreator: (container: ConvertMediaContainer) => ({
|
|
2
|
+
export declare const selectContainerCreator: (container: ConvertMediaContainer) => ({ filename, logLevel, onBytesProgress, onMillisecondsProgress, writer, progressTracker, }: import("./create/media-fn").MediaFnGeneratorInput) => Promise<import("./create/media-fn").MediaFn>;
|
|
@@ -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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/webcodecs",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.256",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/esm/index.mjs",
|
|
@@ -17,15 +17,15 @@
|
|
|
17
17
|
"author": "Jonny Burger <jonny@remotion.dev>",
|
|
18
18
|
"license": "Remotion License (See https://remotion.dev/docs/webcodecs#license)",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@remotion/media-parser": "4.0.
|
|
21
|
-
"@remotion/licensing": "4.0.
|
|
20
|
+
"@remotion/media-parser": "4.0.256",
|
|
21
|
+
"@remotion/licensing": "4.0.256"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/dom-webcodecs": "0.1.11",
|
|
26
26
|
"eslint": "9.14.0",
|
|
27
|
-
"@remotion/example-videos": "4.0.
|
|
28
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
27
|
+
"@remotion/example-videos": "4.0.256",
|
|
28
|
+
"@remotion/eslint-config-internal": "4.0.256"
|
|
29
29
|
},
|
|
30
30
|
"keywords": [],
|
|
31
31
|
"publishConfig": {
|
package/dist/controller.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { ParseMediaController } from '@remotion/media-parser';
|
|
2
|
-
export type WebCodecsController = {
|
|
3
|
-
abort: (reason?: any) => void;
|
|
4
|
-
pause: ParseMediaController['pause'];
|
|
5
|
-
resume: ParseMediaController['resume'];
|
|
6
|
-
addEventListener: ParseMediaController['addEventListener'];
|
|
7
|
-
removeEventListener: ParseMediaController['removeEventListener'];
|
|
8
|
-
/**
|
|
9
|
-
* @deprecated Not public API
|
|
10
|
-
*/
|
|
11
|
-
_internals: {
|
|
12
|
-
signal: AbortSignal;
|
|
13
|
-
checkForAbortAndPause: ParseMediaController['_internals']['checkForAbortAndPause'];
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
export declare const webcodecsController: () => WebCodecsController;
|
package/dist/controller.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.webcodecsController = void 0;
|
|
4
|
-
const media_parser_1 = require("@remotion/media-parser");
|
|
5
|
-
const webcodecsController = () => {
|
|
6
|
-
const controller = (0, media_parser_1.mediaParserController)();
|
|
7
|
-
return {
|
|
8
|
-
abort: controller.abort,
|
|
9
|
-
pause: controller.pause,
|
|
10
|
-
resume: controller.resume,
|
|
11
|
-
addEventListener: controller.addEventListener,
|
|
12
|
-
removeEventListener: controller.removeEventListener,
|
|
13
|
-
_internals: controller._internals,
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
exports.webcodecsController = webcodecsController;
|
package/dist/emitter.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
type MediaParserEventMap = {
|
|
2
|
-
pause: undefined;
|
|
3
|
-
resume: undefined;
|
|
4
|
-
};
|
|
5
|
-
export type MediaParserEventTypes = keyof MediaParserEventMap;
|
|
6
|
-
export type CallbackListener<T extends MediaParserEventTypes> = (data: {
|
|
7
|
-
detail: MediaParserEventMap[T];
|
|
8
|
-
}) => void;
|
|
9
|
-
type MediaParserListeners = {
|
|
10
|
-
[EventType in MediaParserEventTypes]: CallbackListener<EventType>[];
|
|
11
|
-
};
|
|
12
|
-
export declare class MediaParserEmitter {
|
|
13
|
-
listeners: MediaParserListeners;
|
|
14
|
-
addEventListener<Q extends MediaParserEventTypes>(name: Q, callback: CallbackListener<Q>): void;
|
|
15
|
-
removeEventListener<Q extends MediaParserEventTypes>(name: Q, callback: CallbackListener<Q>): void;
|
|
16
|
-
private dispatchEvent;
|
|
17
|
-
dispatchPause: () => void;
|
|
18
|
-
dispatchResume: () => void;
|
|
19
|
-
}
|
|
20
|
-
export {};
|
package/dist/emitter.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MediaParserEmitter = void 0;
|
|
4
|
-
class MediaParserEmitter {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.listeners = {
|
|
7
|
-
pause: [],
|
|
8
|
-
resume: [],
|
|
9
|
-
};
|
|
10
|
-
this.dispatchPause = () => {
|
|
11
|
-
this.dispatchEvent('pause', undefined);
|
|
12
|
-
};
|
|
13
|
-
this.dispatchResume = () => {
|
|
14
|
-
this.dispatchEvent('resume', undefined);
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
addEventListener(name, callback) {
|
|
18
|
-
this.listeners[name].push(callback);
|
|
19
|
-
}
|
|
20
|
-
removeEventListener(name, callback) {
|
|
21
|
-
this.listeners[name] = this.listeners[name].filter((l) => l !== callback);
|
|
22
|
-
}
|
|
23
|
-
dispatchEvent(dispatchName, context) {
|
|
24
|
-
this.listeners[dispatchName].forEach((callback) => {
|
|
25
|
-
callback({ detail: context });
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
exports.MediaParserEmitter = MediaParserEmitter;
|
package/dist/esm/node.mjs
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
// src/writers/node.ts
|
|
2
|
-
import fs from "node:fs";
|
|
3
|
-
var createContent = (filename) => {
|
|
4
|
-
return async () => {
|
|
5
|
-
const writPromise = Promise.resolve();
|
|
6
|
-
const remove = async () => {
|
|
7
|
-
await fs.promises.unlink(filename).catch(() => {
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
await remove();
|
|
11
|
-
if (!fs.existsSync(filename)) {
|
|
12
|
-
fs.writeFileSync(filename, "");
|
|
13
|
-
}
|
|
14
|
-
const writeStream = fs.openSync(filename, "w");
|
|
15
|
-
let written = 0;
|
|
16
|
-
const write = async (data) => {
|
|
17
|
-
await new Promise((resolve, reject) => {
|
|
18
|
-
fs.write(writeStream, data, 0, data.length, undefined, (err) => {
|
|
19
|
-
if (err) {
|
|
20
|
-
reject(err);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
resolve();
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
written += data.byteLength;
|
|
27
|
-
};
|
|
28
|
-
const updateDataAt = (position, data) => {
|
|
29
|
-
return new Promise((resolve, reject) => {
|
|
30
|
-
fs.write(writeStream, data, 0, data.length, position, (err) => {
|
|
31
|
-
if (err) {
|
|
32
|
-
reject(err);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
resolve();
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
|
-
const writer = {
|
|
40
|
-
write: (arr) => {
|
|
41
|
-
writPromise.then(() => write(arr));
|
|
42
|
-
return writPromise;
|
|
43
|
-
},
|
|
44
|
-
updateDataAt: (position, data) => {
|
|
45
|
-
writPromise.then(() => updateDataAt(position, data));
|
|
46
|
-
return writPromise;
|
|
47
|
-
},
|
|
48
|
-
waitForFinish: async () => {
|
|
49
|
-
await writPromise;
|
|
50
|
-
},
|
|
51
|
-
getWrittenByteCount: () => written,
|
|
52
|
-
remove,
|
|
53
|
-
save: async () => {
|
|
54
|
-
try {
|
|
55
|
-
fs.closeSync(writeStream);
|
|
56
|
-
const file = await fs.promises.readFile(filename);
|
|
57
|
-
return new Blob([file]);
|
|
58
|
-
} catch (e) {
|
|
59
|
-
return Promise.reject(e);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
return writer;
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
var nodeWriter = (path) => {
|
|
67
|
-
return { createContent: createContent(path) };
|
|
68
|
-
};
|
|
69
|
-
export {
|
|
70
|
-
nodeWriter
|
|
71
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const media_parser_1 = require("@remotion/media-parser");
|
|
4
|
-
const bun_test_1 = require("bun:test");
|
|
5
|
-
const matroska_utils_1 = require("../create/matroska/matroska-utils");
|
|
6
|
-
(0, bun_test_1.test)('Should make Matroska header that is same as input', async () => {
|
|
7
|
-
const headerOutput = (0, matroska_utils_1.makeMatroskaBytes)({
|
|
8
|
-
type: 'Header',
|
|
9
|
-
minVintWidth: 1,
|
|
10
|
-
value: [
|
|
11
|
-
{
|
|
12
|
-
type: 'EBMLVersion',
|
|
13
|
-
value: { value: 1, byteLength: 1 },
|
|
14
|
-
minVintWidth: 1,
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
type: 'EBMLReadVersion',
|
|
18
|
-
value: { value: 1, byteLength: 1 },
|
|
19
|
-
minVintWidth: 1,
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
type: 'EBMLMaxIDLength',
|
|
23
|
-
value: { value: 4, byteLength: 1 },
|
|
24
|
-
minVintWidth: 1,
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
type: 'EBMLMaxSizeLength',
|
|
28
|
-
value: { value: 8, byteLength: 1 },
|
|
29
|
-
minVintWidth: 1,
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
type: 'DocType',
|
|
33
|
-
value: 'webm',
|
|
34
|
-
minVintWidth: 1,
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
type: 'DocTypeVersion',
|
|
38
|
-
value: { value: 4, byteLength: 1 },
|
|
39
|
-
minVintWidth: 1,
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
type: 'DocTypeReadVersion',
|
|
43
|
-
value: { value: 2, byteLength: 1 },
|
|
44
|
-
minVintWidth: 1,
|
|
45
|
-
},
|
|
46
|
-
],
|
|
47
|
-
});
|
|
48
|
-
const iterator = media_parser_1.MediaParserInternals.getArrayBufferIterator(headerOutput.bytes, headerOutput.bytes.length);
|
|
49
|
-
const state = media_parser_1.MediaParserInternals.makeParserState({
|
|
50
|
-
hasAudioTrackHandlers: false,
|
|
51
|
-
hasVideoTrackHandlers: false,
|
|
52
|
-
signal: undefined,
|
|
53
|
-
iterator,
|
|
54
|
-
fields: {},
|
|
55
|
-
onAudioTrack: null,
|
|
56
|
-
onVideoTrack: null,
|
|
57
|
-
supportsContentRange: true,
|
|
58
|
-
contentLength: null,
|
|
59
|
-
logLevel: 'info',
|
|
60
|
-
});
|
|
61
|
-
const parsed = await media_parser_1.MediaParserInternals.parseEbml(state);
|
|
62
|
-
(0, bun_test_1.expect)(parsed).toEqual({
|
|
63
|
-
type: 'Header',
|
|
64
|
-
minVintWidth: 1,
|
|
65
|
-
value: [
|
|
66
|
-
{
|
|
67
|
-
type: 'EBMLVersion',
|
|
68
|
-
value: { value: 1, byteLength: 1 },
|
|
69
|
-
minVintWidth: 1,
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
type: 'EBMLReadVersion',
|
|
73
|
-
value: { value: 1, byteLength: 1 },
|
|
74
|
-
minVintWidth: 1,
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
type: 'EBMLMaxIDLength',
|
|
78
|
-
value: { value: 4, byteLength: 1 },
|
|
79
|
-
minVintWidth: 1,
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
type: 'EBMLMaxSizeLength',
|
|
83
|
-
value: { value: 8, byteLength: 1 },
|
|
84
|
-
minVintWidth: 1,
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
type: 'DocType',
|
|
88
|
-
value: 'webm',
|
|
89
|
-
minVintWidth: 1,
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
type: 'DocTypeVersion',
|
|
93
|
-
value: { value: 4, byteLength: 1 },
|
|
94
|
-
minVintWidth: 1,
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
type: 'DocTypeReadVersion',
|
|
98
|
-
value: { value: 2, byteLength: 1 },
|
|
99
|
-
minVintWidth: 1,
|
|
100
|
-
},
|
|
101
|
-
],
|
|
102
|
-
});
|
|
103
|
-
});
|
package/dist/test/stsd.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/test/stsd.test.js
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const media_parser_1 = require("@remotion/media-parser");
|
|
4
|
-
const bun_test_1 = require("bun:test");
|
|
5
|
-
(0, bun_test_1.test)('Should be able to parse a STSD audio box correctly', async () => {
|
|
6
|
-
const buffer = Uint8Array.from([
|
|
7
|
-
// box size
|
|
8
|
-
0, 0, 0, 159,
|
|
9
|
-
// data format "stsd"
|
|
10
|
-
115, 116, 115, 100,
|
|
11
|
-
// reserved
|
|
12
|
-
0, 0, 0, 0, 0, 0,
|
|
13
|
-
// number of entries
|
|
14
|
-
0, 1,
|
|
15
|
-
// size
|
|
16
|
-
0, 0, 0, 143,
|
|
17
|
-
// "mp4a"
|
|
18
|
-
109, 112, 52, 97,
|
|
19
|
-
// reserved
|
|
20
|
-
0, 0, 0, 0, 0, 0,
|
|
21
|
-
// data reference index
|
|
22
|
-
0, 1,
|
|
23
|
-
// version
|
|
24
|
-
0, 1,
|
|
25
|
-
// revision level
|
|
26
|
-
0, 0, 0, 0, 0, 0,
|
|
27
|
-
// revision level
|
|
28
|
-
0, 2, 0, 16, 255, 254, 0, 0, 172, 68, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1, 0, 0, 0,
|
|
29
|
-
2, 0, 0, 0, 2, 0, 0, 0, 91, 119, 97, 118, 101, 0, 0, 0, 12, 102, 114, 109,
|
|
30
|
-
97, 109, 112, 52, 97, 0, 0, 0, 12, 109, 112, 52, 97, 0, 0, 0, 0, 0, 0, 0,
|
|
31
|
-
51, 101, 115, 100, 115, 0, 0, 0, 0, 3, 128, 128, 128, 34, 0, 0, 0, 4, 128,
|
|
32
|
-
128, 128, 20, 64, 20, 0, 24, 0, 0, 2, 238, 0, 0, 0, 0, 0, 5, 128, 128, 128,
|
|
33
|
-
2, 18, 16, 6, 128, 128, 128, 1, 2, 0, 0, 0, 8, 0, 0, 0, 0,
|
|
34
|
-
]);
|
|
35
|
-
const iterator = media_parser_1.MediaParserInternals.getArrayBufferIterator(buffer, null);
|
|
36
|
-
iterator.discard(8);
|
|
37
|
-
const parsed = await media_parser_1.MediaParserInternals.parseStsd({
|
|
38
|
-
offset: 0,
|
|
39
|
-
size: 159,
|
|
40
|
-
state: media_parser_1.MediaParserInternals.makeParserState({
|
|
41
|
-
onAudioTrack: null,
|
|
42
|
-
onVideoTrack: () => () => undefined,
|
|
43
|
-
hasAudioTrackHandlers: true,
|
|
44
|
-
hasVideoTrackHandlers: true,
|
|
45
|
-
signal: undefined,
|
|
46
|
-
iterator,
|
|
47
|
-
fields: {},
|
|
48
|
-
supportsContentRange: true,
|
|
49
|
-
contentLength: null,
|
|
50
|
-
logLevel: 'info',
|
|
51
|
-
}),
|
|
52
|
-
});
|
|
53
|
-
(0, bun_test_1.expect)(parsed).toEqual({
|
|
54
|
-
offset: 0,
|
|
55
|
-
boxSize: 159,
|
|
56
|
-
type: 'stsd-box',
|
|
57
|
-
numberOfEntries: 1,
|
|
58
|
-
samples: [
|
|
59
|
-
{
|
|
60
|
-
size: 143,
|
|
61
|
-
offset: 16,
|
|
62
|
-
format: 'mp4a',
|
|
63
|
-
dataReferenceIndex: 1,
|
|
64
|
-
version: 1,
|
|
65
|
-
revisionLevel: 0,
|
|
66
|
-
vendor: [0, 0, 0, 0],
|
|
67
|
-
numberOfChannels: 2,
|
|
68
|
-
type: 'audio',
|
|
69
|
-
sampleSize: 16,
|
|
70
|
-
compressionId: -2,
|
|
71
|
-
packetSize: 0,
|
|
72
|
-
samplesPerPacket: 1024,
|
|
73
|
-
bitsPerSample: 2,
|
|
74
|
-
bytesPerFrame: 2,
|
|
75
|
-
bytesPerPacket: 1,
|
|
76
|
-
sampleRate: 44100,
|
|
77
|
-
children: [
|
|
78
|
-
{
|
|
79
|
-
boxSize: 91,
|
|
80
|
-
boxType: 'wave',
|
|
81
|
-
children: [
|
|
82
|
-
{
|
|
83
|
-
boxSize: 12,
|
|
84
|
-
boxType: 'frma',
|
|
85
|
-
children: [],
|
|
86
|
-
offset: 76,
|
|
87
|
-
type: 'regular-box',
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
boxSize: 12,
|
|
91
|
-
boxType: 'mp4a',
|
|
92
|
-
children: [],
|
|
93
|
-
offset: 88,
|
|
94
|
-
type: 'regular-box',
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
descriptors: [
|
|
98
|
-
{
|
|
99
|
-
objectTypeIndication: 'aac',
|
|
100
|
-
type: 'decoder-config-descriptor',
|
|
101
|
-
asNumber: 64,
|
|
102
|
-
avgBitrate: 0,
|
|
103
|
-
bufferSizeDB: 6144,
|
|
104
|
-
maxBitrate: 192000,
|
|
105
|
-
streamType: 5,
|
|
106
|
-
decoderSpecificConfigs: [
|
|
107
|
-
{
|
|
108
|
-
audioObjectType: 2,
|
|
109
|
-
channelConfiguration: 2,
|
|
110
|
-
samplingFrequencyIndex: 4,
|
|
111
|
-
type: 'mp4a-specific-config',
|
|
112
|
-
asBytes: new Uint8Array([18, 16]),
|
|
113
|
-
},
|
|
114
|
-
],
|
|
115
|
-
upStream: 0,
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
type: 'sl-config-descriptor',
|
|
119
|
-
},
|
|
120
|
-
],
|
|
121
|
-
esId: 0,
|
|
122
|
-
sizeOfInstance: 34,
|
|
123
|
-
tag: 3,
|
|
124
|
-
type: 'esds-box',
|
|
125
|
-
version: 0,
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
boxSize: 8,
|
|
129
|
-
boxType: '\u0000\u0000\u0000\u0000',
|
|
130
|
-
children: [],
|
|
131
|
-
offset: 151,
|
|
132
|
-
type: 'regular-box',
|
|
133
|
-
},
|
|
134
|
-
],
|
|
135
|
-
offset: 68,
|
|
136
|
-
type: 'regular-box',
|
|
137
|
-
},
|
|
138
|
-
],
|
|
139
|
-
},
|
|
140
|
-
],
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
(0, bun_test_1.test)('Should be able to parse a STSD video box correctly', async () => {
|
|
144
|
-
const buffer = Uint8Array.from([
|
|
145
|
-
// box size
|
|
146
|
-
0, 0, 0, 158,
|
|
147
|
-
// data format "avc1"
|
|
148
|
-
97, 118, 99, 49,
|
|
149
|
-
// padding
|
|
150
|
-
0, 0, 0, 0, 0, 0,
|
|
151
|
-
// data reference index
|
|
152
|
-
0, 1,
|
|
153
|
-
// version
|
|
154
|
-
0, 0,
|
|
155
|
-
// revision level
|
|
156
|
-
0, 0,
|
|
157
|
-
// vendor
|
|
158
|
-
0, 0, 0, 0,
|
|
159
|
-
// temporal quality
|
|
160
|
-
0, 0, 0, 0,
|
|
161
|
-
// spatial quality
|
|
162
|
-
0, 0, 0, 0,
|
|
163
|
-
// width
|
|
164
|
-
4, 56,
|
|
165
|
-
// height
|
|
166
|
-
4, 56,
|
|
167
|
-
// horiz resolution
|
|
168
|
-
0, 72, 0, 0,
|
|
169
|
-
// vert resolution
|
|
170
|
-
0, 72, 0, 0,
|
|
171
|
-
// frame count
|
|
172
|
-
0, 0,
|
|
173
|
-
// compressor name
|
|
174
|
-
// 0
|
|
175
|
-
0, 0, 0, 1,
|
|
176
|
-
// 1
|
|
177
|
-
0, 0, 0, 0,
|
|
178
|
-
// 2
|
|
179
|
-
0, 0, 0, 0,
|
|
180
|
-
// 3
|
|
181
|
-
0, 0, 0, 0,
|
|
182
|
-
// 4
|
|
183
|
-
0, 0, 0, 0,
|
|
184
|
-
// 5
|
|
185
|
-
0, 0, 0, 0,
|
|
186
|
-
// 6
|
|
187
|
-
0, 0, 0, 0,
|
|
188
|
-
// 7
|
|
189
|
-
0, 0, 0, 0,
|
|
190
|
-
// 8
|
|
191
|
-
0, 0, 0, 0,
|
|
192
|
-
// depth
|
|
193
|
-
0, 24,
|
|
194
|
-
// color space
|
|
195
|
-
255, 255,
|
|
196
|
-
// avcC info (not parsed)
|
|
197
|
-
0, 0, 0, 56, 97, 118, 99, 67, 1, 100, 0, 32, 255, 225, 0, 27, 103, 100, 0,
|
|
198
|
-
32, 172, 217, 64, 68, 2, 39, 150, 92, 4, 64, 0, 0, 3, 0, 64, 0, 0, 12, 3,
|
|
199
|
-
198, 12, 101, 128, 1, 0, 6, 104, 235, 224, 140, 178, 44, 253, 248, 248, 0,
|
|
200
|
-
// pasp
|
|
201
|
-
0, 0, 0, 16, 112, 97, 115, 112, 0, 0, 0, 1, 0, 0, 0, 1,
|
|
202
|
-
]);
|
|
203
|
-
const parsed = await media_parser_1.MediaParserInternals.processSample({
|
|
204
|
-
state: media_parser_1.MediaParserInternals.makeParserState({
|
|
205
|
-
onAudioTrack: null,
|
|
206
|
-
onVideoTrack: () => () => undefined,
|
|
207
|
-
hasAudioTrackHandlers: true,
|
|
208
|
-
hasVideoTrackHandlers: true,
|
|
209
|
-
signal: undefined,
|
|
210
|
-
iterator: media_parser_1.MediaParserInternals.getArrayBufferIterator(buffer, null),
|
|
211
|
-
fields: {
|
|
212
|
-
structure: true,
|
|
213
|
-
},
|
|
214
|
-
supportsContentRange: true,
|
|
215
|
-
contentLength: null,
|
|
216
|
-
logLevel: 'info',
|
|
217
|
-
}),
|
|
218
|
-
});
|
|
219
|
-
(0, bun_test_1.expect)(parsed.sample).toEqual({
|
|
220
|
-
size: 158,
|
|
221
|
-
format: 'avc1',
|
|
222
|
-
dataReferenceIndex: 1,
|
|
223
|
-
version: 0,
|
|
224
|
-
revisionLevel: 0,
|
|
225
|
-
vendor: [0, 0, 0, 0],
|
|
226
|
-
type: 'video',
|
|
227
|
-
temporalQuality: 0,
|
|
228
|
-
spacialQuality: 0,
|
|
229
|
-
width: 1080,
|
|
230
|
-
height: 1080,
|
|
231
|
-
horizontalResolutionPpi: 72,
|
|
232
|
-
verticalResolutionPpi: 72,
|
|
233
|
-
dataSize: 0,
|
|
234
|
-
frameCountPerSample: 1,
|
|
235
|
-
compressorName: [
|
|
236
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
237
|
-
0, 0, 0, 0, 0, 0, 0,
|
|
238
|
-
],
|
|
239
|
-
offset: 0,
|
|
240
|
-
depth: 24,
|
|
241
|
-
colorTableId: -1,
|
|
242
|
-
descriptors: [
|
|
243
|
-
{
|
|
244
|
-
privateData: new Uint8Array([
|
|
245
|
-
1, 100, 0, 32, 255, 225, 0, 27, 103, 100, 0, 32, 172, 217, 64, 68, 2,
|
|
246
|
-
39, 150, 92, 4, 64, 0, 0, 3, 0, 64, 0, 0, 12, 3, 198, 12, 101, 128, 1,
|
|
247
|
-
0, 6, 104, 235, 224, 140, 178, 44, 253, 248, 248, 0,
|
|
248
|
-
]),
|
|
249
|
-
type: 'avcc-box',
|
|
250
|
-
configurationString: '640020',
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
boxSize: 16,
|
|
254
|
-
offset: 142,
|
|
255
|
-
type: 'pasp-box',
|
|
256
|
-
hSpacing: 1,
|
|
257
|
-
vSpacing: 1,
|
|
258
|
-
},
|
|
259
|
-
],
|
|
260
|
-
});
|
|
261
|
-
});
|
package/dist/writers/node.d.ts
DELETED
package/dist/writers/node.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.nodeWriter = void 0;
|
|
7
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
-
const createContent = (filename) => {
|
|
9
|
-
return async () => {
|
|
10
|
-
const writPromise = Promise.resolve();
|
|
11
|
-
const remove = async () => {
|
|
12
|
-
await node_fs_1.default.promises.unlink(filename).catch(() => { });
|
|
13
|
-
};
|
|
14
|
-
await remove();
|
|
15
|
-
if (!node_fs_1.default.existsSync(filename)) {
|
|
16
|
-
node_fs_1.default.writeFileSync(filename, '');
|
|
17
|
-
}
|
|
18
|
-
const writeStream = node_fs_1.default.openSync(filename, 'w');
|
|
19
|
-
let written = 0;
|
|
20
|
-
const write = async (data) => {
|
|
21
|
-
await new Promise((resolve, reject) => {
|
|
22
|
-
node_fs_1.default.write(writeStream, data, 0, data.length, undefined, (err) => {
|
|
23
|
-
if (err) {
|
|
24
|
-
reject(err);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
resolve();
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
written += data.byteLength;
|
|
31
|
-
};
|
|
32
|
-
const updateDataAt = (position, data) => {
|
|
33
|
-
return new Promise((resolve, reject) => {
|
|
34
|
-
node_fs_1.default.write(writeStream, data, 0, data.length, position, (err) => {
|
|
35
|
-
if (err) {
|
|
36
|
-
reject(err);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
resolve();
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
};
|
|
43
|
-
const writer = {
|
|
44
|
-
write: (arr) => {
|
|
45
|
-
writPromise.then(() => write(arr));
|
|
46
|
-
return writPromise;
|
|
47
|
-
},
|
|
48
|
-
updateDataAt: (position, data) => {
|
|
49
|
-
writPromise.then(() => updateDataAt(position, data));
|
|
50
|
-
return writPromise;
|
|
51
|
-
},
|
|
52
|
-
waitForFinish: async () => {
|
|
53
|
-
await writPromise;
|
|
54
|
-
},
|
|
55
|
-
getWrittenByteCount: () => written,
|
|
56
|
-
remove,
|
|
57
|
-
save: async () => {
|
|
58
|
-
try {
|
|
59
|
-
node_fs_1.default.closeSync(writeStream);
|
|
60
|
-
const file = await node_fs_1.default.promises.readFile(filename);
|
|
61
|
-
return new Blob([file]);
|
|
62
|
-
}
|
|
63
|
-
catch (e) {
|
|
64
|
-
return Promise.reject(e);
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
return writer;
|
|
69
|
-
};
|
|
70
|
-
};
|
|
71
|
-
const nodeWriter = (path) => {
|
|
72
|
-
return { createContent: createContent(path) };
|
|
73
|
-
};
|
|
74
|
-
exports.nodeWriter = nodeWriter;
|
package/dist/writers/writer.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type Writer = {
|
|
2
|
-
write: (arr: Uint8Array) => Promise<void>;
|
|
3
|
-
save: () => Promise<Blob>;
|
|
4
|
-
getWrittenByteCount: () => number;
|
|
5
|
-
updateDataAt: (position: number, data: Uint8Array) => Promise<void>;
|
|
6
|
-
waitForFinish: () => Promise<void>;
|
|
7
|
-
remove: () => Promise<void>;
|
|
8
|
-
};
|
|
9
|
-
export type CreateContent = (options: {
|
|
10
|
-
filename: string;
|
|
11
|
-
mimeType: string;
|
|
12
|
-
}) => Promise<Writer>;
|
|
13
|
-
export type WriterInterface = {
|
|
14
|
-
createContent: CreateContent;
|
|
15
|
-
};
|
|
File without changes
|