@@ -30,7 +30,7 @@ import { mehdBox } from '#/boxes/mehd';
3030import { metaBox } from '#/boxes/meta' ;
3131import { mfhdBox } from '#/boxes/mfhd' ;
3232import { mvhdBox } from '#/boxes/mvhd' ;
33- import { stppSampleEntry } from '#/boxes/sampleentries' ;
33+ import { mp4aSampleEntry , stppSampleEntry } from '#/boxes/sampleentries' ;
3434import {
3535 AudioSampleEntry ,
3636 HintSampleEntry ,
@@ -245,10 +245,15 @@ export class ISOFile<TSegmentUser = unknown, TSampleUser = unknown> {
245245 nbSamplesPerFragment : number ;
246246 sizePerSegment : number ;
247247 rapAlignement : boolean ;
248+ normalizeAudioSampleEntriesForMSE : boolean ;
248249 } > ,
249250 ) {
250251 // Destructure and provide defaults for optional properties
251- const { sizePerSegment = Number . MAX_SAFE_INTEGER , rapAlignement = true } = opts ;
252+ const {
253+ sizePerSegment = Number . MAX_SAFE_INTEGER ,
254+ rapAlignement = true ,
255+ normalizeAudioSampleEntriesForMSE = true ,
256+ } = opts ;
252257
253258 // Set defaults for sample counts
254259 let nbSamples = opts . nbSamples ?? opts . nbSamplesPerFragment ?? 1000 ;
@@ -292,6 +297,7 @@ export class ISOFile<TSegmentUser = unknown, TSampleUser = unknown> {
292297 nb_samples_per_fragment : nbSamplesPerFragment ,
293298 size_per_segment : sizePerSegment ,
294299 rapAlignement,
300+ normalizeAudioSampleEntriesForMSE,
295301 state : {
296302 lastFragmentSampleNumber : 0 ,
297303 lastSegmentSampleNumber : 0 ,
@@ -1261,29 +1267,45 @@ export class ISOFile<TSegmentUser = unknown, TSampleUser = unknown> {
12611267 * Modify the file and create the initialization segment
12621268 * @bundle isofile-write.js
12631269 */
1264- static writeInitializationSegment ( ftyp : ftypBox , moov : moovBox , total_duration : number ) {
1270+ static writeInitializationSegment (
1271+ ftyp : ftypBox ,
1272+ moov : moovBox ,
1273+ total_duration : number ,
1274+ normalizeAudioSampleEntryTrackIds ?: Set < number > ,
1275+ ) {
12651276 Log . debug ( 'ISOFile' , 'Generating initialization segment' ) ;
12661277
12671278 const stream = new DataStream ( ) ;
12681279 ftyp . write ( stream ) ;
12691280
1270- /* we can now create the new mvex box */
1271- const mvex = moov . addBox ( new mvexBox ( ) ) ;
1272- if ( total_duration ) {
1273- const mehd = mvex . addBox ( new mehdBox ( ) ) ;
1274- mehd . fragment_duration = total_duration ;
1275- }
1281+ const restoreCallbacks = ISOFile . normalizeAudioSampleEntriesForMSEFragmentedInit (
1282+ moov . traks ,
1283+ normalizeAudioSampleEntryTrackIds ,
1284+ ) ;
1285+
1286+ try {
1287+ /* we can now create the new mvex box */
1288+ const mvex = moov . addBox ( new mvexBox ( ) ) ;
1289+ if ( total_duration ) {
1290+ const mehd = mvex . addBox ( new mehdBox ( ) ) ;
1291+ mehd . fragment_duration = total_duration ;
1292+ }
12761293
1277- // Add trex boxes for each track
1278- for ( let i = 0 ; i < moov . traks . length ; i ++ ) {
1279- const trex = mvex . addBox ( new trexBox ( ) ) ;
1280- trex . track_id = moov . traks [ i ] . tkhd . track_id ;
1281- trex . default_sample_description_index = 1 ;
1282- trex . default_sample_duration = moov . traks [ i ] . samples [ 0 ] ?. duration ?? 0 ;
1283- trex . default_sample_size = 0 ;
1284- trex . default_sample_flags = 1 << 16 ;
1294+ // Add trex boxes for each track
1295+ for ( let i = 0 ; i < moov . traks . length ; i ++ ) {
1296+ const trex = mvex . addBox ( new trexBox ( ) ) ;
1297+ trex . track_id = moov . traks [ i ] . tkhd . track_id ;
1298+ trex . default_sample_description_index = 1 ;
1299+ trex . default_sample_duration = moov . traks [ i ] . samples [ 0 ] ?. duration ?? 0 ;
1300+ trex . default_sample_size = 0 ;
1301+ trex . default_sample_flags = 1 << 16 ;
1302+ }
1303+ moov . write ( stream ) ;
1304+ } finally {
1305+ for ( let i = restoreCallbacks . length - 1 ; i >= 0 ; i -- ) {
1306+ restoreCallbacks [ i ] ( ) ;
1307+ }
12851308 }
1286- moov . write ( stream ) ;
12871309
12881310 return stream . buffer ;
12891311 }
@@ -1304,6 +1326,51 @@ export class ISOFile<TSegmentUser = unknown, TSampleUser = unknown> {
13041326 return stream ;
13051327 }
13061328
1329+ /** @bundle isofile-write.js */
1330+ private static normalizeAudioSampleEntriesForMSEFragmentedInit (
1331+ traks : Array < trakBox > ,
1332+ normalizeAudioSampleEntryTrackIds ?: Set < number > ,
1333+ ) {
1334+ const restoreCallbacks : Array < ( ) => void > = [ ] ;
1335+
1336+ for ( const trak of traks ) {
1337+ if ( ! normalizeAudioSampleEntryTrackIds ?. has ( trak . tkhd . track_id ) ) {
1338+ continue ;
1339+ }
1340+
1341+ for ( const sampleEntry of trak . mdia . minf . stbl . stsd ?. entries ?? [ ] ) {
1342+ if ( ! ( sampleEntry instanceof mp4aSampleEntry ) ) {
1343+ continue ;
1344+ }
1345+
1346+ const esds = sampleEntry . wave ?. esds ;
1347+
1348+ if ( sampleEntry . esds || ! esds ) {
1349+ continue ;
1350+ }
1351+
1352+ const previousEsds = sampleEntry . esds ;
1353+ const previousWave = sampleEntry . wave ;
1354+ const previousBoxes = sampleEntry . boxes ;
1355+
1356+ restoreCallbacks . push ( ( ) => {
1357+ sampleEntry . esds = previousEsds ;
1358+ sampleEntry . wave = previousWave ;
1359+ sampleEntry . boxes = previousBoxes ;
1360+ } ) ;
1361+
1362+ const boxesWithoutWave = Array . isArray ( sampleEntry . boxes )
1363+ ? sampleEntry . boxes . filter ( box => box ?. type !== 'wave' && box ?. type !== 'esds' )
1364+ : [ ] ;
1365+ sampleEntry . esds = esds ;
1366+ sampleEntry . boxes = [ ...boxesWithoutWave , esds ] ;
1367+ sampleEntry . wave = undefined ;
1368+ }
1369+ }
1370+
1371+ return restoreCallbacks ;
1372+ }
1373+
13071374 /** @bundle isofile-write.js */
13081375 initializeSegmentation ( mode ?: 'combined' ) : SegmentationInitialization < TSegmentUser > ;
13091376 initializeSegmentation (
@@ -1339,6 +1406,11 @@ export class ISOFile<TSegmentUser = unknown, TSampleUser = unknown> {
13391406 }
13401407
13411408 const fragmentDuration = this . moov ?. mvex ?. mehd . fragment_duration ;
1409+ const normalizeAudioSampleEntryTrackIds = new Set (
1410+ this . fragmentedTracks
1411+ . filter ( track => track . normalizeAudioSampleEntriesForMSE !== false )
1412+ . map ( track => track . id ) ,
1413+ ) ;
13421414
13431415 if ( mode === 'per-track' ) {
13441416 return tracksToInitialize . map ( ( { id, user, trak } ) => {
@@ -1349,7 +1421,12 @@ export class ISOFile<TSegmentUser = unknown, TSampleUser = unknown> {
13491421 return {
13501422 id,
13511423 user,
1352- buffer : ISOFile . writeInitializationSegment ( this . ftyp , moov , fragmentDuration ) ,
1424+ buffer : ISOFile . writeInitializationSegment (
1425+ this . ftyp ,
1426+ moov ,
1427+ fragmentDuration ,
1428+ normalizeAudioSampleEntryTrackIds ,
1429+ ) ,
13531430 } ;
13541431 } ) ;
13551432 }
@@ -1363,7 +1440,12 @@ export class ISOFile<TSegmentUser = unknown, TSampleUser = unknown> {
13631440
13641441 return {
13651442 tracks : tracksToInitialize . map ( ( { id, user } ) => ( { id, user } ) ) ,
1366- buffer : ISOFile . writeInitializationSegment ( this . ftyp , moov , fragmentDuration ) ,
1443+ buffer : ISOFile . writeInitializationSegment (
1444+ this . ftyp ,
1445+ moov ,
1446+ fragmentDuration ,
1447+ normalizeAudioSampleEntryTrackIds ,
1448+ ) ,
13671449 } ;
13681450 }
13691451
0 commit comments