Add .gitignore to exclude all node packages and lock files
This commit is contained in:
Generated
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
type Input = {
|
||||
timestamp: number;
|
||||
};
|
||||
type Output = {
|
||||
timestamp: number;
|
||||
};
|
||||
type Processed = {};
|
||||
type Progress = {
|
||||
smallestProgress: number;
|
||||
};
|
||||
type IoEventMap = {
|
||||
input: Input;
|
||||
output: Output;
|
||||
processed: Processed;
|
||||
progress: Progress;
|
||||
};
|
||||
export type IoEventTypes = keyof IoEventMap;
|
||||
export type CallbackListener<T extends IoEventTypes> = (data: {
|
||||
detail: IoEventMap[T];
|
||||
}) => void;
|
||||
type IoListeners = {
|
||||
[EventType in IoEventTypes]: CallbackListener<EventType>[];
|
||||
};
|
||||
export declare class IoEventEmitter {
|
||||
listeners: IoListeners;
|
||||
addEventListener<Q extends IoEventTypes>(name: Q, callback: CallbackListener<Q>): void;
|
||||
removeEventListener<Q extends IoEventTypes>(name: Q, callback: CallbackListener<Q>): void;
|
||||
dispatchEvent<T extends IoEventTypes>(dispatchName: T, context: IoEventMap[T]): void;
|
||||
}
|
||||
export {};
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.IoEventEmitter = void 0;
|
||||
class IoEventEmitter {
|
||||
constructor() {
|
||||
this.listeners = {
|
||||
input: [],
|
||||
output: [],
|
||||
processed: [],
|
||||
progress: [],
|
||||
};
|
||||
}
|
||||
addEventListener(name, callback) {
|
||||
this.listeners[name].push(callback);
|
||||
}
|
||||
removeEventListener(name, callback) {
|
||||
this.listeners[name] = this.listeners[name].filter((l) => l !== callback);
|
||||
}
|
||||
dispatchEvent(dispatchName, context) {
|
||||
this.listeners[dispatchName].forEach((callback) => {
|
||||
callback({ detail: context });
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.IoEventEmitter = IoEventEmitter;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { Avc1Data } from './create-codec-specific-data';
|
||||
export declare const createAvc1Data: ({ avccBox, pasp, width, height, horizontalResolution, verticalResolution, compressorName, depth, }: Avc1Data) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createAvc1Data = void 0;
|
||||
const matroska_utils_1 = require("../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../primitives");
|
||||
const createAvc1Data = ({ avccBox, pasp, width, height, horizontalResolution, verticalResolution, compressorName, depth, }) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('avc1'),
|
||||
// reserved
|
||||
new Uint8Array([0, 0, 0, 0, 0, 0]),
|
||||
// data_reference_index
|
||||
new Uint8Array([0, 1]),
|
||||
// version
|
||||
new Uint8Array([0, 0]),
|
||||
// revisionLevel
|
||||
new Uint8Array([0, 0]),
|
||||
// vendor
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// temporalQuality
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// spatialQuality
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// width
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(width),
|
||||
// height
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(height),
|
||||
// horizontalResolution
|
||||
(0, primitives_1.setFixedPointSignedOrUnsigned1616Number)(horizontalResolution),
|
||||
// verticalResolution
|
||||
(0, primitives_1.setFixedPointSignedOrUnsigned1616Number)(verticalResolution),
|
||||
// dataSize
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// frame count per sample
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(1),
|
||||
// compressor name
|
||||
(0, primitives_1.stringToPascalString)(compressorName),
|
||||
// depth
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(depth),
|
||||
// colorTableId
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(-1),
|
||||
// avcc box
|
||||
avccBox,
|
||||
// pasp
|
||||
pasp,
|
||||
]));
|
||||
};
|
||||
exports.createAvc1Data = createAvc1Data;
|
||||
Generated
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
import type { MakeTrackAudio, MakeTrackVideo } from '../../make-track-info';
|
||||
export type Avc1Data = {
|
||||
pasp: Uint8Array;
|
||||
avccBox: Uint8Array;
|
||||
width: number;
|
||||
height: number;
|
||||
horizontalResolution: number;
|
||||
verticalResolution: number;
|
||||
compressorName: string;
|
||||
depth: number;
|
||||
type: 'avc1-data';
|
||||
};
|
||||
export type Hvc1Data = {
|
||||
pasp: Uint8Array;
|
||||
hvccBox: Uint8Array;
|
||||
width: number;
|
||||
height: number;
|
||||
horizontalResolution: number;
|
||||
verticalResolution: number;
|
||||
compressorName: string;
|
||||
depth: number;
|
||||
type: 'hvc1-data';
|
||||
};
|
||||
export type Mp4aData = {
|
||||
type: 'mp4a-data';
|
||||
sampleRate: number;
|
||||
channelCount: number;
|
||||
maxBitrate: number;
|
||||
avgBitrate: number;
|
||||
codecPrivate: Uint8Array | null;
|
||||
};
|
||||
export type CodecSpecificData = Avc1Data | Mp4aData;
|
||||
export declare const createCodecSpecificData: (track: MakeTrackAudio | MakeTrackVideo) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+62
@@ -0,0 +1,62 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createCodecSpecificData = void 0;
|
||||
const create_avcc_1 = require("../trak/mdia/minf/stbl/stsd/create-avcc");
|
||||
const create_hvcc_1 = require("../trak/mdia/minf/stbl/stsd/create-hvcc");
|
||||
const create_pasp_1 = require("../trak/mdia/minf/stbl/stsd/create-pasp");
|
||||
const avc1_1 = require("./avc1");
|
||||
const hvc1_1 = require("./hvc1");
|
||||
const mp4a_1 = require("./mp4a");
|
||||
const createCodecSpecificData = (track) => {
|
||||
if (track.type === 'video') {
|
||||
if (track.codec === 'h264') {
|
||||
// May not have it initially
|
||||
if (!track.codecPrivate) {
|
||||
return new Uint8Array([]);
|
||||
}
|
||||
return (0, avc1_1.createAvc1Data)({
|
||||
avccBox: (0, create_avcc_1.createAvccBox)(track.codecPrivate),
|
||||
compressorName: 'WebCodecs',
|
||||
depth: 24,
|
||||
horizontalResolution: 72,
|
||||
verticalResolution: 72,
|
||||
height: track.height,
|
||||
width: track.width,
|
||||
pasp: (0, create_pasp_1.createPasp)(1, 1),
|
||||
type: 'avc1-data',
|
||||
});
|
||||
}
|
||||
if (track.codec === 'h265') {
|
||||
// May not have it initially
|
||||
if (!track.codecPrivate) {
|
||||
return new Uint8Array([]);
|
||||
}
|
||||
return (0, hvc1_1.createHvc1Data)({
|
||||
hvccBox: (0, create_hvcc_1.createHvccBox)(track.codecPrivate),
|
||||
compressorName: 'WebCodecs',
|
||||
depth: 24,
|
||||
horizontalResolution: 72,
|
||||
verticalResolution: 72,
|
||||
height: track.height,
|
||||
width: track.width,
|
||||
pasp: (0, create_pasp_1.createPasp)(1, 1),
|
||||
type: 'hvc1-data',
|
||||
});
|
||||
}
|
||||
throw new Error('Unsupported codec specific data ' + track.codec);
|
||||
}
|
||||
if (track.type === 'audio') {
|
||||
return (0, mp4a_1.createMp4a)({
|
||||
type: 'mp4a-data',
|
||||
// TODO: Put in values based on real data,
|
||||
// this seems to work though
|
||||
avgBitrate: 128 * 1024,
|
||||
maxBitrate: 128 * 1024,
|
||||
channelCount: track.numberOfChannels,
|
||||
sampleRate: track.sampleRate,
|
||||
codecPrivate: track.codecPrivate,
|
||||
});
|
||||
}
|
||||
throw new Error('Unsupported codec specific data ' + track);
|
||||
};
|
||||
exports.createCodecSpecificData = createCodecSpecificData;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { Hvc1Data } from './create-codec-specific-data';
|
||||
export declare const createHvc1Data: ({ compressorName, depth, height, horizontalResolution, hvccBox, pasp, verticalResolution, width, }: Hvc1Data) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createHvc1Data = void 0;
|
||||
const matroska_utils_1 = require("../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../primitives");
|
||||
const createHvc1Data = ({ compressorName, depth, height, horizontalResolution, hvccBox, pasp, verticalResolution, width, }) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('hvc1'),
|
||||
// reserved
|
||||
new Uint8Array([0, 0, 0, 0, 0, 0]),
|
||||
// data_reference_index
|
||||
new Uint8Array([0, 1]),
|
||||
// version
|
||||
new Uint8Array([0, 0]),
|
||||
// revisionLevel
|
||||
new Uint8Array([0, 0]),
|
||||
// vendor
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// temporalQuality
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// spatialQuality
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// width
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(width),
|
||||
// height
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(height),
|
||||
// horizontalResolution
|
||||
(0, primitives_1.setFixedPointSignedOrUnsigned1616Number)(horizontalResolution),
|
||||
// verticalResolution
|
||||
(0, primitives_1.setFixedPointSignedOrUnsigned1616Number)(verticalResolution),
|
||||
// dataSize
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// frame count per sample
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(1),
|
||||
// compressor name
|
||||
(0, primitives_1.stringToPascalString)(compressorName),
|
||||
// depth
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(depth),
|
||||
// colorTableId
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(-1),
|
||||
// hvcc box
|
||||
hvccBox,
|
||||
// pasp
|
||||
pasp,
|
||||
]));
|
||||
};
|
||||
exports.createHvc1Data = createHvc1Data;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { Mp4aData } from './create-codec-specific-data';
|
||||
export declare const createMp4a: ({ sampleRate, channelCount, avgBitrate, maxBitrate, codecPrivate, }: Mp4aData) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+74
@@ -0,0 +1,74 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMp4a = void 0;
|
||||
const matroska_utils_1 = require("../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../primitives");
|
||||
const createMp4a = ({ sampleRate, channelCount, avgBitrate, maxBitrate, codecPrivate, }) => {
|
||||
if (!codecPrivate) {
|
||||
throw new Error('Need codecPrivate for mp4a');
|
||||
}
|
||||
const esdsAtom = (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('esds'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// tag = 'ES_DescrTag'
|
||||
new Uint8Array([3]),
|
||||
(0, primitives_1.addLeading128Size)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// ES_ID
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(2),
|
||||
// streamDependenceFlag, URL_Flag, OCRstreamFlag
|
||||
new Uint8Array([0]),
|
||||
// DecoderConfigDescrTag
|
||||
new Uint8Array([4]),
|
||||
(0, primitives_1.addLeading128Size)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// objectTypeIndication
|
||||
new Uint8Array([0x40]),
|
||||
// streamType, upStream
|
||||
new Uint8Array([21]),
|
||||
// reserved
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// maxBitrate
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(maxBitrate),
|
||||
// avgBitrate
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(avgBitrate),
|
||||
// DecoderSpecificInfoTag
|
||||
new Uint8Array([5]),
|
||||
// see create-aac-codecprivate.ts
|
||||
(0, primitives_1.addLeading128Size)(codecPrivate),
|
||||
])),
|
||||
// SLConfigDescrTag
|
||||
new Uint8Array([6]),
|
||||
(0, primitives_1.addLeading128Size)(new Uint8Array([2])),
|
||||
])),
|
||||
]));
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('mp4a'),
|
||||
// reserved
|
||||
new Uint8Array([0, 0, 0, 0, 0, 0]),
|
||||
// data_reference_index
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(1),
|
||||
// version
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(0),
|
||||
// revision level
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(0),
|
||||
// vendor
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// channelCount
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(channelCount),
|
||||
// sampleSize
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(16),
|
||||
// compressionId
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(0),
|
||||
// packet size
|
||||
(0, primitives_1.numberTo16BitUIntOrInt)(0),
|
||||
// sample rate
|
||||
(0, primitives_1.setFixedPointSignedOrUnsigned1616Number)(sampleRate),
|
||||
// esds atom
|
||||
esdsAtom,
|
||||
]));
|
||||
};
|
||||
exports.createMp4a = createMp4a;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
export declare const createColr: ({ fullRange, matrixIndex, primaries, transferFunction, }: {
|
||||
fullRange: boolean;
|
||||
matrixIndex: number;
|
||||
primaries: number;
|
||||
transferFunction: number;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createColr = void 0;
|
||||
const matroska_utils_1 = require("../matroska/matroska-utils");
|
||||
const primitives_1 = require("./primitives");
|
||||
// TODO: Not used in creation of MP4 yet
|
||||
const createColr = ({ fullRange, matrixIndex, primaries, transferFunction, }) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('colr'),
|
||||
// colour_type
|
||||
(0, primitives_1.stringsToUint8Array)('nclx'),
|
||||
// primaries
|
||||
// 1 = 'ITU-R BT.7090
|
||||
new Uint8Array([0, primaries]),
|
||||
// transfer_function
|
||||
// 1 = 'ITU-R BT.7090
|
||||
new Uint8Array([0, transferFunction]),
|
||||
// matrix_index
|
||||
// 1 = 'ITU-R BT.7090
|
||||
new Uint8Array([0, matrixIndex]),
|
||||
// full_range_flag
|
||||
new Uint8Array([fullRange ? 1 : 0]),
|
||||
]));
|
||||
};
|
||||
exports.createColr = createColr;
|
||||
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
export declare const createFtyp: ({ majorBrand, minorBrand, compatibleBrands, }: {
|
||||
majorBrand: string;
|
||||
minorBrand: number;
|
||||
compatibleBrands: string[];
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
export declare const createIsoBaseMediaFtyp: ({ majorBrand, minorBrand, compatibleBrands, }: {
|
||||
majorBrand: string;
|
||||
minorBrand: number;
|
||||
compatibleBrands: string[];
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createIsoBaseMediaFtyp = exports.createFtyp = void 0;
|
||||
const matroska_utils_1 = require("../matroska/matroska-utils");
|
||||
const primitives_1 = require("./primitives");
|
||||
const createFtyp = ({ majorBrand, minorBrand, compatibleBrands, }) => {
|
||||
const type = (0, primitives_1.stringsToUint8Array)('ftyp');
|
||||
const majorBrandArr = (0, primitives_1.stringsToUint8Array)(majorBrand);
|
||||
const minorBrandArr = (0, primitives_1.numberTo32BitUIntOrInt)(minorBrand);
|
||||
const compatibleBrandsArr = (0, matroska_utils_1.combineUint8Arrays)(compatibleBrands.map((b) => (0, primitives_1.stringsToUint8Array)(b)));
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
type,
|
||||
majorBrandArr,
|
||||
minorBrandArr,
|
||||
compatibleBrandsArr,
|
||||
]));
|
||||
};
|
||||
exports.createFtyp = createFtyp;
|
||||
const createIsoBaseMediaFtyp = ({ majorBrand, minorBrand, compatibleBrands, }) => {
|
||||
return (0, exports.createFtyp)({ compatibleBrands, majorBrand, minorBrand });
|
||||
};
|
||||
exports.createIsoBaseMediaFtyp = createIsoBaseMediaFtyp;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createIlst: (items: Uint8Array[]) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createIlst = void 0;
|
||||
const matroska_utils_1 = require("../matroska/matroska-utils");
|
||||
const primitives_1 = require("./primitives");
|
||||
const createIlst = (items) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// name
|
||||
(0, primitives_1.stringsToUint8Array)('ilst'),
|
||||
// items
|
||||
...items,
|
||||
]));
|
||||
};
|
||||
exports.createIlst = createIlst;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { MediaFn, MediaFnGeneratorInput } from '../media-fn';
|
||||
export declare const createIsoBaseMedia: ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, expectedDurationInSeconds, expectedFrameRate, }: MediaFnGeneratorInput) => Promise<MediaFn>;
|
||||
Generated
Vendored
+191
@@ -0,0 +1,191 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createIsoBaseMedia = void 0;
|
||||
const media_parser_1 = require("@remotion/media-parser");
|
||||
const matroska_utils_1 = require("../matroska/matroska-utils");
|
||||
const create_ftyp_1 = require("./create-ftyp");
|
||||
const mp4_header_1 = require("./mp4-header");
|
||||
const primitives_1 = require("./primitives");
|
||||
const CONTAINER_TIMESCALE = 1000;
|
||||
const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, expectedDurationInSeconds, expectedFrameRate, }) => {
|
||||
const header = (0, create_ftyp_1.createIsoBaseMediaFtyp)({
|
||||
compatibleBrands: ['isom', 'iso2', 'avc1', 'mp42'],
|
||||
majorBrand: 'isom',
|
||||
minorBrand: 512,
|
||||
});
|
||||
const w = await writer.createContent({
|
||||
filename,
|
||||
mimeType: 'video/mp4',
|
||||
logLevel,
|
||||
});
|
||||
await w.write(header);
|
||||
let globalDurationInUnits = 0;
|
||||
const lowestTrackTimestamps = {};
|
||||
const trackDurations = {};
|
||||
const currentTracks = [];
|
||||
const samplePositions = [];
|
||||
const sampleChunkIndices = [];
|
||||
const moovOffset = w.getWrittenByteCount();
|
||||
const getPaddedMoovAtom = () => {
|
||||
return (0, mp4_header_1.createPaddedMoovAtom)({
|
||||
durationInUnits: globalDurationInUnits,
|
||||
trackInfo: currentTracks.map((track) => {
|
||||
return {
|
||||
track,
|
||||
durationInUnits: trackDurations[track.trackNumber] ?? 0,
|
||||
samplePositions: samplePositions[track.trackNumber] ?? [],
|
||||
timescale: track.timescale,
|
||||
};
|
||||
}),
|
||||
timescale: CONTAINER_TIMESCALE,
|
||||
expectedDurationInSeconds,
|
||||
logLevel,
|
||||
expectedFrameRate,
|
||||
});
|
||||
};
|
||||
await w.write(getPaddedMoovAtom());
|
||||
let mdatSize = 8;
|
||||
const mdatSizeOffset = w.getWrittenByteCount();
|
||||
await w.write((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// size
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(mdatSize),
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('mdat'),
|
||||
]));
|
||||
const updateMdatSize = async () => {
|
||||
await w.updateDataAt(mdatSizeOffset, (0, primitives_1.numberTo32BitUIntOrInt)(mdatSize));
|
||||
onBytesProgress(w.getWrittenByteCount());
|
||||
};
|
||||
const operationProm = { current: Promise.resolve() };
|
||||
const updateMoov = async () => {
|
||||
await w.updateDataAt(moovOffset, getPaddedMoovAtom());
|
||||
onBytesProgress(w.getWrittenByteCount());
|
||||
};
|
||||
const addCodecPrivateToTrack = ({ trackNumber, codecPrivate, }) => {
|
||||
currentTracks.forEach((track) => {
|
||||
if (track.trackNumber === trackNumber) {
|
||||
track.codecPrivate = codecPrivate;
|
||||
}
|
||||
});
|
||||
};
|
||||
let lastChunkWasVideo = false;
|
||||
const addSample = async ({ chunk, trackNumber, isVideo, codecPrivate, }) => {
|
||||
const position = w.getWrittenByteCount();
|
||||
await w.write(chunk.data);
|
||||
mdatSize += chunk.data.length;
|
||||
onBytesProgress(w.getWrittenByteCount());
|
||||
progressTracker.setPossibleLowestTimestamp(Math.min(chunk.timestamp, chunk.decodingTimestamp ?? Infinity));
|
||||
progressTracker.updateTrackProgress(trackNumber, chunk.timestamp);
|
||||
if (codecPrivate) {
|
||||
addCodecPrivateToTrack({ trackNumber, codecPrivate });
|
||||
}
|
||||
const currentTrack = currentTracks.find((t) => t.trackNumber === trackNumber);
|
||||
if (!currentTrack) {
|
||||
throw new Error(`Tried to add sample to track ${trackNumber}, but it doesn't exist`);
|
||||
}
|
||||
if (!lowestTrackTimestamps[trackNumber] ||
|
||||
chunk.timestamp < lowestTrackTimestamps[trackNumber]) {
|
||||
lowestTrackTimestamps[trackNumber] = chunk.timestamp;
|
||||
}
|
||||
if (typeof lowestTrackTimestamps[trackNumber] !== 'number') {
|
||||
throw new Error(`Tried to add sample to track ${trackNumber}, but it has no timestamp`);
|
||||
}
|
||||
const newDurationInMicroSeconds = chunk.timestamp +
|
||||
(chunk.duration ?? 0) -
|
||||
lowestTrackTimestamps[trackNumber];
|
||||
const newDurationInTrackTimeUnits = Math.round(newDurationInMicroSeconds / (1000000 / currentTrack.timescale));
|
||||
trackDurations[trackNumber] = newDurationInTrackTimeUnits;
|
||||
// webcodecs returns frame duration in microseconds
|
||||
const newDurationInMilliseconds = Math.round((newDurationInMicroSeconds / 1000000) * CONTAINER_TIMESCALE);
|
||||
if (newDurationInMilliseconds > globalDurationInUnits) {
|
||||
globalDurationInUnits = newDurationInMilliseconds;
|
||||
onMillisecondsProgress(newDurationInMilliseconds);
|
||||
}
|
||||
if (!samplePositions[trackNumber]) {
|
||||
samplePositions[trackNumber] = [];
|
||||
}
|
||||
if (typeof sampleChunkIndices[trackNumber] === 'undefined') {
|
||||
sampleChunkIndices[trackNumber] = 0;
|
||||
}
|
||||
// For video, make a new chunk if it's a keyframe
|
||||
if (isVideo && chunk.type === 'key') {
|
||||
sampleChunkIndices[trackNumber]++;
|
||||
} // For audio, make a new chunk every 22 samples, that's how bbb.mp4 is encoded
|
||||
else if (!isVideo && samplePositions[trackNumber].length % 22 === 0) {
|
||||
sampleChunkIndices[trackNumber]++;
|
||||
}
|
||||
// Need to create a new chunk if the last chunk was a different type
|
||||
else if (lastChunkWasVideo !== isVideo) {
|
||||
sampleChunkIndices[trackNumber]++;
|
||||
}
|
||||
// media parser and EncodedVideoChunk returns timestamps in microseconds
|
||||
// need to normalize the timestamps to milliseconds
|
||||
const samplePositionToAdd = {
|
||||
isKeyframe: chunk.type === 'key',
|
||||
offset: position,
|
||||
chunk: sampleChunkIndices[trackNumber],
|
||||
timestamp: Math.round((chunk.timestamp / 1000000) * currentTrack.timescale),
|
||||
decodingTimestamp: Math.round((chunk.decodingTimestamp / 1000000) * currentTrack.timescale),
|
||||
duration: Math.round(((chunk.duration ?? 0) / 1000000) * currentTrack.timescale),
|
||||
size: chunk.data.length,
|
||||
bigEndian: false,
|
||||
chunkSize: null,
|
||||
};
|
||||
lastChunkWasVideo = isVideo;
|
||||
samplePositions[trackNumber].push(samplePositionToAdd);
|
||||
};
|
||||
const addTrack = (track) => {
|
||||
const trackNumber = currentTracks.length + 1;
|
||||
currentTracks.push({ ...track, trackNumber });
|
||||
progressTracker.registerTrack(trackNumber);
|
||||
return Promise.resolve({ trackNumber });
|
||||
};
|
||||
const waitForFinishPromises = [];
|
||||
return {
|
||||
getBlob: () => {
|
||||
return w.getBlob();
|
||||
},
|
||||
remove: async () => {
|
||||
await w.remove();
|
||||
},
|
||||
addSample: ({ chunk, trackNumber, isVideo, codecPrivate }) => {
|
||||
operationProm.current = operationProm.current.then(() => {
|
||||
return addSample({
|
||||
chunk,
|
||||
trackNumber,
|
||||
isVideo,
|
||||
codecPrivate,
|
||||
});
|
||||
});
|
||||
return operationProm.current;
|
||||
},
|
||||
addTrack: (track) => {
|
||||
operationProm.current = operationProm.current.then(() => addTrack(track));
|
||||
return operationProm.current;
|
||||
},
|
||||
updateTrackSampleRate: ({ sampleRate, trackNumber }) => {
|
||||
currentTracks.forEach((track) => {
|
||||
if (track.trackNumber === trackNumber) {
|
||||
if (track.type !== 'audio') {
|
||||
throw new Error(`Tried to update sample rate of track ${trackNumber}, but it's not an audio track`);
|
||||
}
|
||||
track.sampleRate = sampleRate;
|
||||
}
|
||||
});
|
||||
},
|
||||
addWaitForFinishPromise: (promise) => {
|
||||
waitForFinishPromises.push(promise);
|
||||
},
|
||||
async waitForFinish() {
|
||||
media_parser_1.MediaParserInternals.Log.verbose(logLevel, 'All write operations queued. Waiting for finish...');
|
||||
await Promise.all(waitForFinishPromises.map((p) => p()));
|
||||
media_parser_1.MediaParserInternals.Log.verbose(logLevel, 'Cleanup tasks executed');
|
||||
await operationProm.current;
|
||||
await updateMoov();
|
||||
await updateMdatSize();
|
||||
media_parser_1.MediaParserInternals.Log.verbose(logLevel, 'All write operations done. Waiting for finish...');
|
||||
await w.finish();
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.createIsoBaseMedia = createIsoBaseMedia;
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
export declare const createMdia: ({ mdhd, hdlr, minf, }: {
|
||||
mdhd: Uint8Array;
|
||||
hdlr: Uint8Array;
|
||||
minf: Uint8Array;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMdia = void 0;
|
||||
const matroska_utils_1 = require("../matroska/matroska-utils");
|
||||
const primitives_1 = require("./primitives");
|
||||
const createMdia = ({ mdhd, hdlr, minf, }) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('mdia'),
|
||||
// mdhd
|
||||
mdhd,
|
||||
// hdlr
|
||||
hdlr,
|
||||
// minf
|
||||
minf,
|
||||
]));
|
||||
};
|
||||
exports.createMdia = createMdia;
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
export declare const createMoov: ({ mvhd, traks, udta, }: {
|
||||
mvhd: Uint8Array;
|
||||
traks: Uint8Array[];
|
||||
udta: Uint8Array;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMoov = void 0;
|
||||
const matroska_utils_1 = require("../matroska/matroska-utils");
|
||||
const primitives_1 = require("./primitives");
|
||||
const createMoov = ({ mvhd, traks, udta, }) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('moov'),
|
||||
// moov atom
|
||||
mvhd,
|
||||
// traks
|
||||
...traks,
|
||||
// udta
|
||||
udta,
|
||||
]));
|
||||
};
|
||||
exports.createMoov = createMoov;
|
||||
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
export declare const createMvhd: ({ timescale, durationInUnits, rate, volume, nextTrackId, matrix, creationTime, modificationTime, }: {
|
||||
timescale: number;
|
||||
durationInUnits: number;
|
||||
rate: number;
|
||||
volume: number;
|
||||
nextTrackId: number;
|
||||
matrix: number[];
|
||||
creationTime: number | null;
|
||||
modificationTime: number | null;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMvhd = void 0;
|
||||
const from_unix_timestamp_1 = require("../../from-unix-timestamp");
|
||||
const matroska_utils_1 = require("../matroska/matroska-utils");
|
||||
const primitives_1 = require("./primitives");
|
||||
const createMvhd = ({ timescale, durationInUnits, rate, volume, nextTrackId, matrix, creationTime, modificationTime, }) => {
|
||||
if (matrix.length !== 9) {
|
||||
throw new Error('Matrix must be 9 elements long');
|
||||
}
|
||||
const content = (0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('mvhd'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// creation time
|
||||
creationTime === null
|
||||
? (0, primitives_1.numberTo32BitUIntOrInt)(0)
|
||||
: (0, primitives_1.numberTo32BitUIntOrInt)((0, from_unix_timestamp_1.fromUnixTimestamp)(creationTime)),
|
||||
// modification time
|
||||
modificationTime === null
|
||||
? (0, primitives_1.numberTo32BitUIntOrInt)(0)
|
||||
: (0, primitives_1.numberTo32BitUIntOrInt)((0, from_unix_timestamp_1.fromUnixTimestamp)(modificationTime)),
|
||||
// timescale
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(timescale),
|
||||
// duration in units, 32bit for version 0
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(durationInUnits),
|
||||
// rate
|
||||
(0, primitives_1.floatTo16Point1632Bit)(rate),
|
||||
// volume
|
||||
(0, primitives_1.floatTo16Point16_16Bit)(volume),
|
||||
// reserved
|
||||
new Uint8Array([0, 0]),
|
||||
// reserved
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// reserved
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
(0, primitives_1.serializeMatrix)(matrix),
|
||||
// predefined
|
||||
(0, matroska_utils_1.combineUint8Arrays)(new Array(6).fill(new Uint8Array([0, 0, 0, 0]))),
|
||||
// next track id
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(nextTrackId),
|
||||
]);
|
||||
return (0, primitives_1.addSize)(content);
|
||||
};
|
||||
exports.createMvhd = createMvhd;
|
||||
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
export declare const createTrak: ({ tkhd, mdia, }: {
|
||||
tkhd: Uint8Array;
|
||||
mdia: Uint8Array;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createTrak = void 0;
|
||||
const truthy_1 = require("../../truthy");
|
||||
const matroska_utils_1 = require("../matroska/matroska-utils");
|
||||
const primitives_1 = require("./primitives");
|
||||
const createTrak = ({ tkhd, mdia, }) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// name
|
||||
(0, primitives_1.stringsToUint8Array)('trak'),
|
||||
// tkhd
|
||||
tkhd,
|
||||
// mdia
|
||||
mdia,
|
||||
].filter(truthy_1.truthy)));
|
||||
};
|
||||
exports.createTrak = createTrak;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createUdta: (children: Uint8Array) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createUdta = void 0;
|
||||
const matroska_utils_1 = require("../matroska/matroska-utils");
|
||||
const primitives_1 = require("./primitives");
|
||||
const createUdta = (children) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('udta'),
|
||||
// children
|
||||
children,
|
||||
]));
|
||||
};
|
||||
exports.createUdta = createUdta;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createUrlAtom: () => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createUrlAtom = void 0;
|
||||
const matroska_utils_1 = require("../matroska/matroska-utils");
|
||||
const primitives_1 = require("./primitives");
|
||||
const createUrlAtom = () => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('url '),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 1]),
|
||||
]));
|
||||
};
|
||||
exports.createUrlAtom = createUrlAtom;
|
||||
Generated
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
import type { MediaParserInternalTypes } from '@remotion/media-parser';
|
||||
export declare const exampleVideoSamplePositions: MediaParserInternalTypes['SamplePosition'][];
|
||||
export declare const exampleAudioSamplePositions: MediaParserInternalTypes['SamplePosition'][];
|
||||
Generated
Vendored
+3417
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
export declare const calculateAReasonableMp4HeaderLength: ({ expectedDurationInSeconds, expectedFrameRate, }: {
|
||||
expectedDurationInSeconds: number | null;
|
||||
expectedFrameRate: number | null;
|
||||
}) => number;
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.calculateAReasonableMp4HeaderLength = void 0;
|
||||
const calculateAReasonableMp4HeaderLength = ({ expectedDurationInSeconds, expectedFrameRate, }) => {
|
||||
if (expectedDurationInSeconds === null) {
|
||||
return 2048000;
|
||||
}
|
||||
/**
|
||||
* we had a video that was 1 hour 40 minutes long and the header ended up being 3.7MB. the header approximately grows linearly to the video length in seconds, but we should reserve enough, like at least 50KB in any case.
|
||||
* it's better to be safe than to fail, so let's add a 30% safety margin
|
||||
*/
|
||||
// This was however with 30fps, and there can also be 60fps videos, so let's
|
||||
// estimate even more conservatively and estimate 60fps
|
||||
const assumedFrameRate = expectedFrameRate ?? 60;
|
||||
const frameRateMultiplier = assumedFrameRate / 30;
|
||||
// 1h40m = 6000 seconds resulted in 3.7MB header
|
||||
// So bytes per second = 3.7MB / 6000 = ~616 bytes/second
|
||||
const bytesPerSecond = (3.7 * 1024 * 1024) / 6000;
|
||||
// Add 20% safety margin and multiply by frame rate multiplier
|
||||
const bytesWithSafetyMargin = bytesPerSecond * 1.2 * frameRateMultiplier;
|
||||
// Calculate based on duration, with minimum 50KB
|
||||
const calculatedBytes = Math.max(50 * 1024, Math.ceil(expectedDurationInSeconds * bytesWithSafetyMargin));
|
||||
return calculatedBytes;
|
||||
};
|
||||
exports.calculateAReasonableMp4HeaderLength = calculateAReasonableMp4HeaderLength;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createCmt: (comment: string) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createCmt = void 0;
|
||||
const matroska_utils_1 = require("../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../primitives");
|
||||
const createCmt = (comment) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// ©cmt
|
||||
new Uint8Array([0xa9, 0x63, 0x6d, 0x74]),
|
||||
(0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// data
|
||||
(0, primitives_1.stringsToUint8Array)('data'),
|
||||
// type indicator
|
||||
new Uint8Array([0, 0]),
|
||||
// well-known type
|
||||
new Uint8Array([0, 1]),
|
||||
// country indicator
|
||||
new Uint8Array([0, 0]),
|
||||
// language indicator
|
||||
new Uint8Array([0, 0]),
|
||||
// value
|
||||
(0, primitives_1.stringsToUint8Array)(comment),
|
||||
])),
|
||||
]));
|
||||
};
|
||||
exports.createCmt = createCmt;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createToo: (value: string) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createToo = void 0;
|
||||
const matroska_utils_1 = require("../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../primitives");
|
||||
const createToo = (value) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type: ©too
|
||||
new Uint8Array([0xa9, 0x74, 0x6f, 0x6f]),
|
||||
// data
|
||||
(0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// data
|
||||
new Uint8Array([0x64, 0x61, 0x74, 0x61]),
|
||||
// type indicator
|
||||
new Uint8Array([0, 0]),
|
||||
// well-known type
|
||||
new Uint8Array([0, 1]),
|
||||
// country indicator
|
||||
new Uint8Array([0, 0]),
|
||||
// language indicator
|
||||
new Uint8Array([0, 0]),
|
||||
// value
|
||||
(0, primitives_1.stringsToUint8Array)(value),
|
||||
])),
|
||||
]));
|
||||
};
|
||||
exports.createToo = createToo;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
export declare const createMdhd: ({ creationTime, modificationTime, timescale, duration, }: {
|
||||
creationTime: number | null;
|
||||
modificationTime: number | null;
|
||||
timescale: number;
|
||||
duration: number;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMdhd = void 0;
|
||||
const from_unix_timestamp_1 = require("../../../from-unix-timestamp");
|
||||
const matroska_utils_1 = require("../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../primitives");
|
||||
const createMdhd = ({ creationTime, modificationTime, timescale, duration, }) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('mdhd'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// creation time
|
||||
creationTime === null
|
||||
? (0, primitives_1.numberTo32BitUIntOrInt)(0)
|
||||
: (0, primitives_1.numberTo32BitUIntOrInt)((0, from_unix_timestamp_1.fromUnixTimestamp)(creationTime)),
|
||||
// modification time
|
||||
modificationTime === null
|
||||
? (0, primitives_1.numberTo32BitUIntOrInt)(0)
|
||||
: (0, primitives_1.numberTo32BitUIntOrInt)((0, from_unix_timestamp_1.fromUnixTimestamp)(modificationTime)),
|
||||
// timescale
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(timescale),
|
||||
// duration
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(Math.round((duration / 1000) * timescale)),
|
||||
// language: unspecified
|
||||
new Uint8Array([0x55, 0xc4]),
|
||||
// quality
|
||||
new Uint8Array([0, 0]),
|
||||
]));
|
||||
};
|
||||
exports.createMdhd = createMdhd;
|
||||
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
import type { MediaParserLogLevel } from '@remotion/media-parser';
|
||||
import type { IsoBaseMediaTrackData } from './serialize-track';
|
||||
export declare const createPaddedMoovAtom: ({ durationInUnits, trackInfo, timescale, expectedDurationInSeconds, logLevel, expectedFrameRate, }: {
|
||||
durationInUnits: number;
|
||||
trackInfo: IsoBaseMediaTrackData[];
|
||||
timescale: number;
|
||||
expectedDurationInSeconds: number | null;
|
||||
logLevel: MediaParserLogLevel;
|
||||
expectedFrameRate: number | null;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+58
@@ -0,0 +1,58 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createPaddedMoovAtom = void 0;
|
||||
const media_parser_1 = require("@remotion/media-parser");
|
||||
const log_1 = require("../../log");
|
||||
const create_ilst_1 = require("./create-ilst");
|
||||
const create_moov_1 = require("./create-moov");
|
||||
const create_mvhd_1 = require("./create-mvhd");
|
||||
const create_udta_1 = require("./create-udta");
|
||||
const header_length_1 = require("./header-length");
|
||||
const create_cmt_1 = require("./ilst/create-cmt");
|
||||
const create_too_1 = require("./ilst/create-too");
|
||||
const primitives_1 = require("./primitives");
|
||||
const serialize_track_1 = require("./serialize-track");
|
||||
const create_meta_1 = require("./udta/create-meta");
|
||||
const create_hdlr_1 = require("./udta/meta/create-hdlr");
|
||||
const createPaddedMoovAtom = ({ durationInUnits, trackInfo, timescale, expectedDurationInSeconds, logLevel, expectedFrameRate, }) => {
|
||||
const headerLength = (0, header_length_1.calculateAReasonableMp4HeaderLength)({
|
||||
expectedDurationInSeconds,
|
||||
expectedFrameRate,
|
||||
});
|
||||
if (expectedDurationInSeconds !== null) {
|
||||
log_1.Log.verbose(logLevel, `Expecting duration of the video to be ${expectedDurationInSeconds} seconds, allocating ${headerLength} bytes for the MP4 header.`);
|
||||
}
|
||||
else {
|
||||
log_1.Log.verbose(logLevel, `No duration was provided, allocating ${headerLength} bytes for the MP4 header.`);
|
||||
}
|
||||
return (0, primitives_1.padIsoBaseMediaBytes)((0, create_moov_1.createMoov)({
|
||||
mvhd: (0, create_mvhd_1.createMvhd)({
|
||||
timescale,
|
||||
durationInUnits,
|
||||
matrix: primitives_1.IDENTITY_MATRIX,
|
||||
nextTrackId: trackInfo
|
||||
.map((t) => t.track.trackNumber)
|
||||
.reduce((a, b) => Math.max(a, b), 0) + 1,
|
||||
rate: 1,
|
||||
volume: 1,
|
||||
creationTime: Date.now(),
|
||||
modificationTime: Date.now(),
|
||||
}),
|
||||
traks: trackInfo.map((track) => {
|
||||
return (0, serialize_track_1.serializeTrack)({
|
||||
timescale,
|
||||
track: track.track,
|
||||
durationInUnits,
|
||||
samplePositions: track.samplePositions,
|
||||
});
|
||||
}),
|
||||
udta: (0, create_udta_1.createUdta)((0, create_meta_1.createMeta)({
|
||||
hdlr: (0, create_hdlr_1.createHdlr)('mdir'),
|
||||
ilst: (0, create_ilst_1.createIlst)([
|
||||
(0, create_too_1.createToo)('WebCodecs'),
|
||||
(0, create_cmt_1.createCmt)(`Made with @remotion/webcodecs ${media_parser_1.VERSION}`),
|
||||
]),
|
||||
})),
|
||||
}), headerLength);
|
||||
};
|
||||
exports.createPaddedMoovAtom = createPaddedMoovAtom;
|
||||
Generated
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
export declare const stringsToUint8Array: (str: string) => Uint8Array<ArrayBuffer>;
|
||||
export declare const numberTo32BitUIntOrInt: (num: number) => Uint8Array<ArrayBuffer>;
|
||||
export declare const numberTo64BitUIntOrInt: (num: number | bigint) => Uint8Array<ArrayBuffer>;
|
||||
export declare const numberTo32BitUIntOrIntLeading128: (num: number) => Uint8Array<ArrayBuffer>;
|
||||
export declare const numberTo16BitUIntOrInt: (num: number) => Uint8Array<ArrayBuffer>;
|
||||
export declare const setFixedPointSignedOrUnsigned1616Number: (num: number) => Uint8Array<ArrayBuffer>;
|
||||
export declare const setFixedPointSigned230Number: (num: number) => Uint8Array<ArrayBuffer>;
|
||||
export declare const addSize: (arr: Uint8Array) => Uint8Array<ArrayBufferLike>;
|
||||
export declare const addLeading128Size: (arr: Uint8Array) => Uint8Array<ArrayBufferLike>;
|
||||
export declare const floatTo16Point1632Bit: (number: number) => Uint8Array<ArrayBuffer>;
|
||||
export declare const floatTo16Point16_16Bit: (number: number) => Uint8Array<ArrayBuffer>;
|
||||
export declare const serializeMatrix: (matrix: number[]) => Uint8Array<ArrayBufferLike>;
|
||||
export declare const stringToPascalString: (str: string) => Uint8Array<ArrayBuffer>;
|
||||
export declare const padIsoBaseMediaBytes: (data: Uint8Array, totalLength: number) => Uint8Array<ArrayBufferLike>;
|
||||
type ThreeDMatrix = [
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number
|
||||
];
|
||||
export declare const IDENTITY_MATRIX: ThreeDMatrix;
|
||||
export {};
|
||||
Generated
Vendored
+147
@@ -0,0 +1,147 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.IDENTITY_MATRIX = exports.padIsoBaseMediaBytes = exports.stringToPascalString = exports.serializeMatrix = exports.floatTo16Point16_16Bit = exports.floatTo16Point1632Bit = exports.addLeading128Size = exports.addSize = exports.setFixedPointSigned230Number = exports.setFixedPointSignedOrUnsigned1616Number = exports.numberTo16BitUIntOrInt = exports.numberTo32BitUIntOrIntLeading128 = exports.numberTo64BitUIntOrInt = exports.numberTo32BitUIntOrInt = exports.stringsToUint8Array = void 0;
|
||||
const matroska_utils_1 = require("../matroska/matroska-utils");
|
||||
const stringsToUint8Array = (str) => {
|
||||
return new TextEncoder().encode(str);
|
||||
};
|
||||
exports.stringsToUint8Array = stringsToUint8Array;
|
||||
const numberTo32BitUIntOrInt = (num) => {
|
||||
return new Uint8Array([
|
||||
(num >> 24) & 0xff,
|
||||
(num >> 16) & 0xff,
|
||||
(num >> 8) & 0xff,
|
||||
num & 0xff,
|
||||
]);
|
||||
};
|
||||
exports.numberTo32BitUIntOrInt = numberTo32BitUIntOrInt;
|
||||
const numberTo64BitUIntOrInt = (num) => {
|
||||
const bigNum = BigInt(num);
|
||||
return new Uint8Array([
|
||||
Number((bigNum >> 56n) & 0xffn),
|
||||
Number((bigNum >> 48n) & 0xffn),
|
||||
Number((bigNum >> 40n) & 0xffn),
|
||||
Number((bigNum >> 32n) & 0xffn),
|
||||
Number((bigNum >> 24n) & 0xffn),
|
||||
Number((bigNum >> 16n) & 0xffn),
|
||||
Number((bigNum >> 8n) & 0xffn),
|
||||
Number(bigNum & 0xffn),
|
||||
]);
|
||||
};
|
||||
exports.numberTo64BitUIntOrInt = numberTo64BitUIntOrInt;
|
||||
const numberTo32BitUIntOrIntLeading128 = (num) => {
|
||||
const arr = [
|
||||
(num >> 24) & 0xff,
|
||||
(num >> 16) & 0xff,
|
||||
(num >> 8) & 0xff,
|
||||
num & 0xff,
|
||||
];
|
||||
for (const i in arr) {
|
||||
if (arr[i] === 0) {
|
||||
arr[i] = 128;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Uint8Array(arr);
|
||||
};
|
||||
exports.numberTo32BitUIntOrIntLeading128 = numberTo32BitUIntOrIntLeading128;
|
||||
const numberTo16BitUIntOrInt = (num) => {
|
||||
return new Uint8Array([(num >> 8) & 0xff, num & 0xff]);
|
||||
};
|
||||
exports.numberTo16BitUIntOrInt = numberTo16BitUIntOrInt;
|
||||
const setFixedPointSignedOrUnsigned1616Number = (num) => {
|
||||
const val = Math.round(num * 2 ** 16);
|
||||
return (0, exports.numberTo32BitUIntOrInt)(val);
|
||||
};
|
||||
exports.setFixedPointSignedOrUnsigned1616Number = setFixedPointSignedOrUnsigned1616Number;
|
||||
const setFixedPointSigned230Number = (num) => {
|
||||
const val = Math.round(num * 2 ** 30);
|
||||
return (0, exports.numberTo32BitUIntOrInt)(val);
|
||||
};
|
||||
exports.setFixedPointSigned230Number = setFixedPointSigned230Number;
|
||||
const addSize = (arr) => {
|
||||
return (0, matroska_utils_1.combineUint8Arrays)([(0, exports.numberTo32BitUIntOrInt)(arr.length + 4), arr]);
|
||||
};
|
||||
exports.addSize = addSize;
|
||||
const addLeading128Size = (arr) => {
|
||||
return (0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, exports.numberTo32BitUIntOrIntLeading128)(arr.length),
|
||||
arr,
|
||||
]);
|
||||
};
|
||||
exports.addLeading128Size = addLeading128Size;
|
||||
const floatTo16Point1632Bit = (number) => {
|
||||
// Ensure the number has exactly 2 decimal places
|
||||
const fixedNumber = Number(number.toFixed(2));
|
||||
// Create a new Uint8Array of 4 bytes
|
||||
const result = new Uint8Array(4);
|
||||
// Extract digits
|
||||
const tens = Math.floor(fixedNumber / 10);
|
||||
const ones = Math.floor(fixedNumber % 10);
|
||||
const tenths = Math.floor((fixedNumber * 10) % 10);
|
||||
const hundredths = Math.floor((fixedNumber * 100) % 10);
|
||||
// Assign to array
|
||||
result[0] = tens;
|
||||
result[1] = ones;
|
||||
result[2] = tenths;
|
||||
result[3] = hundredths;
|
||||
return result;
|
||||
};
|
||||
exports.floatTo16Point1632Bit = floatTo16Point1632Bit;
|
||||
const floatTo16Point16_16Bit = (number) => {
|
||||
// Ensure the number has exactly 2 decimal places
|
||||
const fixedNumber = Number(number.toFixed(2));
|
||||
// Create a new Uint8Array of 4 bytes
|
||||
const result = new Uint8Array(2);
|
||||
// Extract digits
|
||||
const ones = Math.floor(fixedNumber % 10);
|
||||
const tenths = Math.floor((fixedNumber * 10) % 10);
|
||||
// Assign to array
|
||||
result[0] = ones;
|
||||
result[1] = tenths;
|
||||
return result;
|
||||
};
|
||||
exports.floatTo16Point16_16Bit = floatTo16Point16_16Bit;
|
||||
const serializeMatrix = (matrix) => {
|
||||
return (0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, exports.setFixedPointSignedOrUnsigned1616Number)(matrix[0]),
|
||||
(0, exports.setFixedPointSignedOrUnsigned1616Number)(matrix[1]),
|
||||
(0, exports.setFixedPointSigned230Number)(matrix[2]),
|
||||
(0, exports.setFixedPointSignedOrUnsigned1616Number)(matrix[3]),
|
||||
(0, exports.setFixedPointSignedOrUnsigned1616Number)(matrix[4]),
|
||||
(0, exports.setFixedPointSigned230Number)(matrix[5]),
|
||||
(0, exports.setFixedPointSignedOrUnsigned1616Number)(matrix[6]),
|
||||
(0, exports.setFixedPointSignedOrUnsigned1616Number)(matrix[7]),
|
||||
(0, exports.setFixedPointSigned230Number)(matrix[8]),
|
||||
]);
|
||||
};
|
||||
exports.serializeMatrix = serializeMatrix;
|
||||
const stringToPascalString = (str) => {
|
||||
// Create a fixed 32-byte Uint8Array
|
||||
const buffer = new Uint8Array(32);
|
||||
// Convert the string characters to bytes
|
||||
for (let i = 0; i < Math.min(str.length, 32); i++) {
|
||||
buffer[i] = str.charCodeAt(i);
|
||||
}
|
||||
return buffer;
|
||||
};
|
||||
exports.stringToPascalString = stringToPascalString;
|
||||
const padIsoBaseMediaBytes = (data, totalLength) => {
|
||||
if (data.length - 8 > totalLength) {
|
||||
throw new Error(`Data is longer than the total length: ${data.length - 8} > ${totalLength}. Set the 'expectedDurationInSeconds' value to avoid this problem: https://www.remotion.dev/docs/webcodecs/convert-media#expecteddurationinseconds`);
|
||||
}
|
||||
if (data.length - 8 === totalLength) {
|
||||
return data;
|
||||
}
|
||||
return (0, matroska_utils_1.combineUint8Arrays)([
|
||||
data,
|
||||
(0, exports.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, exports.stringsToUint8Array)('free'),
|
||||
new Uint8Array(totalLength - (data.length - 8)),
|
||||
])),
|
||||
]);
|
||||
};
|
||||
exports.padIsoBaseMediaBytes = padIsoBaseMediaBytes;
|
||||
exports.IDENTITY_MATRIX = [1, 0, 0, 0, 1, 0, 0, 0, 1];
|
||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
import type { MediaParserInternalTypes } from '@remotion/media-parser';
|
||||
import type { MakeTrackAudio, MakeTrackVideo } from '../make-track-info';
|
||||
export type IsoBaseMediaTrackData = {
|
||||
track: MakeTrackVideo | MakeTrackAudio;
|
||||
durationInUnits: number;
|
||||
samplePositions: MediaParserInternalTypes['SamplePosition'][];
|
||||
timescale: number;
|
||||
};
|
||||
export declare const serializeTrack: ({ track, durationInUnits, samplePositions, timescale, }: IsoBaseMediaTrackData) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+65
@@ -0,0 +1,65 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.serializeTrack = void 0;
|
||||
const create_codec_specific_data_1 = require("./codec-specific/create-codec-specific-data");
|
||||
const create_mdia_1 = require("./create-mdia");
|
||||
const create_trak_1 = require("./create-trak");
|
||||
const create_mdhd_1 = require("./mdia/create-mdhd");
|
||||
const primitives_1 = require("./primitives");
|
||||
const create_tkhd_1 = require("./trak/create-tkhd");
|
||||
const create_minf_1 = require("./trak/mdia/create-minf");
|
||||
const create_smhd_1 = require("./trak/mdia/minf/create-smhd");
|
||||
const create_stbl_1 = require("./trak/mdia/minf/create-stbl");
|
||||
const create_vmhd_1 = require("./trak/mdia/minf/create-vmhd");
|
||||
const create_hdlr_1 = require("./udta/meta/create-hdlr");
|
||||
const serializeTrack = ({ track, durationInUnits, samplePositions, timescale, }) => {
|
||||
if (track.codec !== 'h264' &&
|
||||
track.codec !== 'h265' &&
|
||||
track.codec !== 'aac') {
|
||||
throw new Error('Currently only H.264 and AAC is supported');
|
||||
}
|
||||
return (0, create_trak_1.createTrak)({
|
||||
tkhd: track.codec === 'aac'
|
||||
? (0, create_tkhd_1.createTkhdForAudio)({
|
||||
creationTime: Date.now(),
|
||||
flags: create_tkhd_1.TKHD_FLAGS.TRACK_ENABLED | create_tkhd_1.TKHD_FLAGS.TRACK_IN_MOVIE,
|
||||
modificationTime: Date.now(),
|
||||
duration: durationInUnits,
|
||||
trackId: track.trackNumber,
|
||||
volume: 1,
|
||||
timescale,
|
||||
})
|
||||
: track.type === 'video'
|
||||
? (0, create_tkhd_1.createTkhdForVideo)({
|
||||
creationTime: Date.now(),
|
||||
modificationTime: Date.now(),
|
||||
duration: durationInUnits,
|
||||
flags: create_tkhd_1.TKHD_FLAGS.TRACK_ENABLED | create_tkhd_1.TKHD_FLAGS.TRACK_IN_MOVIE,
|
||||
height: track.height,
|
||||
width: track.width,
|
||||
matrix: primitives_1.IDENTITY_MATRIX,
|
||||
trackId: track.trackNumber,
|
||||
volume: 0,
|
||||
timescale,
|
||||
})
|
||||
: new Uint8Array((0, primitives_1.stringsToUint8Array)('wrong')),
|
||||
mdia: (0, create_mdia_1.createMdia)({
|
||||
mdhd: (0, create_mdhd_1.createMdhd)({
|
||||
creationTime: null,
|
||||
modificationTime: null,
|
||||
duration: durationInUnits,
|
||||
timescale: track.timescale,
|
||||
}),
|
||||
hdlr: track.type === 'video' ? (0, create_hdlr_1.createHdlr)('video') : (0, create_hdlr_1.createHdlr)('audio'),
|
||||
minf: (0, create_minf_1.createMinf)({
|
||||
stblAtom: (0, create_stbl_1.createStbl)({
|
||||
samplePositions,
|
||||
isVideo: track.type === 'video',
|
||||
codecSpecificData: (0, create_codec_specific_data_1.createCodecSpecificData)(track),
|
||||
}),
|
||||
vmhdAtom: track.type === 'audio' ? (0, create_smhd_1.createSmhd)() : (0, create_vmhd_1.createVmhd)(),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
};
|
||||
exports.serializeTrack = serializeTrack;
|
||||
Generated
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
export declare const TKHD_FLAGS: {
|
||||
TRACK_ENABLED: number;
|
||||
TRACK_IN_MOVIE: number;
|
||||
TRACK_IN_PREVIEW: number;
|
||||
TRACK_IN_POSTER: number;
|
||||
};
|
||||
export declare const createTkhdForAudio: ({ creationTime, modificationTime, flags, trackId, duration, volume, timescale, }: {
|
||||
creationTime: number | null;
|
||||
modificationTime: number | null;
|
||||
flags: number;
|
||||
trackId: number;
|
||||
duration: number;
|
||||
volume: number;
|
||||
timescale: number;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
export declare const createTkhdForVideo: ({ creationTime, modificationTime, duration, trackId, volume, matrix, width, height, flags, timescale, }: {
|
||||
creationTime: number | null;
|
||||
modificationTime: number | null;
|
||||
trackId: number;
|
||||
duration: number;
|
||||
volume: number;
|
||||
matrix: number[];
|
||||
width: number;
|
||||
height: number;
|
||||
flags: number;
|
||||
timescale: number;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+97
@@ -0,0 +1,97 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createTkhdForVideo = exports.createTkhdForAudio = exports.TKHD_FLAGS = void 0;
|
||||
const from_unix_timestamp_1 = require("../../../from-unix-timestamp");
|
||||
const matroska_utils_1 = require("../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../primitives");
|
||||
exports.TKHD_FLAGS = {
|
||||
TRACK_ENABLED: 0x000001,
|
||||
TRACK_IN_MOVIE: 0x000002,
|
||||
TRACK_IN_PREVIEW: 0x000004,
|
||||
TRACK_IN_POSTER: 0x000008,
|
||||
};
|
||||
const createTkhdForAudio = ({ creationTime, modificationTime, flags, trackId, duration, volume, timescale, }) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// name
|
||||
(0, primitives_1.stringsToUint8Array)('tkhd'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, flags]),
|
||||
// creation time
|
||||
creationTime === null
|
||||
? (0, primitives_1.numberTo32BitUIntOrInt)(0)
|
||||
: (0, primitives_1.numberTo32BitUIntOrInt)((0, from_unix_timestamp_1.fromUnixTimestamp)(creationTime)),
|
||||
// modification time
|
||||
modificationTime === null
|
||||
? (0, primitives_1.numberTo32BitUIntOrInt)(0)
|
||||
: (0, primitives_1.numberTo32BitUIntOrInt)((0, from_unix_timestamp_1.fromUnixTimestamp)(modificationTime)),
|
||||
// trackId
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(trackId),
|
||||
// reserved
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// duration
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(Math.round((duration / 1000) * timescale)),
|
||||
// reserved
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// layer
|
||||
new Uint8Array([0, 0]),
|
||||
// alternate group, 1 = 'sound'
|
||||
new Uint8Array([0, 1]),
|
||||
// volume
|
||||
(0, primitives_1.floatTo16Point16_16Bit)(volume),
|
||||
// reserved
|
||||
new Uint8Array([0, 0]),
|
||||
// matrix
|
||||
(0, primitives_1.serializeMatrix)(primitives_1.IDENTITY_MATRIX),
|
||||
// width
|
||||
(0, primitives_1.setFixedPointSignedOrUnsigned1616Number)(0),
|
||||
// height
|
||||
(0, primitives_1.setFixedPointSignedOrUnsigned1616Number)(0),
|
||||
]));
|
||||
};
|
||||
exports.createTkhdForAudio = createTkhdForAudio;
|
||||
const createTkhdForVideo = ({ creationTime, modificationTime, duration, trackId, volume, matrix, width, height, flags, timescale, }) => {
|
||||
const content = (0, matroska_utils_1.combineUint8Arrays)([
|
||||
// name
|
||||
(0, primitives_1.stringsToUint8Array)('tkhd'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, flags]),
|
||||
// creation time
|
||||
creationTime === null
|
||||
? (0, primitives_1.numberTo32BitUIntOrInt)(0)
|
||||
: (0, primitives_1.numberTo32BitUIntOrInt)((0, from_unix_timestamp_1.fromUnixTimestamp)(creationTime)),
|
||||
// modification time
|
||||
modificationTime === null
|
||||
? (0, primitives_1.numberTo32BitUIntOrInt)(0)
|
||||
: (0, primitives_1.numberTo32BitUIntOrInt)((0, from_unix_timestamp_1.fromUnixTimestamp)(modificationTime)),
|
||||
// trackId
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(trackId),
|
||||
// reserved
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// duration
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)((duration / 1000) * timescale),
|
||||
// reserved
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// layer
|
||||
new Uint8Array([0, 0]),
|
||||
// alternate group, 0 = 'video'
|
||||
new Uint8Array([0, 0]),
|
||||
// volume
|
||||
(0, primitives_1.floatTo16Point16_16Bit)(volume),
|
||||
// reserved
|
||||
new Uint8Array([0, 0]),
|
||||
// matrix
|
||||
(0, primitives_1.serializeMatrix)(matrix),
|
||||
// width
|
||||
(0, primitives_1.setFixedPointSignedOrUnsigned1616Number)(width),
|
||||
// height
|
||||
(0, primitives_1.setFixedPointSignedOrUnsigned1616Number)(height),
|
||||
]);
|
||||
return (0, primitives_1.addSize)(content);
|
||||
};
|
||||
exports.createTkhdForVideo = createTkhdForVideo;
|
||||
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
export declare const createMinf: ({ vmhdAtom, stblAtom, }: {
|
||||
vmhdAtom: Uint8Array;
|
||||
stblAtom: Uint8Array;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMinf = void 0;
|
||||
const matroska_utils_1 = require("../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../primitives");
|
||||
const create_dinf_1 = require("./minf/create-dinf");
|
||||
const createMinf = ({ vmhdAtom, stblAtom, }) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('minf'),
|
||||
// vmhd
|
||||
vmhdAtom,
|
||||
// dinf
|
||||
(0, create_dinf_1.createDinf)(),
|
||||
// stbl
|
||||
stblAtom,
|
||||
]));
|
||||
};
|
||||
exports.createMinf = createMinf;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createDinf: () => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createDinf = void 0;
|
||||
const matroska_utils_1 = require("../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../primitives");
|
||||
const createDinf = () => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, primitives_1.stringsToUint8Array)('dinf'),
|
||||
(0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, primitives_1.stringsToUint8Array)('dref'),
|
||||
new Uint8Array([0]), // version
|
||||
new Uint8Array([0, 0, 0]), // flags
|
||||
new Uint8Array([0, 0, 0, 1]), // entry count
|
||||
(0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, primitives_1.stringsToUint8Array)('url '),
|
||||
new Uint8Array([0]), // version
|
||||
new Uint8Array([0, 0, 1]), // flags
|
||||
])),
|
||||
])),
|
||||
]));
|
||||
};
|
||||
exports.createDinf = createDinf;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createSmhd: () => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createSmhd = void 0;
|
||||
const matroska_utils_1 = require("../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../primitives");
|
||||
const createSmhd = () => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('smhd'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// balance
|
||||
new Uint8Array([0, 0]),
|
||||
// reserved
|
||||
new Uint8Array([0, 0]),
|
||||
]));
|
||||
};
|
||||
exports.createSmhd = createSmhd;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import type { MediaParserInternalTypes } from '@remotion/media-parser';
|
||||
export declare const createStbl: ({ samplePositions, codecSpecificData, isVideo, }: {
|
||||
samplePositions: MediaParserInternalTypes["SamplePosition"][];
|
||||
codecSpecificData: Uint8Array;
|
||||
isVideo: boolean;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+43
@@ -0,0 +1,43 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createStbl = void 0;
|
||||
const truthy_1 = require("../../../../../truthy");
|
||||
const matroska_utils_1 = require("../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../primitives");
|
||||
const create_ctts_1 = require("./stbl/create-ctts");
|
||||
const create_stco_1 = require("./stbl/create-stco");
|
||||
const create_stsc_1 = require("./stbl/create-stsc");
|
||||
const create_stss_1 = require("./stbl/create-stss");
|
||||
const create_stsz_1 = require("./stbl/create-stsz");
|
||||
const create_stts_1 = require("./stbl/create-stts");
|
||||
const create_avc1_1 = require("./stbl/stsd/create-avc1");
|
||||
const createStbl = ({ samplePositions, codecSpecificData, isVideo, }) => {
|
||||
// For stts:
|
||||
// https://developer.apple.com/documentation/quicktime-file-format/time-to-sample_atom
|
||||
// The sample entries are ordered by time stamps; therefore, the deltas are all nonnegative.
|
||||
// For the other tables, there doesn't seem to be a requirement for them to be sorted
|
||||
// -> ordering the sample positions by dts
|
||||
const sorted = samplePositions
|
||||
.slice()
|
||||
.sort((a, b) => a.decodingTimestamp - b.decodingTimestamp);
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, primitives_1.stringsToUint8Array)('stbl'),
|
||||
(0, create_avc1_1.createStsdData)(codecSpecificData),
|
||||
(0, create_stts_1.createSttsAtom)(sorted),
|
||||
isVideo ? (0, create_stss_1.createStss)(samplePositions) : null,
|
||||
(0, create_ctts_1.createCttsBox)(samplePositions),
|
||||
(0, create_stsc_1.createStsc)(samplePositions),
|
||||
(0, create_stsz_1.createStsz)(samplePositions),
|
||||
(0, create_stco_1.createStcoAtom)(samplePositions),
|
||||
isVideo
|
||||
? null
|
||||
: new Uint8Array([
|
||||
0x00, 0x00, 0x00, 0x1a, 0x73, 0x67, 0x70, 0x64, 0x01, 0x00, 0x00,
|
||||
0x00, 0x72, 0x6f, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||
0x00, 0x01, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1c, 0x73, 0x62, 0x67,
|
||||
0x70, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6f, 0x6c, 0x6c, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x00, 0x0a, 0x19, 0x00, 0x00, 0x00, 0x01,
|
||||
]),
|
||||
].filter(truthy_1.truthy)));
|
||||
};
|
||||
exports.createStbl = createStbl;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createVmhd: () => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createVmhd = void 0;
|
||||
const matroska_utils_1 = require("../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../primitives");
|
||||
const createVmhd = () => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('vmhd'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 1]),
|
||||
// graphics mode, 0 = copy
|
||||
new Uint8Array([0, 0]),
|
||||
// opcolor
|
||||
new Uint8Array([0, 0, 0, 0, 0, 0]),
|
||||
]));
|
||||
};
|
||||
exports.createVmhd = createVmhd;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { MediaParserInternalTypes } from '@remotion/media-parser';
|
||||
export declare const createCttsBox: (samplePositions: MediaParserInternalTypes["SamplePosition"][]) => Uint8Array<ArrayBufferLike> | null;
|
||||
Generated
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createCttsBox = void 0;
|
||||
const matroska_utils_1 = require("../../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../../primitives");
|
||||
const makeEntry = (entry) => {
|
||||
return (0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(entry.sampleCount),
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(entry.sampleOffset),
|
||||
]);
|
||||
};
|
||||
const createCttsBox = (samplePositions) => {
|
||||
const offsets = samplePositions.map((s) => s.timestamp - s.decodingTimestamp);
|
||||
const entries = [];
|
||||
let lastOffset = null;
|
||||
for (const offset of offsets) {
|
||||
if (lastOffset === offset) {
|
||||
entries[entries.length - 1].sampleCount++;
|
||||
}
|
||||
else {
|
||||
entries.push({
|
||||
sampleCount: 1,
|
||||
sampleOffset: offset,
|
||||
});
|
||||
}
|
||||
lastOffset = offset;
|
||||
}
|
||||
const needsCtts = entries.length > 0 && entries.some((e) => e.sampleOffset !== 0);
|
||||
if (!needsCtts) {
|
||||
return null;
|
||||
}
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('ctts'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// entry count
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(entries.length),
|
||||
// entries
|
||||
...entries.map((e) => makeEntry(e)),
|
||||
]));
|
||||
};
|
||||
exports.createCttsBox = createCttsBox;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { MediaParserInternalTypes } from '@remotion/media-parser';
|
||||
export declare const createStcoAtom: (samplePositions: MediaParserInternalTypes["SamplePosition"][]) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createStcoAtom = void 0;
|
||||
const matroska_utils_1 = require("../../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../../primitives");
|
||||
const createStcoAtom = (samplePositions) => {
|
||||
const chunkOffsets = [];
|
||||
let lastChunk;
|
||||
let needs64Bit = false;
|
||||
for (const sample of samplePositions) {
|
||||
if (lastChunk !== sample.chunk) {
|
||||
chunkOffsets.push(sample.offset);
|
||||
}
|
||||
if (sample.offset > 2 ** 32) {
|
||||
needs64Bit = true;
|
||||
}
|
||||
lastChunk = sample.chunk;
|
||||
}
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)(needs64Bit ? 'co64' : 'stco'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// number of entries
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(chunkOffsets.length),
|
||||
// chunk offsets
|
||||
(0, matroska_utils_1.combineUint8Arrays)(chunkOffsets.map((offset) => needs64Bit
|
||||
? (0, primitives_1.numberTo64BitUIntOrInt)(offset)
|
||||
: (0, primitives_1.numberTo32BitUIntOrInt)(offset))),
|
||||
]));
|
||||
};
|
||||
exports.createStcoAtom = createStcoAtom;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { MediaParserInternalTypes } from '@remotion/media-parser';
|
||||
export declare const createStsc: (samplePositions: MediaParserInternalTypes["SamplePosition"][]) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+56
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createStsc = void 0;
|
||||
const matroska_utils_1 = require("../../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../../primitives");
|
||||
const createEntry = (entry) => {
|
||||
return (0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(entry.firstChunk),
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(entry.samplesPerChunk),
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(entry.sampleDescriptionIndex),
|
||||
]);
|
||||
};
|
||||
const createStsc = (samplePositions) => {
|
||||
const entries = [];
|
||||
const deduplicateLastEntry = () => {
|
||||
const lastEntry = entries[entries.length - 1];
|
||||
const secondToLastEntry = entries[entries.length - 2];
|
||||
if (lastEntry &&
|
||||
secondToLastEntry &&
|
||||
lastEntry.samplesPerChunk === secondToLastEntry.samplesPerChunk &&
|
||||
lastEntry.sampleDescriptionIndex ===
|
||||
secondToLastEntry.sampleDescriptionIndex) {
|
||||
const lastIndex = entries.length - 1;
|
||||
entries.length = lastIndex;
|
||||
}
|
||||
};
|
||||
let lastChunk;
|
||||
for (const samplePosition of samplePositions) {
|
||||
if (samplePosition.chunk === lastChunk) {
|
||||
entries[entries.length - 1].samplesPerChunk++;
|
||||
}
|
||||
else {
|
||||
deduplicateLastEntry();
|
||||
entries.push({
|
||||
firstChunk: samplePosition.chunk,
|
||||
samplesPerChunk: 1,
|
||||
sampleDescriptionIndex: 1,
|
||||
});
|
||||
lastChunk = samplePosition.chunk;
|
||||
}
|
||||
}
|
||||
deduplicateLastEntry();
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('stsc'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// entry count
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(entries.length),
|
||||
// entries
|
||||
...entries.map((e) => createEntry(e)),
|
||||
]));
|
||||
};
|
||||
exports.createStsc = createStsc;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { MediaParserInternalTypes } from '@remotion/media-parser';
|
||||
export declare const createStss: (samplePositions: MediaParserInternalTypes["SamplePosition"][]) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createStss = void 0;
|
||||
const matroska_utils_1 = require("../../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../../primitives");
|
||||
const createStss = (samplePositions) => {
|
||||
const samples = samplePositions
|
||||
.map((sample, i) => [sample.isKeyframe, i])
|
||||
.filter((s) => s[0])
|
||||
.map((s) => s[1] + 1);
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('stss'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// entry count
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(samples.length),
|
||||
...samples.map((sample) => (0, primitives_1.numberTo32BitUIntOrInt)(sample)),
|
||||
]));
|
||||
};
|
||||
exports.createStss = createStss;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { MediaParserInternalTypes } from '@remotion/media-parser';
|
||||
export declare const createStsz: (samplePositions: MediaParserInternalTypes["SamplePosition"][]) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createStsz = void 0;
|
||||
const matroska_utils_1 = require("../../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../../primitives");
|
||||
const createStsz = (samplePositions) => {
|
||||
const sampleSizes = samplePositions.map((samplePosition) => samplePosition.size);
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('stsz'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// sample size
|
||||
// Possible optimization for the future: If all sizes are the same, we don't have to list them all out
|
||||
// https://developer.apple.com/documentation/quicktime-file-format/sample_size_atom
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(0),
|
||||
// number of entries
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(sampleSizes.length),
|
||||
// sample sizes
|
||||
...sampleSizes.map((size) => (0, primitives_1.numberTo32BitUIntOrInt)(size)),
|
||||
]));
|
||||
};
|
||||
exports.createStsz = createStsz;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { MediaParserInternalTypes } from '@remotion/media-parser';
|
||||
export declare const createSttsAtom: (samplePositions: MediaParserInternalTypes["SamplePosition"][]) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createSttsAtom = void 0;
|
||||
const matroska_utils_1 = require("../../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../../primitives");
|
||||
const makeEntry = (entry) => {
|
||||
if (entry.sampleOffset < 0) {
|
||||
throw new Error('negative sample offset in stts ' + entry.sampleOffset);
|
||||
}
|
||||
return (0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(entry.sampleCount),
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(entry.sampleOffset),
|
||||
]);
|
||||
};
|
||||
const createSttsAtom = (samplePositions) => {
|
||||
let lastDuration = null;
|
||||
const durations = samplePositions.map((_, i, a) => {
|
||||
// TODO: Why does 0 appear here?
|
||||
if (a[i].duration === undefined || a[i].duration === 0) {
|
||||
if (a[i + 1] === undefined) {
|
||||
return (a[i].decodingTimestamp -
|
||||
(a[i - 1]?.decodingTimestamp ?? a[i].decodingTimestamp));
|
||||
}
|
||||
return a[i + 1].decodingTimestamp - a[i].decodingTimestamp;
|
||||
}
|
||||
return a[i].duration;
|
||||
});
|
||||
const entries = [];
|
||||
for (const duration of durations) {
|
||||
if (duration === lastDuration) {
|
||||
entries[entries.length - 1].sampleCount++;
|
||||
}
|
||||
else {
|
||||
entries.push({
|
||||
sampleCount: 1,
|
||||
sampleOffset: duration,
|
||||
});
|
||||
}
|
||||
lastDuration = duration;
|
||||
}
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('stts'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// entry count
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(entries.length),
|
||||
// entries
|
||||
...entries.map((e) => makeEntry(e)),
|
||||
]));
|
||||
};
|
||||
exports.createSttsAtom = createSttsAtom;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createStsdData: (codecSpecificData: Uint8Array) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createStsdData = void 0;
|
||||
const matroska_utils_1 = require("../../../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../../../primitives");
|
||||
const createStsdData = (codecSpecificData) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('stsd'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// entry count
|
||||
new Uint8Array([0, 0, 0, 1]),
|
||||
// entry
|
||||
codecSpecificData,
|
||||
]));
|
||||
};
|
||||
exports.createStsdData = createStsdData;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createAvccBox: (privateData: Uint8Array | null) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createAvccBox = void 0;
|
||||
const matroska_utils_1 = require("../../../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../../../primitives");
|
||||
const createAvccBox = (privateData) => {
|
||||
if (!privateData) {
|
||||
throw new Error('privateData is required');
|
||||
}
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('avcC'),
|
||||
privateData,
|
||||
]));
|
||||
};
|
||||
exports.createAvccBox = createAvccBox;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createHvccBox: (privateData: Uint8Array | null) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createHvccBox = void 0;
|
||||
const matroska_utils_1 = require("../../../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../../../primitives");
|
||||
const createHvccBox = (privateData) => {
|
||||
if (!privateData) {
|
||||
throw new Error('privateData is required');
|
||||
}
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('hvcC'),
|
||||
privateData,
|
||||
]));
|
||||
};
|
||||
exports.createHvccBox = createHvccBox;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createPasp: (x: number, y: number) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createPasp = void 0;
|
||||
const matroska_utils_1 = require("../../../../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../../../../primitives");
|
||||
const createPasp = (x, y) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, primitives_1.stringsToUint8Array)('pasp'),
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(x),
|
||||
(0, primitives_1.numberTo32BitUIntOrInt)(y),
|
||||
]));
|
||||
};
|
||||
exports.createPasp = createPasp;
|
||||
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
export declare const createMeta: ({ hdlr, ilst, }: {
|
||||
hdlr: Uint8Array;
|
||||
ilst: Uint8Array;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMeta = void 0;
|
||||
const matroska_utils_1 = require("../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../primitives");
|
||||
const createMeta = ({ hdlr, ilst, }) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('meta'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// hdlr
|
||||
hdlr,
|
||||
// ilst
|
||||
ilst,
|
||||
]));
|
||||
};
|
||||
exports.createMeta = createMeta;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const createHdlr: (type: "video" | "audio" | "mdir") => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createHdlr = void 0;
|
||||
const matroska_utils_1 = require("../../../matroska/matroska-utils");
|
||||
const primitives_1 = require("../../primitives");
|
||||
const createHdlr = (type) => {
|
||||
return (0, primitives_1.addSize)((0, matroska_utils_1.combineUint8Arrays)([
|
||||
// type
|
||||
(0, primitives_1.stringsToUint8Array)('hdlr'),
|
||||
// version
|
||||
new Uint8Array([0]),
|
||||
// flags
|
||||
new Uint8Array([0, 0, 0]),
|
||||
// pre_defined
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// handler_type
|
||||
(0, primitives_1.stringsToUint8Array)(type === 'mdir' ? 'mdir' : type === 'video' ? 'vide' : 'soun'),
|
||||
// reserved
|
||||
type === 'mdir'
|
||||
? (0, primitives_1.numberTo32BitUIntOrInt)(1634758764)
|
||||
: new Uint8Array([0, 0, 0, 0]),
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
new Uint8Array([0, 0, 0, 0]),
|
||||
// name
|
||||
(0, primitives_1.stringsToUint8Array)(type === 'mdir'
|
||||
? '\0'
|
||||
: type === 'video'
|
||||
? 'VideoHandler\0'
|
||||
: 'SoundHandler\0'),
|
||||
]));
|
||||
};
|
||||
exports.createHdlr = createHdlr;
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
import type { MediaParserAdvancedColor, MediaParserAudioCodec, MediaParserVideoCodec } from '@remotion/media-parser';
|
||||
export type MakeTrackAudio = {
|
||||
trackNumber: number;
|
||||
codec: MediaParserAudioCodec;
|
||||
numberOfChannels: number;
|
||||
sampleRate: number;
|
||||
type: 'audio';
|
||||
codecPrivate: Uint8Array | null;
|
||||
timescale: number;
|
||||
};
|
||||
export type MakeTrackVideo = {
|
||||
color: MediaParserAdvancedColor;
|
||||
width: number;
|
||||
height: number;
|
||||
trackNumber: number;
|
||||
codec: MediaParserVideoCodec;
|
||||
type: 'video';
|
||||
codecPrivate: Uint8Array | null;
|
||||
timescale: number;
|
||||
};
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
export declare const CLUSTER_MIN_VINT_WIDTH = 8;
|
||||
export declare const createClusterSegment: (timestamp: number) => import("./matroska-utils").BytesAndOffset;
|
||||
export declare const makeSimpleBlock: ({ bytes, trackNumber, timecodeRelativeToCluster, keyframe, invisible, lacing, }: {
|
||||
bytes: Uint8Array;
|
||||
trackNumber: number;
|
||||
timecodeRelativeToCluster: number;
|
||||
keyframe: boolean;
|
||||
invisible: boolean;
|
||||
lacing: number;
|
||||
}) => Uint8Array<ArrayBufferLike>;
|
||||
Generated
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeSimpleBlock = exports.createClusterSegment = exports.CLUSTER_MIN_VINT_WIDTH = void 0;
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
exports.CLUSTER_MIN_VINT_WIDTH = 8;
|
||||
const createClusterSegment = (timestamp) => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Cluster',
|
||||
value: [
|
||||
{
|
||||
type: 'Timestamp',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: timestamp,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
minVintWidth: exports.CLUSTER_MIN_VINT_WIDTH,
|
||||
});
|
||||
};
|
||||
exports.createClusterSegment = createClusterSegment;
|
||||
const makeSimpleBlock = ({ bytes, trackNumber, timecodeRelativeToCluster, keyframe, invisible, lacing, }) => {
|
||||
const simpleBlockHeader = (0, matroska_utils_1.matroskaToHex)('0xa3');
|
||||
const headerByte = (Number(keyframe) << 7) | (Number(invisible) << 3) | (lacing << 1);
|
||||
const body = (0, matroska_utils_1.combineUint8Arrays)([
|
||||
(0, matroska_utils_1.getVariableInt)(trackNumber, null),
|
||||
(0, matroska_utils_1.serializeUint16)(timecodeRelativeToCluster),
|
||||
new Uint8Array([headerByte]),
|
||||
bytes,
|
||||
]);
|
||||
return (0, matroska_utils_1.combineUint8Arrays)([
|
||||
simpleBlockHeader,
|
||||
(0, matroska_utils_1.getVariableInt)(body.length, null),
|
||||
body,
|
||||
]);
|
||||
};
|
||||
exports.makeSimpleBlock = makeSimpleBlock;
|
||||
Generated
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
import type { MediaParserInternalTypes, MediaParserLogLevel } from '@remotion/media-parser';
|
||||
import { type MediaParserAudioSample, type MediaParserVideoSample } from '@remotion/media-parser';
|
||||
export declare const timestampToClusterTimestamp: (timestamp: number, timescale: number) => number;
|
||||
export declare const canFitInCluster: ({ clusterStartTimestamp, chunk, timescale, }: {
|
||||
clusterStartTimestamp: number;
|
||||
chunk: MediaParserAudioSample | MediaParserVideoSample;
|
||||
timescale: number;
|
||||
}) => boolean;
|
||||
export declare const makeCluster: ({ writer, clusterStartTimestamp, timescale, logLevel, }: {
|
||||
writer: MediaParserInternalTypes["Writer"];
|
||||
clusterStartTimestamp: number;
|
||||
timescale: number;
|
||||
logLevel: MediaParserLogLevel;
|
||||
}) => Promise<{
|
||||
addSample: (chunk: MediaParserAudioSample | MediaParserVideoSample, trackNumber: number) => Promise<{
|
||||
timecodeRelativeToCluster: number;
|
||||
}>;
|
||||
shouldMakeNewCluster: ({ isVideo, chunk, newT, }: {
|
||||
newT: number;
|
||||
chunk: MediaParserAudioSample | MediaParserVideoSample;
|
||||
isVideo: boolean;
|
||||
}) => boolean;
|
||||
startTimestamp: number;
|
||||
}>;
|
||||
Generated
Vendored
+76
@@ -0,0 +1,76 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeCluster = exports.canFitInCluster = exports.timestampToClusterTimestamp = void 0;
|
||||
const media_parser_1 = require("@remotion/media-parser");
|
||||
const log_1 = require("../../log");
|
||||
const cluster_segment_1 = require("./cluster-segment");
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const maxClusterTimestamp = 2 ** 15;
|
||||
const timestampToClusterTimestamp = (timestamp, timescale) => {
|
||||
return Math.round((timestamp / timescale) * 1000);
|
||||
};
|
||||
exports.timestampToClusterTimestamp = timestampToClusterTimestamp;
|
||||
const canFitInCluster = ({ clusterStartTimestamp, chunk, timescale, }) => {
|
||||
const timecodeRelativeToCluster = (0, exports.timestampToClusterTimestamp)(chunk.timestamp, timescale) -
|
||||
(0, exports.timestampToClusterTimestamp)(clusterStartTimestamp, timescale);
|
||||
if (timecodeRelativeToCluster < 0) {
|
||||
throw new Error(`timecodeRelativeToCluster is negative, tried to add ${chunk.timestamp} to ${clusterStartTimestamp}`);
|
||||
}
|
||||
return timecodeRelativeToCluster <= maxClusterTimestamp;
|
||||
};
|
||||
exports.canFitInCluster = canFitInCluster;
|
||||
const makeCluster = async ({ writer, clusterStartTimestamp, timescale, logLevel, }) => {
|
||||
log_1.Log.verbose(logLevel, `Making new Matroska cluster with timestamp ${clusterStartTimestamp}`);
|
||||
const cluster = (0, cluster_segment_1.createClusterSegment)((0, exports.timestampToClusterTimestamp)(clusterStartTimestamp, timescale));
|
||||
const clusterVIntPosition = writer.getWrittenByteCount() +
|
||||
cluster.offsets.offset +
|
||||
(0, matroska_utils_1.matroskaToHex)(media_parser_1.MediaParserInternals.matroskaElements.Cluster).byteLength;
|
||||
let clusterSize = cluster.bytes.byteLength -
|
||||
(0, matroska_utils_1.matroskaToHex)(media_parser_1.MediaParserInternals.matroskaElements.Cluster).byteLength -
|
||||
cluster_segment_1.CLUSTER_MIN_VINT_WIDTH;
|
||||
await writer.write(cluster.bytes);
|
||||
const addSample = async (chunk, trackNumber) => {
|
||||
const timecodeRelativeToCluster = (0, exports.timestampToClusterTimestamp)(chunk.timestamp, timescale) -
|
||||
(0, exports.timestampToClusterTimestamp)(clusterStartTimestamp, timescale);
|
||||
if (!(0, exports.canFitInCluster)({ clusterStartTimestamp, chunk, timescale })) {
|
||||
throw new Error(`timecodeRelativeToCluster is too big: ${timecodeRelativeToCluster} > ${maxClusterTimestamp}`);
|
||||
}
|
||||
const keyframe = chunk.type === 'key';
|
||||
const simpleBlock = (0, cluster_segment_1.makeSimpleBlock)({
|
||||
bytes: chunk.data,
|
||||
invisible: false,
|
||||
keyframe,
|
||||
lacing: 0,
|
||||
trackNumber,
|
||||
timecodeRelativeToCluster,
|
||||
});
|
||||
clusterSize += simpleBlock.byteLength;
|
||||
await writer.updateDataAt(clusterVIntPosition, (0, matroska_utils_1.getVariableInt)(clusterSize, cluster_segment_1.CLUSTER_MIN_VINT_WIDTH));
|
||||
await writer.write(simpleBlock);
|
||||
return { timecodeRelativeToCluster };
|
||||
};
|
||||
const shouldMakeNewCluster = ({ isVideo, chunk, newT, }) => {
|
||||
const newTimestamp = (0, exports.timestampToClusterTimestamp)(newT, timescale);
|
||||
const oldTimestamp = (0, exports.timestampToClusterTimestamp)(clusterStartTimestamp, timescale);
|
||||
const canFit = (0, exports.canFitInCluster)({
|
||||
chunk,
|
||||
clusterStartTimestamp,
|
||||
timescale,
|
||||
});
|
||||
if (!canFit) {
|
||||
// We must create a new cluster
|
||||
// This is for example if we have an audio-only file
|
||||
log_1.Log.verbose(logLevel, `Cannot fit ${chunk.timestamp} in cluster ${clusterStartTimestamp}. Creating new cluster`);
|
||||
return true;
|
||||
}
|
||||
const keyframe = chunk.type === 'key';
|
||||
// TODO: Timestamp falls apart when video only
|
||||
return newTimestamp - oldTimestamp >= 2000 && keyframe && isVideo;
|
||||
};
|
||||
return {
|
||||
addSample,
|
||||
shouldMakeNewCluster,
|
||||
startTimestamp: clusterStartTimestamp,
|
||||
};
|
||||
};
|
||||
exports.makeCluster = makeCluster;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { MediaParserAdvancedColor } from '@remotion/media-parser';
|
||||
export declare const makeMatroskaColorBytes: ({ transfer: transferCharacteristics, matrix: matrixCoefficients, primaries, fullRange, }: MediaParserAdvancedColor) => import("./matroska-utils").BytesAndOffset;
|
||||
Generated
Vendored
+142
@@ -0,0 +1,142 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeMatroskaColorBytes = void 0;
|
||||
const truthy_1 = require("../../truthy");
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const getRangeValue = ({ transferCharacteristics, matrixCoefficients, fullRange, }) => {
|
||||
return transferCharacteristics && matrixCoefficients
|
||||
? 3
|
||||
: fullRange === true
|
||||
? 2
|
||||
: fullRange === false
|
||||
? 1
|
||||
: 0;
|
||||
};
|
||||
// https://w3c.github.io/webcodecs/#videocolorprimaries
|
||||
const getPrimariesValue = (primaries) => {
|
||||
if (primaries === null) {
|
||||
return null;
|
||||
}
|
||||
if (primaries === 'bt709') {
|
||||
return 1;
|
||||
}
|
||||
if (primaries === 'bt470bg') {
|
||||
return 5;
|
||||
}
|
||||
if (primaries === 'smpte170m') {
|
||||
return 6;
|
||||
}
|
||||
if (primaries === 'bt2020') {
|
||||
return 9;
|
||||
}
|
||||
if (primaries === 'smpte432') {
|
||||
return 12;
|
||||
}
|
||||
throw new Error('Unknown primaries ' + primaries);
|
||||
};
|
||||
const getTransferCharacteristicsValue = (transferCharacteristics) => {
|
||||
if (transferCharacteristics === null) {
|
||||
return null;
|
||||
}
|
||||
if (transferCharacteristics === 'bt709') {
|
||||
return 1;
|
||||
}
|
||||
if (transferCharacteristics === 'smpte170m') {
|
||||
return 6;
|
||||
}
|
||||
if (transferCharacteristics === 'iec61966-2-1') {
|
||||
return 13;
|
||||
}
|
||||
if (transferCharacteristics === 'linear') {
|
||||
return 8;
|
||||
}
|
||||
if (transferCharacteristics === 'pq') {
|
||||
return 16;
|
||||
}
|
||||
if (transferCharacteristics === 'hlg') {
|
||||
return 18;
|
||||
}
|
||||
throw new Error('Unknown transfer characteristics ' +
|
||||
transferCharacteristics);
|
||||
};
|
||||
const getMatrixCoefficientsValue = (matrixCoefficients) => {
|
||||
if (matrixCoefficients === null) {
|
||||
return null;
|
||||
}
|
||||
if (matrixCoefficients === 'rgb') {
|
||||
return 0;
|
||||
}
|
||||
if (matrixCoefficients === 'bt709') {
|
||||
return 1;
|
||||
}
|
||||
if (matrixCoefficients === 'bt470bg') {
|
||||
return 5;
|
||||
}
|
||||
if (matrixCoefficients === 'smpte170m') {
|
||||
return 6;
|
||||
}
|
||||
if (matrixCoefficients === 'bt2020-ncl') {
|
||||
return 9;
|
||||
}
|
||||
throw new Error('Unknown matrix coefficients ' + matrixCoefficients);
|
||||
};
|
||||
const makeMatroskaColorBytes = ({ transfer: transferCharacteristics, matrix: matrixCoefficients, primaries, fullRange, }) => {
|
||||
const rangeValue = getRangeValue({
|
||||
transferCharacteristics,
|
||||
matrixCoefficients,
|
||||
fullRange,
|
||||
});
|
||||
// https://datatracker.ietf.org/doc/draft-ietf-cellar-matroska/
|
||||
// 5.1.4.1.28.27
|
||||
const primariesValue = getPrimariesValue(primaries);
|
||||
const transferChracteristicsValue = getTransferCharacteristicsValue(transferCharacteristics);
|
||||
if (matrixCoefficients === 'rgb') {
|
||||
throw new Error('Cannot encode Matroska in RGB');
|
||||
}
|
||||
const matrixCoefficientsValue = getMatrixCoefficientsValue(matrixCoefficients);
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Colour',
|
||||
minVintWidth: null,
|
||||
value: [
|
||||
transferChracteristicsValue === null
|
||||
? null
|
||||
: {
|
||||
type: 'TransferCharacteristics',
|
||||
value: {
|
||||
value: transferChracteristicsValue,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
matrixCoefficientsValue === null
|
||||
? null
|
||||
: {
|
||||
type: 'MatrixCoefficients',
|
||||
value: {
|
||||
value: matrixCoefficientsValue,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
primariesValue === null
|
||||
? null
|
||||
: {
|
||||
type: 'Primaries',
|
||||
value: {
|
||||
value: primariesValue,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'Range',
|
||||
value: {
|
||||
value: rangeValue,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
].filter(truthy_1.truthy),
|
||||
});
|
||||
};
|
||||
exports.makeMatroskaColorBytes = makeMatroskaColorBytes;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { MediaFn, MediaFnGeneratorInput } from '../media-fn';
|
||||
export declare const createMatroskaMedia: ({ writer, onBytesProgress, onMillisecondsProgress, filename, logLevel, progressTracker, }: MediaFnGeneratorInput) => Promise<MediaFn>;
|
||||
Generated
Vendored
+206
@@ -0,0 +1,206 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMatroskaMedia = void 0;
|
||||
const media_parser_1 = require("@remotion/media-parser");
|
||||
const cluster_1 = require("./cluster");
|
||||
const make_duration_with_padding_1 = require("./make-duration-with-padding");
|
||||
const matroska_cues_1 = require("./matroska-cues");
|
||||
const matroska_header_1 = require("./matroska-header");
|
||||
const matroska_info_1 = require("./matroska-info");
|
||||
const matroska_seek_1 = require("./matroska-seek");
|
||||
const matroska_segment_1 = require("./matroska-segment");
|
||||
const matroska_trackentry_1 = require("./matroska-trackentry");
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const { matroskaElements } = media_parser_1.MediaParserInternals;
|
||||
const timescale = 1000000;
|
||||
const createMatroskaMedia = async ({ writer, onBytesProgress, onMillisecondsProgress, filename, logLevel, progressTracker, }) => {
|
||||
const header = (0, matroska_header_1.makeMatroskaHeader)();
|
||||
const w = await writer.createContent({
|
||||
filename,
|
||||
mimeType: 'video/webm',
|
||||
logLevel,
|
||||
});
|
||||
await w.write(header.bytes);
|
||||
const matroskaInfo = (0, matroska_info_1.makeMatroskaInfo)({
|
||||
timescale,
|
||||
});
|
||||
const currentTracks = [];
|
||||
const seeks = [];
|
||||
const cues = [];
|
||||
const trackNumbers = [];
|
||||
const matroskaSegment = (0, matroska_segment_1.createMatroskaSegment)([
|
||||
...(0, matroska_seek_1.createMatroskaSeekHead)(seeks),
|
||||
matroskaInfo,
|
||||
...(0, matroska_trackentry_1.makeMatroskaTracks)(currentTracks),
|
||||
]);
|
||||
const infoSegment = matroskaSegment.offsets.children.find((o) => o.field === 'Info');
|
||||
const durationOffset = (infoSegment?.children.find((c) => c.field === 'Duration')?.offset ?? 0) +
|
||||
w.getWrittenByteCount();
|
||||
const tracksOffset = (matroskaSegment.offsets.children.find((o) => o.field === 'Tracks')
|
||||
?.offset ?? 0) + w.getWrittenByteCount();
|
||||
const seekHeadOffset = (matroskaSegment.offsets.children.find((o) => o.field === 'SeekHead')
|
||||
?.offset ?? 0) + w.getWrittenByteCount();
|
||||
const infoOffset = (infoSegment?.offset ?? 0) + w.getWrittenByteCount();
|
||||
if (!seekHeadOffset) {
|
||||
throw new Error('could not get seek offset');
|
||||
}
|
||||
if (!durationOffset) {
|
||||
throw new Error('could not get duration offset');
|
||||
}
|
||||
if (!tracksOffset) {
|
||||
throw new Error('could not get tracks offset');
|
||||
}
|
||||
if (!infoOffset) {
|
||||
throw new Error('could not get tracks offset');
|
||||
}
|
||||
seeks.push({
|
||||
hexString: matroskaElements.Info,
|
||||
byte: infoOffset - seekHeadOffset,
|
||||
});
|
||||
seeks.push({
|
||||
hexString: matroskaElements.Tracks,
|
||||
byte: tracksOffset - seekHeadOffset,
|
||||
});
|
||||
const updateSeekWrite = async () => {
|
||||
const updatedSeek = (0, matroska_seek_1.createMatroskaSeekHead)(seeks);
|
||||
await w.updateDataAt(seekHeadOffset, (0, matroska_utils_1.combineUint8Arrays)(updatedSeek.map((b) => b.bytes)));
|
||||
onBytesProgress(w.getWrittenByteCount());
|
||||
};
|
||||
const segmentOffset = w.getWrittenByteCount();
|
||||
const updateSegmentSize = async (size) => {
|
||||
const data = (0, matroska_utils_1.getVariableInt)(size, matroska_segment_1.MATROSKA_SEGMENT_MIN_VINT_WIDTH);
|
||||
await w.updateDataAt(segmentOffset + (0, matroska_utils_1.matroskaToHex)(matroskaElements.Segment).byteLength, data);
|
||||
onBytesProgress(w.getWrittenByteCount());
|
||||
};
|
||||
await w.write(matroskaSegment.bytes);
|
||||
const clusterOffset = w.getWrittenByteCount();
|
||||
let currentCluster = await (0, cluster_1.makeCluster)({
|
||||
writer: w,
|
||||
clusterStartTimestamp: 0,
|
||||
timescale,
|
||||
logLevel,
|
||||
});
|
||||
seeks.push({
|
||||
hexString: matroskaElements.Cluster,
|
||||
byte: clusterOffset - seekHeadOffset,
|
||||
});
|
||||
const getClusterOrMakeNew = async ({ chunk, isVideo, }) => {
|
||||
// In Safari, samples can arrive out of order, e.g public/bigbuckbunny.mp4
|
||||
// Therefore, only updating track number progress if it is a keyframe
|
||||
// to allow for timestamps to be lower than the previous one
|
||||
progressTracker.setPossibleLowestTimestamp(Math.min(chunk.timestamp, chunk.decodingTimestamp ?? Infinity));
|
||||
const smallestProgress = progressTracker.getSmallestProgress();
|
||||
if (!currentCluster.shouldMakeNewCluster({
|
||||
newT: smallestProgress,
|
||||
isVideo,
|
||||
chunk,
|
||||
})) {
|
||||
return {
|
||||
cluster: currentCluster,
|
||||
isNew: false,
|
||||
smallestProgress,
|
||||
};
|
||||
}
|
||||
currentCluster = await (0, cluster_1.makeCluster)({
|
||||
writer: w,
|
||||
clusterStartTimestamp: smallestProgress,
|
||||
timescale,
|
||||
logLevel,
|
||||
});
|
||||
return {
|
||||
cluster: currentCluster,
|
||||
isNew: true,
|
||||
smallestProgress,
|
||||
};
|
||||
};
|
||||
const updateDuration = async (newDuration) => {
|
||||
const blocks = (0, make_duration_with_padding_1.makeDurationWithPadding)(newDuration);
|
||||
await w.updateDataAt(durationOffset, blocks.bytes);
|
||||
onBytesProgress(w.getWrittenByteCount());
|
||||
};
|
||||
const addSample = async ({ chunk, trackNumber, isVideo, }) => {
|
||||
const offset = w.getWrittenByteCount();
|
||||
const { cluster, isNew, smallestProgress } = await getClusterOrMakeNew({
|
||||
chunk,
|
||||
isVideo,
|
||||
});
|
||||
const newDuration = Math.round((chunk.timestamp + (chunk.duration ?? 0)) / 1000);
|
||||
await updateDuration(newDuration);
|
||||
const { timecodeRelativeToCluster } = await cluster.addSample(chunk, trackNumber);
|
||||
if (isNew) {
|
||||
if (offset === null) {
|
||||
throw new Error('offset is null');
|
||||
}
|
||||
cues.push({
|
||||
time: (0, cluster_1.timestampToClusterTimestamp)(smallestProgress, timescale) +
|
||||
timecodeRelativeToCluster,
|
||||
clusterPosition: offset - seekHeadOffset,
|
||||
trackNumber,
|
||||
});
|
||||
}
|
||||
if (chunk.type === 'key') {
|
||||
progressTracker.updateTrackProgress(trackNumber, chunk.timestamp);
|
||||
}
|
||||
onBytesProgress(w.getWrittenByteCount());
|
||||
onMillisecondsProgress(newDuration);
|
||||
};
|
||||
const addTrack = async (track) => {
|
||||
currentTracks.push(track);
|
||||
const newTracks = (0, matroska_trackentry_1.makeMatroskaTracks)(currentTracks);
|
||||
progressTracker.registerTrack(track.trackNumber);
|
||||
await w.updateDataAt(tracksOffset, (0, matroska_utils_1.combineUint8Arrays)(newTracks.map((b) => b.bytes)));
|
||||
};
|
||||
const operationProm = { current: Promise.resolve() };
|
||||
const waitForFinishPromises = [];
|
||||
return {
|
||||
updateTrackSampleRate: ({ sampleRate, trackNumber }) => {
|
||||
currentTracks.forEach((track) => {
|
||||
if (track.trackNumber === trackNumber) {
|
||||
if (track.type !== 'audio') {
|
||||
throw new Error('track is not audio');
|
||||
}
|
||||
track.sampleRate = sampleRate;
|
||||
}
|
||||
});
|
||||
},
|
||||
getBlob: () => {
|
||||
return w.getBlob();
|
||||
},
|
||||
remove: async () => {
|
||||
await w.remove();
|
||||
},
|
||||
addSample: ({ chunk, trackNumber, isVideo }) => {
|
||||
operationProm.current = operationProm.current.then(() => addSample({ chunk, trackNumber, isVideo }));
|
||||
return operationProm.current;
|
||||
},
|
||||
addTrack: (track) => {
|
||||
const trackNumber = currentTracks.length + 1;
|
||||
operationProm.current = operationProm.current.then(() => addTrack({ ...track, trackNumber }));
|
||||
trackNumbers.push(trackNumber);
|
||||
return operationProm.current.then(() => ({ trackNumber }));
|
||||
},
|
||||
addWaitForFinishPromise: (promise) => {
|
||||
waitForFinishPromises.push(promise);
|
||||
},
|
||||
async waitForFinish() {
|
||||
await Promise.all(waitForFinishPromises.map((p) => p()));
|
||||
await operationProm.current;
|
||||
const cuesBytes = (0, matroska_cues_1.createMatroskaCues)(cues);
|
||||
if (cuesBytes) {
|
||||
seeks.push({
|
||||
hexString: matroskaElements.Cues,
|
||||
byte: w.getWrittenByteCount() - seekHeadOffset,
|
||||
});
|
||||
await w.write(cuesBytes.bytes);
|
||||
}
|
||||
await updateSeekWrite();
|
||||
const segmentSize = w.getWrittenByteCount() -
|
||||
segmentOffset -
|
||||
(0, matroska_utils_1.matroskaToHex)(matroskaElements.Segment).byteLength -
|
||||
matroska_segment_1.MATROSKA_SEGMENT_MIN_VINT_WIDTH;
|
||||
await updateSegmentSize(segmentSize);
|
||||
await w.finish();
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.createMatroskaMedia = createMatroskaMedia;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const makeDurationWithPadding: (newDuration: number) => import("./matroska-utils").BytesAndOffset;
|
||||
Generated
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeDurationWithPadding = void 0;
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const makeDurationWithPadding = (newDuration) => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Duration',
|
||||
value: {
|
||||
value: newDuration,
|
||||
size: '64',
|
||||
},
|
||||
minVintWidth: 8,
|
||||
});
|
||||
};
|
||||
exports.makeDurationWithPadding = makeDurationWithPadding;
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import type { BytesAndOffset } from './matroska-utils';
|
||||
export type Cue = {
|
||||
time: number;
|
||||
clusterPosition: number;
|
||||
trackNumber: number;
|
||||
};
|
||||
export declare const createMatroskaCues: (cues: Cue[]) => BytesAndOffset | null;
|
||||
Generated
Vendored
+52
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMatroskaCues = void 0;
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const createMatroskaCues = (cues) => {
|
||||
if (cues.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Cues',
|
||||
minVintWidth: null,
|
||||
value: cues.map((cue) => {
|
||||
return {
|
||||
type: 'CuePoint',
|
||||
value: [
|
||||
{
|
||||
type: 'CueTime',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: cue.time,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'CueTrackPositions',
|
||||
value: [
|
||||
{
|
||||
type: 'CueTrack',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: cue.trackNumber,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'CueClusterPosition',
|
||||
minVintWidth: null,
|
||||
value: {
|
||||
value: cue.clusterPosition,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
minVintWidth: null,
|
||||
},
|
||||
],
|
||||
minVintWidth: null,
|
||||
};
|
||||
}),
|
||||
});
|
||||
};
|
||||
exports.createMatroskaCues = createMatroskaCues;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const makeMatroskaHeader: () => import("./matroska-utils").BytesAndOffset;
|
||||
Generated
Vendored
+66
@@ -0,0 +1,66 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeMatroskaHeader = void 0;
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const makeMatroskaHeader = () => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Header',
|
||||
value: [
|
||||
{
|
||||
minVintWidth: null,
|
||||
type: 'EBMLVersion',
|
||||
value: {
|
||||
value: 1,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
minVintWidth: null,
|
||||
type: 'EBMLReadVersion',
|
||||
value: {
|
||||
value: 1,
|
||||
byteLength: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'EBMLMaxIDLength',
|
||||
value: {
|
||||
byteLength: null,
|
||||
value: 4,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'EBMLMaxSizeLength',
|
||||
value: {
|
||||
byteLength: null,
|
||||
value: 8,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'DocType',
|
||||
value: 'webm',
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'DocTypeVersion',
|
||||
value: {
|
||||
byteLength: null,
|
||||
value: 4,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'DocTypeReadVersion',
|
||||
value: {
|
||||
byteLength: null,
|
||||
value: 2,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
],
|
||||
minVintWidth: null,
|
||||
});
|
||||
};
|
||||
exports.makeMatroskaHeader = makeMatroskaHeader;
|
||||
Generated
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
export declare const makeMatroskaInfo: ({ timescale }: {
|
||||
timescale: number;
|
||||
}) => import("./matroska-utils").BytesAndOffset;
|
||||
Generated
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeMatroskaInfo = void 0;
|
||||
const make_duration_with_padding_1 = require("./make-duration-with-padding");
|
||||
const matroska_utils_1 = require("./matroska-utils");
|
||||
const makeMatroskaInfo = ({ timescale }) => {
|
||||
return (0, matroska_utils_1.makeMatroskaBytes)({
|
||||
type: 'Info',
|
||||
value: [
|
||||
{
|
||||
type: 'TimestampScale',
|
||||
value: {
|
||||
value: timescale,
|
||||
byteLength: null,
|
||||
},
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'MuxingApp',
|
||||
value: '@remotion/webcodecs',
|
||||
minVintWidth: null,
|
||||
},
|
||||
{
|
||||
type: 'WritingApp',
|
||||
value: '@remotion/webcodecs',
|
||||
minVintWidth: null,
|
||||
},
|
||||
(0, make_duration_with_padding_1.makeDurationWithPadding)(0),
|
||||
],
|
||||
minVintWidth: null,
|
||||
});
|
||||
};
|
||||
exports.makeMatroskaInfo = makeMatroskaInfo;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user