Add getMimeType to Output & other small adjustments

This commit is contained in:
Vanilagy
2025-06-07 22:51:57 +02:00
parent 85bd7bdcf4
commit c7c57e2132
21 changed files with 330 additions and 101 deletions
+5 -10
View File
@@ -7,7 +7,7 @@ import { PacketRetrievalOptions } from '../media-sink';
import { assert, AsyncMutex, findLast, roundToPrecision, toDataView, UNDETERMINED_LANGUAGE } from '../misc';
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
import { Reader } from '../reader';
import { computeOggPageCrc, extractSampleMetadata, OggCodecInfo } from './ogg-misc';
import { buildOggMimeType, computeOggPageCrc, extractSampleMetadata, OggCodecInfo } from './ogg-misc';
import { MAX_PAGE_HEADER_SIZE, MAX_PAGE_SIZE, MIN_PAGE_HEADER_SIZE, OggReader, Page } from './ogg-reader';
type LogicalBitstream = {
@@ -366,16 +366,11 @@ export class OggDemuxer extends Demuxer {
async getMimeType() {
await this.readMetadata();
let string = 'audio/ogg';
const codecStrings = await Promise.all(this.tracks.map(x => x.getCodecParameterString()));
if (this.tracks.length > 0) {
const codecMimeTypes = await Promise.all(this.tracks.map(x => x.getCodecParameterString()));
const uniqueCodecMimeTypes = [...new Set(codecMimeTypes.filter(Boolean))];
string += `; codecs="${uniqueCodecMimeTypes.join(', ')}"`;
}
return string;
return buildOggMimeType({
codecStrings: codecStrings.filter(Boolean) as string[],
});
}
async getTracks() {
+13
View File
@@ -93,3 +93,16 @@ export const extractSampleMetadata = (
vorbisBlockSize: currentBlocksize,
};
};
export const buildOggMimeType = (info: {
codecStrings: string[];
}) => {
let string = 'audio/ogg';
if (info.codecStrings) {
const uniqueCodecMimeTypes = [...new Set(info.codecStrings)];
string += `; codecs="${uniqueCodecMimeTypes.join(', ')}"`;
}
return string;
};
+34 -5
View File
@@ -1,12 +1,13 @@
import { OPUS_INTERNAL_SAMPLE_RATE, validateAudioChunkMetadata } from '../codec';
import { parseModesFromVorbisSetupPacket, parseOpusIdentificationHeader } from '../codec-data';
import { assert, setInt64, toDataView, toUint8Array } from '../misc';
import { assert, promiseWithResolvers, setInt64, toDataView, toUint8Array } from '../misc';
import { Muxer } from '../muxer';
import { Output, OutputAudioTrack } from '../output';
import { OggOutputFormat } from '../output-format';
import { EncodedPacket } from '../packet';
import { Writer } from '../writer';
import {
buildOggMimeType,
computeOggPageCrc,
extractSampleMetadata,
OggCodecInfo,
@@ -46,6 +47,7 @@ export class OggMuxer extends Muxer {
private trackDatas: OggTrackData[] = [];
private bosPagesWritten = false;
private allTracksKnown = promiseWithResolvers();
private pageBytes = new Uint8Array(MAX_PAGE_SIZE);
private pageView = new DataView(this.pageBytes.buffer);
@@ -63,6 +65,14 @@ export class OggMuxer extends Muxer {
// Nothin'
}
async getMimeType() {
await this.allTracksKnown.promise;
return buildOggMimeType({
codecStrings: this.trackDatas.map(x => x.codecInfo.codec!),
});
}
addEncodedVideoPacket(): never {
throw new Error('Video tracks are not supported.');
}
@@ -112,6 +122,11 @@ export class OggMuxer extends Muxer {
this.queueHeaderPackets(newTrackData, meta);
this.trackDatas.push(newTrackData);
if (this.allTracksAreKnown()) {
this.allTracksKnown.resolve();
}
return newTrackData;
}
@@ -250,12 +265,20 @@ export class OggMuxer extends Muxer {
throw new Error('Subtitle tracks are not supported.');
}
allTracksAreKnown() {
for (const track of this.output._tracks) {
if (!track.source._closed && !this.trackDatas.some(x => x.track === track)) {
return false; // We haven't seen a sample from this open track yet
}
}
return true;
}
async interleavePages(isFinalCall = false) {
if (!this.bosPagesWritten) {
for (const track of this.output._tracks) {
if (!track.source._closed && !this.trackDatas.some(x => x.track === track)) {
return; // We haven't seen a sample from this open track yet
}
if (!this.allTracksAreKnown()) {
return; // We can't interleave yet as we don't yet know how many tracks we'll truly have
}
// Write the header page for all bitstreams
@@ -421,6 +444,10 @@ export class OggMuxer extends Muxer {
override async onTrackClose() {
const release = await this.mutex.acquire();
if (this.allTracksAreKnown()) {
this.allTracksKnown.resolve();
}
// Since a track is now closed, we may be able to write out chunks that were previously waiting
await this.interleavePages();
@@ -430,6 +457,8 @@ export class OggMuxer extends Muxer {
async finalize() {
const release = await this.mutex.acquire();
this.allTracksKnown.resolve();
await this.interleavePages(true);
for (const trackData of this.trackDatas) {