Add compileSampleStats

This commit is contained in:
Vanilagy
2025-01-04 14:25:22 +01:00
parent 5bb9f8609c
commit b8c0d76503
5 changed files with 55 additions and 5 deletions
+5 -1
View File
@@ -49,6 +49,10 @@
const videoTrack = await input.getPrimaryVideoTrack(); const videoTrack = await input.getPrimaryVideoTrack();
const drain = new Metamuxer.EncodedVideoSampleDrain(videoTrack); const drain = new Metamuxer.EncodedVideoSampleDrain(videoTrack);
console.log(await videoTrack.computeSampleStats())
document.body.textContent = performance.now() - start;
return;
const decoderConfig = await videoTrack.getDecoderConfig(); const decoderConfig = await videoTrack.getDecoderConfig();
const sampleSource = new Metamuxer.EncodedVideoSampleSource(await videoTrack.getCodec()); const sampleSource = new Metamuxer.EncodedVideoSampleSource(await videoTrack.getCodec());
output.addVideoTrack(sampleSource); output.addVideoTrack(sampleSource);
@@ -65,7 +69,7 @@
} }
await output.finalize(); await output.finalize();
document.body.textContent = performance.now() - start;
console.log(target) console.log(target)
+1 -1
View File
@@ -58,7 +58,7 @@ export {
WEBM, WEBM,
} from './input-format'; } from './input-format';
export { Input, InputOptions } from './input'; export { Input, InputOptions } from './input';
export { InputTrack, InputVideoTrack, InputAudioTrack } from './input-track'; export { InputTrack, InputVideoTrack, InputAudioTrack, SampleStats } from './input-track';
export { export {
EncodedVideoSample, EncodedVideoSample,
EncodedAudioSample, EncodedAudioSample,
+42 -1
View File
@@ -1,10 +1,11 @@
import { AudioCodec, MediaCodec, VideoCodec } from './codec'; import { AudioCodec, MediaCodec, VideoCodec } from './codec';
import { SampleRetrievalOptions } from './media-drain'; import { EncodedAudioSampleDrain, EncodedVideoSampleDrain, SampleRetrievalOptions } from './media-drain';
import { Rotation } from './misc'; import { Rotation } from './misc';
import { EncodedAudioSample, EncodedVideoSample } from './sample'; import { EncodedAudioSample, EncodedVideoSample } from './sample';
export interface InputTrackBacking { export interface InputTrackBacking {
getCodec(): Promise<MediaCodec | null>; getCodec(): Promise<MediaCodec | null>;
getFirstTimestamp(): Promise<number>;
computeDuration(): Promise<number>; computeDuration(): Promise<number>;
} }
@@ -30,6 +31,10 @@ export abstract class InputTrack {
return this instanceof InputAudioTrack; return this instanceof InputAudioTrack;
} }
getFirstTimestamp() {
return this._backing.getFirstTimestamp();
}
computeDuration() { computeDuration() {
return this._backing.computeDuration(); return this._backing.computeDuration();
} }
@@ -109,6 +114,10 @@ export class InputVideoTrack extends InputTrack {
return false; return false;
} }
} }
computeSampleStats() {
return computeSampleStats(new EncodedVideoSampleDrain(this));
}
} }
export interface InputAudioTrackBacking extends InputTrackBacking { export interface InputAudioTrackBacking extends InputTrackBacking {
@@ -174,4 +183,36 @@ export class InputAudioTrack extends InputTrack {
return false; return false;
} }
} }
computeSampleStats() {
return computeSampleStats(new EncodedAudioSampleDrain(this));
}
} }
/** @public */
export type SampleStats = {
sampleCount: number;
averageSampleRate: number;
averageBitrate: number;
};
const computeSampleStats = async (drain: EncodedVideoSampleDrain | EncodedAudioSampleDrain): Promise<SampleStats> => {
let startTimestamp = Infinity;
let endTimestamp = -Infinity;
let sampleCount = 0;
let totalSampleBytes = 0;
for await (const sample of drain.samples(undefined, undefined, { metadataOnly: true })) {
startTimestamp = Math.min(startTimestamp, sample.timestamp);
endTimestamp = Math.max(endTimestamp, sample.timestamp + sample.duration);
sampleCount++;
totalSampleBytes += sample.byteLength;
}
return {
sampleCount,
averageSampleRate: sampleCount ? Math.fround(sampleCount / (endTimestamp - startTimestamp)) : 0,
averageBitrate: sampleCount ? Math.fround(8 * totalSampleBytes / (endTimestamp - startTimestamp)) : 0,
};
};
+5
View File
@@ -1673,6 +1673,11 @@ abstract class IsobmffTrackBacking<
throw new Error('Not implemented on base class.'); throw new Error('Not implemented on base class.');
} }
async getFirstTimestamp() {
const firstSample = await this.getFirstSample({ metadataOnly: true });
return firstSample?.timestamp ?? 0;
}
async computeDuration() { async computeDuration() {
const lastSample = await this.getSample(Infinity, { metadataOnly: true }); const lastSample = await this.getSample(Infinity, { metadataOnly: true });
return (lastSample?.timestamp ?? 0) + (lastSample?.duration ?? 0); return (lastSample?.timestamp ?? 0) + (lastSample?.duration ?? 0);
+2 -2
View File
@@ -2,8 +2,8 @@
- Throw if edit list detected - Throw if edit list detected
- Add the new audio codecs to muxers - Add the new audio codecs to muxers
- Mov muxer!!! Only mov can hold PCM audio, MP4 cannot - Mov muxer!!! Only mov can hold PCM audio, MP4 cannot
- Metadata methods for computing average fps and bitrate
- A stream source?? Or like a callback-driven source - A stream source?? Or like a callback-driven source
- onRead callback for Source - onRead callback for Source
- onHeader, etc callbacks for Matroska - onHeader, etc callbacks for Matroska
- Add cslg box - Add cslg box
- https://github.com/Vanilagy/mp4-muxer/issues/83 tell him it's possible now