@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.
@@ -0,0 +1,2 @@
1
+ export type ConvertMediaVideoCodec = 'vp8' | 'vp9';
2
+ export type ConvertMediaAudioCodec = 'opus';
@@ -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 | 4 | 3 | 5 | 6;
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,5 @@
1
+ export declare const normalizeVideoRotation: (rotation: number) => number;
2
+ export declare const rotateVideoFrame: ({ frame, rotation, }: {
3
+ frame: VideoFrame;
4
+ rotation: number;
5
+ }) => VideoFrame;
@@ -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) => ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, }: import("./create/media-fn").MediaFnGeneratorInput) => Promise<import("./create/media-fn").MediaFn>;
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,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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/webcodecs",
3
- "version": "4.0.254",
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.254",
21
- "@remotion/licensing": "4.0.254"
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.254",
28
- "@remotion/eslint-config-internal": "4.0.254"
27
+ "@remotion/example-videos": "4.0.256",
28
+ "@remotion/eslint-config-internal": "4.0.256"
29
29
  },
30
30
  "keywords": [],
31
31
  "publishConfig": {
@@ -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;
@@ -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
- });
@@ -1 +0,0 @@
1
- export {};
@@ -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
- });
@@ -1,4 +0,0 @@
1
- import type { CreateContent } from './writer';
2
- export declare const nodeWriter: (path: string) => {
3
- createContent: CreateContent;
4
- };
@@ -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;
@@ -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