From 454476ab26fdab30529ceca0622664251f57275c Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 18 Jul 2026 22:45:23 +0900 Subject: [PATCH] Fix WebVTT-in-MP4 output by starting the aux writer (#441) * Fix WebVTT-in-MP4 output by starting the aux writer The ISOBMFF muxer advertises WebVTT as a supported subtitle codec and maps it to the wvtt sample entry, but IsobmffMuxer.start() never calls auxWriter.start(). The aux writer builds subtitle sample boxes in memory, so the first box write for any subtitle track hits its started === false assert and muxing fails. Start the aux writer alongside the main writer so WebVTT subtitle tracks can be written to MP4/MOV. * Move code around, add simple WebVTT muxing test --------- Co-authored-by: hikari Co-authored-by: Vanilagy <1696106+Vanilagy@users.noreply.github.com> --- src/isobmff/isobmff-muxer.ts | 2 ++ test/node/webvtt.test.ts | 57 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 test/node/webvtt.test.ts diff --git a/src/isobmff/isobmff-muxer.ts b/src/isobmff/isobmff-muxer.ts index c9baf86..bf3a89e 100644 --- a/src/isobmff/isobmff-muxer.ts +++ b/src/isobmff/isobmff-muxer.ts @@ -206,6 +206,8 @@ export class IsobmffMuxer extends Muxer { this.isCmaf = format instanceof CmafOutputFormat; this.minimumFragmentDuration = format._options.minimumFragmentDuration ?? (format instanceof CmafOutputFormat ? Infinity : 1); + + this.auxWriter.start(); } async start() { diff --git a/test/node/webvtt.test.ts b/test/node/webvtt.test.ts new file mode 100644 index 0000000..5f3f72c --- /dev/null +++ b/test/node/webvtt.test.ts @@ -0,0 +1,57 @@ +import { test } from 'vitest'; +import { Output } from '../../src/output.js'; +import { MkvOutputFormat, Mp4OutputFormat } from '../../src/output-format.js'; +import { BufferTarget } from '../../src/target.js'; +import { TextSubtitleSource } from '../../src/media-source.js'; + +test('ISOBMFF muxing', async () => { + const output = new Output({ + format: new Mp4OutputFormat(), + target: new BufferTarget(), + }); + + const source = new TextSubtitleSource('webvtt'); + output.addSubtitleTrack(source); + + await output.start(); + + await source.add(`WEBVTT + +00:00.000 --> 00:00.900 +Hildy! + +00:01.000 --> 00:01.400 +How are you? + +00:01.500 --> 00:02.900 +Tell me, is the lord of the universe in? +`); + + await output.finalize(); +}); + +test('Matroska muxing', async () => { + const output = new Output({ + format: new MkvOutputFormat(), + target: new BufferTarget(), + }); + + const source = new TextSubtitleSource('webvtt'); + output.addSubtitleTrack(source); + + await output.start(); + + await source.add(`WEBVTT + +00:00.000 --> 00:00.900 +Hildy! + +00:01.000 --> 00:01.400 +How are you? + +00:01.500 --> 00:02.900 +Tell me, is the lord of the universe in? +`); + + await output.finalize(); +});