diff --git a/dev/player.html b/dev/player.html index 7dd4d8f..4fbbe07 100644 --- a/dev/player.html +++ b/dev/player.html @@ -41,7 +41,7 @@ const input = new Metamuxer.Input({ source }); -console.log(await input.getMimeType()) +console.log(await input.getMimeType()); let videoTrack = await input.getPrimaryVideoTrack(); let audioTrack = await input.getPrimaryAudioTrack(); diff --git a/src/index.ts b/src/index.ts index 84a0be1..d30c020 100644 --- a/src/index.ts +++ b/src/index.ts @@ -68,7 +68,7 @@ export { } from './codec'; export { Target, BufferTarget, StreamTarget, StreamTargetChunk, StreamTargetOptions } from './target'; export { Rotation, TransformationMatrix, AnyIterable, setVideoFrameTiming } from './misc'; -export { Source, BufferSource, BlobSource, UrlSource } from './source'; +export { Source, BufferSource, StreamSource, StreamSourceOptions, BlobSource, UrlSource } from './source'; export { InputFormat, IsobmffInputFormat, diff --git a/src/source.ts b/src/source.ts index 9357b76..28a06e5 100644 --- a/src/source.ts +++ b/src/source.ts @@ -32,16 +32,54 @@ export class BufferSource extends Source { } /** @internal */ - override async _read(start: number, end: number) { + async _read(start: number, end: number) { return this._bytes.subarray(start, end); } /** @internal */ - override async _retrieveSize() { + async _retrieveSize() { return this._bytes.byteLength; } } +/** @public */ +export type StreamSourceOptions = { + read: (start: number, end: number) => Uint8Array | Promise; + getSize: () => number | Promise; +}; + +/** @public */ +export class StreamSource extends Source { + /** @internal */ + _options: StreamSourceOptions; + + constructor(options: StreamSourceOptions) { + if (!options || typeof options !== 'object') { + throw new TypeError('options must be an object.'); + } + if (typeof options.read !== 'function') { + throw new TypeError('options.read must be a function.'); + } + if (typeof options.getSize !== 'function') { + throw new TypeError('options.getSize must be a function.'); + } + + super(); + + this._options = options; + } + + /** @internal */ + async _read(start: number, end: number) { + return this._options.read(start, end); + } + + /** @internal */ + async _retrieveSize() { + return this._options.getSize(); + } +} + /** @public */ export class BlobSource extends Source { /** @internal */ @@ -58,14 +96,14 @@ export class BlobSource extends Source { } /** @internal */ - override async _read(start: number, end: number) { + async _read(start: number, end: number) { const slice = this._blob.slice(start, end); const buffer = await slice.arrayBuffer(); return new Uint8Array(buffer); } /** @internal */ - override async _retrieveSize() { + async _retrieveSize() { return this._blob.size; } } @@ -140,7 +178,7 @@ export class UrlSource extends Source { } /** @internal */ - override async _read(start: number, end: number): Promise { + async _read(start: number, end: number): Promise { if (this._fullData) { return new Uint8Array(this._fullData, start, end - start); } @@ -158,7 +196,7 @@ export class UrlSource extends Source { } /** @internal */ - override async _retrieveSize(): Promise { + async _retrieveSize(): Promise { if (this._fullData) { return this._fullData.byteLength; } diff --git a/todo.txt b/todo.txt index c37bc4b..03447b2 100644 --- a/todo.txt +++ b/todo.txt @@ -1,3 +1,2 @@ -- A stream source?? Or like a callback-driven source - onHeader, etc callbacks for Matroska - https://github.com/Vanilagy/mp4-muxer/issues/83 tell him it's possible now \ No newline at end of file