* Add non-owning conversions via ConversionOptions.ownsOutput
A conversion with ownsOutput: false only adds tracks to the output and
drives their media data; starting, finalizing, and metadata tags remain
the caller's responsibility. This lets multiple conversions and
directly-added user tracks compose on a single Output (see upstream
issue #436).
- ownsOutput: false allows a pre-populated output (state must still be
'pending') and seeds track-capacity accounting from existing tracks
- execute() requires the output to be started and never finalizes it
- cancel() closes only the conversion's own sources, releasing internal
synchronizer waiters, and leaves the output usable
- tags cannot be combined with ownsOutput: false
- isValid requires at least one contributed track instead of the
format's minimum track counts
Prototype for API discussion; default (owning) behavior is unchanged.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AJdfnbY9AFh9i9dKgtrj6E
* Add external-audio example using a non-owning conversion
Demonstrates composing a user-owned audio track (synthesized voiceover
via OfflineAudioContext + AudioBufferSource) onto a picked video with
Conversion.init({ ownsOutput: false }), including progress reporting
and playback/download of the result.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AJdfnbY9AFh9i9dKgtrj6E
* Release synchronizer waiters when canceling during output finalization
A non-owning conversion's cancel() previously no-oped entirely when the
output (owned by someone else) was already finalizing or finalized,
leaving pump loops parked in the track synchronizer and hanging
execute() forever. Now it still marks the conversion canceled and
releases parked waiters in that state, without force-closing sources
(finalization owns flushing them at that point).
Also adds coverage: non-owning onProgress monotonicity, canceling one
of two sibling conversions, capacity seeding across sequential inits,
exact metadata exclusivity, and cancel-before-execute.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AJdfnbY9AFh9i9dKgtrj6E
* Document non-owning conversions on the converting-media-files guide page
Adds the doc section requested in #436: what ownsOutput: false does, the
required choreography (add tracks -> output.start() before execute() ->
run the conversion concurrently with your own sources -> finalize), the
cancellation split (conversion.cancel() leaves the output alive; cancel
both for a full abort and tear the output down on error paths), isValid
semantics in this mode, and the tags restriction with the
setMetadataTags() alternative. Also cross-links the fresh-output rule to
the new section. VitePress build passes with dead-link checking on.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
* Clean up conversion logic, add Output.tracks and .hasEnoughTracks(), move new conversion tests around, remove external audio example
* non-owning -> composable, and update docs
* Update
---------
Co-authored-by: Claude <[email protected]>
Co-authored-by: Vanilagy <[email protected]>
Subtitle cues were written as SimpleBlocks, which carry no duration. A
SimpleBlock tells the player when a cue starts but not how long to show it,
so players such as VLC and libass-based renderers display nothing for
S_TEXT/WEBVTT tracks muxed into Matroska/WebM.
Route a subtitle chunk that has a positive duration through a BlockGroup so
its BlockDuration is written, matching how additions are already handled.
Non-subtitle tracks and zero-duration cues keep using SimpleBlocks.
Co-authored-by: hikari <[email protected]>
* 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 <[email protected]>
Co-authored-by: Vanilagy <[email protected]>
* Add extension decoders to media player example
* Enable extension decoders in input examples
* Simplify media player file filter
* Align input file filters across examples