* fix: release targets from Output._targets on finalize
Long-running HLS transcodes leak memory. Every finalized BufferTarget
stays in _targets until the outer Output closes, pinning its buffer.
Writer.finalize() already does this cleanup for writer-based flows;
extend it to buffer-finalize paths via the public 'finalized' event.
* fix: ReadOrchestrator LRU eviction picks only drained workers
assert(pendingSlices.length === 0) fires under heavy concurrent reads
(e.g. multi-rendition HLS decode from BlobSource). LRU filter only
checked !running; workers with queued slices could be evicted.
Add pendingSlices.length === 0 to the filter.
* fix: export AppendOnlyStreamTarget from index
Missing from the re-export; public docs import it by name.
* fix: join HLS init segment path with root + playlist path
Init path went through _getTarget bare; segments got joined with rootPath + playlist.path. Playlist-relative URI then can't resolve when the playlist lives in a subdirectory.
* Fix targets not being cleaned up, fix paused workers with remaining pending slices, modify doc block, fixed isRoot not being changed on proxied requests
---------
Co-authored-by: Vanilagy <[email protected]>
* Add BufferTarget.onFinalize option for awaitable async action on finalize
The `finalized` event fires synchronously and its return value is ignored,
making it unsuitable for use cases where the muxer should wait (e.g.
uploading the buffer to S3, R2, or other object stores that require a
known Content-Length and therefore can't stream via StreamTarget).
Adds a new `BufferTargetOptions` type with an `onFinalize` callback that
the muxer awaits before resolving. Matches the existing callback pattern
used by `HlsOutputFormatOptions.onSegment`, `onMaster`, etc.
When used with PathedTarget, this provides proper backpressure: the next
segment won't start being produced until the previous one has finished
uploading, keeping memory bounded regardless of video length.
- Adds `BufferTargetOptions` type, exported from the package root
- `BufferTarget` constructor now accepts optional options (backward compatible)
- `_finalize()` awaits `onFinalize` before emitting the `finalized` event
- Adds runtime validation for non-function callbacks
- Updates "Upload to a server" docs in writing-hls.md with S3 pattern
- Documents `onFinalize` in writing-media-files.md BufferTarget section
- Adds tests for callback invocation, async awaiting, backward compat, and validation
* Add ConcurrentRunner, add OutputOptions.onFinalize, adjust docs accordingly, clean up tests
* give me more control baby
* forgot to tell about it
* polish guide and js docs
* vanilagy says remove this, docs will reveal it
---------
Co-authored-by: Vanilagy <[email protected]>
* Add support for reading transparent Matroska and implement alpha side data & decode
* Few fixes
* Implement alpha encoding
* Gracefully handle inability to acquire WebGL context, properly clean up WebGL contexts
* Improve touch device detection
* Test test
* Test test #2
* Test test 3
* Test test 4
* Test test 5
* Test test 6
* Test test 7
* Test test 8
* Test test 9
* Test test 10
* Test test 11
* Test test 12
* Test test 13
* Test test 14
* Test test 15
* Test test 16
* Test test 17
* Test test 18
* Test test 19
* Test test 20
* Fix type errors, improve MetadataTags docs
* Do a bunch of docs work
* Test test?
* "Unexpected only modifier 🤓"
* Add InputVideoTrack.canBeTransparent()
* Some clean-up
* Adjust CI to be less spammy in PRs
* Fix broken license headers
* add a test
* recognize as input format
* scaffold flac demuxer
* implement getting metadata
* Implement mime type
* read all metadata + deduplicate stubs
* Read first packet
* copyright headers
* read the first packet
* Get entire first packet, work on advancing
* iterate over all samples
* testable with bun
* stub out metadata support
* parse descriptive metadata
* All in 1 file
seems more appropriate to the philosophy
* some parameters are not needed anymore all within 1 class
* skip over bytes we are sure are not the syncword
* run prettier
* timestamp is determined based on passed blocks, not maximumBlockSize
* no binary search needed!
* simplifications
* Finish demuxer reading sequentially
* more tests + add a file with a seektable
* don't throw if (this.audioInfo.minimumBlockSize !== this.audioInfo.maximumBlockSize
* Add docs
* Update format compatibility table
* Simplification
* confirm conversion is working
* Finish
* Resolve TODO comment
* Support images (read-only)
* Returning description as Uint8Array
* Cleanup of demuxer
* Misc renames
* Object on same line
* Resolve first batch of comments
* Throw errors on corrupt blocks, correctly use requestSlice()
* Fix description field
* Explain why last frame is a bit shorter
* Add FLAC to README
* Put track backings below demuxer
* convert to methods
* Reorder container checking
* getBlockSize() -> readBlockSize()
* bitStream -> bitstream
* better naming for bytes
* use .skip()
* Don't return blockSize twice in readFlacFrameHeader
* Use enum + switch to distinguish Flac block types
* Use else-if
* Use else-if
* Compressed switch statement
* readCodedNumber
* Update flac-misc.ts
* We don't need the bits variable at all
* reorder functions in flac-demuxer
* Handle gracefully not being able to load another sample
* Update flac-demuxer.ts
* blockingbit null
* use async instead of promise.resolve
* use binary search
* Replace recursion with while loop
* Add mutex to getPacket()
* Load more data not in getPacketAtIndex, but outside
* Apply suggestion from @Vanilagy
Co-authored-by: David P. <[email protected]>
* computeDuration() reads last packet
* Update flac-demuxer.ts
* share vorbis comment reading logic
* reuse vorbis comment writing logic, set vendor always to "Mediabunny"
* flush after writign
* Use FileSlice.tempFromBytes
* assert !== null
* fixing nitpicks
* apply suggestions
* fix ogg
* We are now muxing images
* apply suggestion
* Update src/flac/flac-muxer.ts
Co-authored-by: David P. <[email protected]>
* apply suggestion
* readSampleRate()
* seek outside writeHeader()
* mention vorbis metadata + add to metadatatags comment
* should be able to -> can
* Add test in metadata tags
* Add test for packets being byte identical after remuxing
* compare to null
* no casting to uint8array
* make test pass
* Update flac-muxer.ts
* Call validateAudioChunkMetadata() and validateAndNormalizeTimestamp()
* `onFrame` option
* emit frames using onFrame
* Run prettier over files
* Fix FLAC PICTURE block logic, small other changes
* Update docs
* Remove .only modifier
* fix remuxing and add test
* Don't throw error if parsing fails in header, since hitting a syncword might just be coincidential
* Fix remaining type errors
---------
Co-authored-by: David P. <[email protected]>