mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-28 19:33:51 +02:00
Address a bunch of TODOs and add parameter validation everywhere
This commit is contained in:
+48
-5
@@ -32,7 +32,7 @@ export type OutputAudioTrack = OutputTrack & { type: 'audio' };
|
||||
export type OutputSubtitleTrack = OutputTrack & { type: 'subtitle' };
|
||||
|
||||
type VideoTrackMetadata = {
|
||||
rotation?: 0 | 90 | 180 | 270 | TransformationMatrix,
|
||||
rotation?: 0 | 90 | 180 | 270 | TransformationMatrix, // TODO respect this field for Matroska
|
||||
frameRate?: number
|
||||
};
|
||||
type AudioTrackMetadata = {};
|
||||
@@ -46,6 +46,16 @@ export class Output {
|
||||
finalizing = false;
|
||||
|
||||
constructor(options: OutputOptions) {
|
||||
if (!options || typeof options !== 'object') {
|
||||
throw new TypeError('options must be an object.');
|
||||
}
|
||||
if (!(options.format instanceof OutputFormat)) {
|
||||
throw new TypeError('options.format must be an OutputFormat.');
|
||||
}
|
||||
if (!(options.target instanceof Target)) {
|
||||
throw new TypeError('options.target must be a Target.');
|
||||
}
|
||||
|
||||
if (options.target.output) {
|
||||
throw new Error('Target is already used for another output.');
|
||||
}
|
||||
@@ -56,14 +66,51 @@ export class Output {
|
||||
}
|
||||
|
||||
addVideoTrack(source: VideoSource, metadata: VideoTrackMetadata = {}) {
|
||||
if (!(source instanceof VideoSource)) {
|
||||
throw new TypeError('source must be a VideoSource.');
|
||||
}
|
||||
if (!metadata || typeof metadata !== 'object') {
|
||||
throw new TypeError('metadata must be an object.');
|
||||
}
|
||||
if (typeof metadata.rotation === 'number' && ![0, 90, 180, 270].includes(metadata.rotation)) {
|
||||
throw new TypeError(`Invalid video rotation: ${metadata.rotation}. Has to be 0, 90, 180 or 270.`);
|
||||
} else if (
|
||||
Array.isArray(metadata.rotation) &&
|
||||
(metadata.rotation.length !== 9 || metadata.rotation.some(value => !Number.isFinite(value)))
|
||||
) {
|
||||
throw new TypeError(`Invalid video transformation matrix: ${metadata.rotation.join()}`);
|
||||
}
|
||||
if (
|
||||
metadata.frameRate !== undefined &&
|
||||
(!Number.isInteger(metadata.frameRate) || metadata.frameRate <= 0)
|
||||
) {
|
||||
throw new TypeError(
|
||||
`Invalid video frame rate: ${metadata.frameRate}. Must be a positive integer.`
|
||||
);
|
||||
}
|
||||
|
||||
this.addTrack('video', source, metadata);
|
||||
}
|
||||
|
||||
addAudioTrack(source: AudioSource, metadata: AudioTrackMetadata = {}) {
|
||||
if (!(source instanceof AudioSource)) {
|
||||
throw new TypeError('source must be an AudioSource.');
|
||||
}
|
||||
if (!metadata || typeof metadata !== 'object') {
|
||||
throw new TypeError('metadata must be an object.');
|
||||
}
|
||||
|
||||
this.addTrack('audio', source, metadata);
|
||||
}
|
||||
|
||||
addSubtitleTrack(source: SubtitleSource, metadata: SubtitleTrackMetadata = {}) {
|
||||
if (!(source instanceof SubtitleSource)) {
|
||||
throw new TypeError('source must be a SubtitleSource.');
|
||||
}
|
||||
if (!metadata || typeof metadata !== 'object') {
|
||||
throw new TypeError('metadata must be an object.');
|
||||
}
|
||||
|
||||
this.addTrack('subtitle', source, metadata);
|
||||
}
|
||||
|
||||
@@ -90,8 +137,6 @@ export class Output {
|
||||
}
|
||||
|
||||
start() {
|
||||
// TODO: Warn / throw if there are no sources
|
||||
|
||||
if (this.started) {
|
||||
throw new Error('Output already started.');
|
||||
}
|
||||
@@ -105,8 +150,6 @@ export class Output {
|
||||
}
|
||||
|
||||
async finalize() {
|
||||
// TODO: Test what happens when finalizing without a single chunk of media
|
||||
|
||||
if (this.finalizing) {
|
||||
throw new Error('Cannot call finalize twice.');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user