This commit is contained in:
Vanilagy
2025-04-25 17:35:05 +02:00
10 changed files with 36 additions and 24 deletions
+5 -5
View File
@@ -35,7 +35,7 @@ export abstract class InputFormat {
export abstract class IsobmffInputFormat extends InputFormat {
/** @internal */
protected async _getMajorBrand(input: Input) {
const sourceSize = await input._mainReader.source._getSize();
const sourceSize = await input._mainReader.source.getSize();
if (sourceSize < 12) {
return null;
}
@@ -104,7 +104,7 @@ export class QuickTimeInputFormat extends IsobmffInputFormat {
export class MatroskaInputFormat extends InputFormat {
/** @internal */
protected async isSupportedEBMLOfDocType(input: Input, desiredDocType: string) {
const sourceSize = await input._mainReader.source._getSize();
const sourceSize = await input._mainReader.source.getSize();
if (sourceSize < 8) {
return false;
}
@@ -209,7 +209,7 @@ export class WebMInputFormat extends MatroskaInputFormat {
export class Mp3InputFormat extends InputFormat {
/** @internal */
async _canReadInput(input: Input) {
const sourceSize = await input._mainReader.source._getSize();
const sourceSize = await input._mainReader.source.getSize();
if (sourceSize < 4) {
return false;
}
@@ -274,7 +274,7 @@ export class Mp3InputFormat extends InputFormat {
export class WaveInputFormat extends InputFormat {
/** @internal */
async _canReadInput(input: Input) {
const sourceSize = await input._mainReader.source._getSize();
const sourceSize = await input._mainReader.source.getSize();
if (sourceSize < 12) {
return false;
}
@@ -311,7 +311,7 @@ export class WaveInputFormat extends InputFormat {
export class OggInputFormat extends InputFormat {
/** @internal */
async _canReadInput(input: Input) {
const sourceSize = await input._mainReader.source._getSize();
const sourceSize = await input._mainReader.source.getSize();
if (sourceSize < 4) {
return false;
}
+13 -5
View File
@@ -8,20 +8,20 @@ import { Source } from './source';
* The options for creating an Input object.
* @public
*/
export type InputOptions = {
export type InputOptions<S extends Source = Source> = {
/** A list of supported formats. If the source file is not of one of these formats, then it cannot be read. */
formats: InputFormat[];
/** The source from which data will be read. */
source: Source;
source: S;
};
/**
* Represents an input media file. This is the root object from which all media read operations start.
* @public
*/
export class Input {
export class Input<S extends Source = Source> {
/** @internal */
_source: Source;
_source: S;
/** @internal */
_formats: InputFormat[];
/** @internal */
@@ -31,7 +31,7 @@ export class Input {
/** @internal */
_format: InputFormat | null = null;
constructor(options: InputOptions) {
constructor(options: InputOptions<S>) {
if (!options || typeof options !== 'object') {
throw new TypeError('options must be an object.');
}
@@ -64,6 +64,14 @@ export class Input {
})();
}
/**
* Returns the source from which this input file reads its data. This is the same source that was passed to the
* constructor.
*/
get source() {
return this._source;
}
/**
* Returns the format of the input file. You can compare this result directly to the InputFormat singletons or use
* `instanceof` checks for subset-aware logic (for example, `format instanceof MatroskaInputFormat` is true for
+3 -3
View File
@@ -198,7 +198,7 @@ export class IsobmffDemuxer extends Demuxer {
super(input);
this.metadataReader = new IsobmffReader(input._mainReader);
this.chunkReader = new IsobmffReader(new Reader(input._source, 64 * 2 ** 20)); // Max 64 MiB of stored chunks
this.chunkReader = new IsobmffReader(new Reader(input.source, 64 * 2 ** 20)); // Max 64 MiB of stored chunks
}
override async computeDuration() {
@@ -235,7 +235,7 @@ export class IsobmffDemuxer extends Demuxer {
readMetadata() {
return this.metadataPromise ??= (async () => {
const sourceSize = await this.metadataReader.reader.source._getSize();
const sourceSize = await this.metadataReader.reader.source.getSize();
while (this.metadataReader.pos < sourceSize) {
await this.metadataReader.reader.loadRange(
@@ -2191,7 +2191,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
}
const metadataReader = demuxer.metadataReader;
const sourceSize = await metadataReader.reader.source._getSize();
const sourceSize = await metadataReader.reader.source.getSize();
let prevFragment: Fragment | null = null;
let bestFragmentIndex = fragmentIndex;
+3 -3
View File
@@ -165,7 +165,7 @@ export class MatroskaDemuxer extends Demuxer {
this.metadataReader = new EBMLReader(input._mainReader);
// Max 64 MiB of stored clusters
this.clusterReader = new EBMLReader(new Reader(input._source, 64 * 2 ** 20));
this.clusterReader = new EBMLReader(new Reader(input.source, 64 * 2 ** 20));
}
override async computeDuration() {
@@ -211,7 +211,7 @@ export class MatroskaDemuxer extends Demuxer {
return this.readMetadataPromise ??= (async () => {
this.metadataReader.pos = 0;
const fileSize = await this.input._source._getSize();
const fileSize = await this.input.source.getSize();
while (this.metadataReader.pos < fileSize - MIN_HEADER_SIZE) {
await this.metadataReader.reader.loadRange(
@@ -258,7 +258,7 @@ export class MatroskaDemuxer extends Demuxer {
dataStartPos: segmentDataStart,
elementEndPos: dataSize === -1
? (await this.input._source._getSize() - MIN_HEADER_SIZE)
? (await this.input.source.getSize() - MIN_HEADER_SIZE)
: segmentDataStart + dataSize,
clusterSeekStartPos: segmentDataStart,
+1 -1
View File
@@ -32,7 +32,7 @@ export class Mp3Demuxer extends Demuxer {
async readMetadata() {
return this.metadataPromise ??= (async () => {
const fileSize = await this.input._source._getSize();
const fileSize = await this.input.source.getSize();
this.reader.fileSize = fileSize;
// Just load the entire file. Primitive, but the only way to actually ensure 100% correct timestamps.
+2 -2
View File
@@ -38,12 +38,12 @@ export class OggDemuxer extends Demuxer {
super(input);
// We don't need a persistent metadata reader as we read all metadata once at the start and then never again
this.reader = new OggReader(new Reader(input._source, 64 * 2 ** 20));
this.reader = new OggReader(new Reader(input.source, 64 * 2 ** 20));
}
async readMetadata() {
return this.metadataPromise ??= (async () => {
this.fileSize = await this.input._source._getSize();
this.fileSize = await this.input.source.getSize();
while (this.reader.pos < this.fileSize - MIN_PAGE_HEADER_SIZE) {
await this.reader.reader.loadRange(
+1 -1
View File
@@ -25,7 +25,7 @@ export class Reader {
constructor(public source: Source, public maxStorableBytes = Infinity) {}
async loadRange(start: number, end: number) {
end = Math.min(end, await this.source._getSize());
end = Math.min(end, await this.source.getSize());
if (start >= end) {
return;
+5 -2
View File
@@ -13,8 +13,11 @@ export abstract class Source {
/** @internal */
_sizePromise: Promise<number> | null = null;
/** @internal */
_getSize() {
/**
* Resolves with the total size of the file in bytes. This function is memoized, meaning only the first call
* will retrieve the size.
*/
getSize() {
return this._sizePromise ??= this._retrieveSize();
}
+1 -1
View File
@@ -37,7 +37,7 @@ export class WaveDemuxer extends Demuxer {
super(input);
this.metadataReader = new RiffReader(input._mainReader);
this.chunkReader = new RiffReader(new Reader(input._source, 64 * 2 ** 20));
this.chunkReader = new RiffReader(new Reader(input.source, 64 * 2 ** 20));
}
async readMetadata() {
+2 -1
View File
@@ -1,4 +1,5 @@
- https://github.com/Vanilagy/mp4-muxer/issues/83 tell him it's possible now
- cross-track offset for streaming sources
- textsubtitlesource, chunked piping
- More efficient MP3 loading when reading sequentially
- More efficient MP3 loading when reading sequentially
- Validate types returned by custom coders