- Introduced `readableStreamIterator` to convert ReadableStream into async iterable.
- Updated `LosslessAPI` to utilize `readableStreamIterator` for handling response body.
- Modified `ZipNeutralinoWriter` to use `readableStreamIterator` for reading chunks.
- #322: Fullscreen overlay padding and main-view scrollable so volume stays above taskbar when Up next is shown
- #313: Settings tab content constrained on small displays with max-width, min-width, overflow-x
- #278: HEAD request before GET for download to get Content-Length for progress bar; resolveDownloadTotalBytes in downloadProgressUtils.js
- Improved progress tracking in FFmpeg worker by extracting total duration and current time from logs.
- Updated downloadTrackBlob function to use console logging for progress updates.
- Enhanced error handling and progress reporting during audio encoding.
taglib supports multiple media formats beyond what was previously supported, this would enable transcoding to other formats without needing to write additional metadata libraries.
Inline fixes:
- Remove TDRC frame from ID3 writer (ID3v2.3 uses TYER only, not TDRC)
- Add try/finally cleanup in worker to prevent VFS leaks on errors
- Fix Blob creation to use Uint8Array directly (avoid extra bytes)
- Replace loadFFmpeg race guard with promise singleton pattern
- Add -map_metadata -1 to strip source metadata (prevent duplicate ID3)
Error handling improvements:
- Create MP3EncodingError class with code property for reliable detection
- Update api.js to use instanceof check instead of string matching
- Pass AbortSignal to encodeToMp3 for proper cancellation support
- Remove error re-wrapping in mp3-encoder.js (preserve original errors)
Technical details:
- Promise singleton ensures FFmpeg loads once even with concurrent calls
- AbortSignal listener properly cleaned up on success/error/abort
- Virtual FS cleanup in finally block prevents file leaks
- MP3EncodingError.code = 'MP3_ENCODING_FAILED' for robust detection
Implements MP3 320kbps download functionality using ffmpeg.wasm for
industry-standard encoding with libmp3lame.
Features:
- New MP3_320 quality option in download settings UI
- ID3v2.3 metadata writing (title, artist, album, cover art, ISRC, etc.)
- Non-blocking encoding via Web Worker to keep UI responsive
- Proper UTF-16 with BOM text encoding for international characters
- Album artist fallback to track artist (mirrors FLAC/M4A behavior)
- Automatic format detection for downloaded audio
- Year validation to prevent writing NaN to ID3 tags
Implementation:
- mp3-encoder.js: Main encoder module with worker orchestration
- mp3-encoder.worker.js: FFmpeg Web Worker for async encoding
- id3-writer.js: ID3v2.3 tag writer with synchsafe size encoding
- Updates to api.js, metadata.js, utils.js for MP3 support
- Vite config excludes @ffmpeg packages from dep optimization
Technical details:
- Uses @ffmpeg/ffmpeg (libmp3lame 320kbps CBR, 44.1kHz)
- FFmpeg binary lazy-loaded from CDN (~25MB, cached)
- Encoding runs in separate thread (non-blocking UI)
- Proper error handling with distinct encoding vs network errors
- Memory-efficient: transfers ArrayBuffer with zero-copy
Dependencies:
- @ffmpeg/ffmpeg ^0.12.10
- @ffmpeg/util ^0.12.1
- Removed: package-lock.json (project uses bun.lock)
Closes maintainer request to use ffmpeg.wasm instead of lamejs.