feat: hls-stream: Enable extension to download live streams in HLS protocol#25
Merged
jvillegasd merged 16 commits intomainfrom Feb 22, 2026
Merged
feat: hls-stream: Enable extension to download live streams in HLS protocol#25jvillegasd merged 16 commits intomainfrom
jvillegasd merged 16 commits intomainfrom
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a REC button for HLS/M3U8 video cards that starts a live recording session. The recording handler polls the manifest every 3 s, collects new segments into IndexedDB, and merges them via FFmpeg when the user clicks Stop (or when #EXT-X-ENDLIST is detected). Popup shows a red shimmer bar and segment count during recording. - Add RECORDING stage to DownloadStage and segmentsCollected to DownloadProgress - Add START_RECORDING / STOP_RECORDING message types - New HlsRecordingHandler with polling loop, concurrent segment download, and FFmpeg handoff - Service worker handles START_RECORDING / STOP_RECORDING messages - RECORDING stage is non-cancellable via standard cancel path - Popup: red shimmer progress bar, REC badge, REC/Stop buttons Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- crypto-utils: cast Uint8Array iv to BufferSource to satisfy TS5 strict generic ArrayBufferView<ArrayBuffer> requirement in SubtleCrypto.decrypt - options: cast getElementById result through unknown before SVGElement to satisfy non-overlapping type assertion check Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds isLive detection during manifest analysis so the REC button is not shown on regular VOD streams. - Add isLive? to VideoMetadata - m3u8 (standalone media playlist): live when #EXT-X-ENDLIST is absent - hls (master playlist): fetch first variant at detection time and check for #EXT-X-ENDLIST; defaults to false (VOD) if the fetch fails - Popup gates REC button on video.isLive === true Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allows users to stop an in-progress HLS or M3U8 download mid-way and still receive a valid (shorter) MP4 from the segments already downloaded. - Add STOP_AND_SAVE_DOWNLOAD message type - Add shouldSaveOnCancel option to HlsDownloadHandler and M3u8DownloadHandler; on CancellationError, compute effective video/audio lengths from stored chunk count, then mux and save the partial file via the existing FFmpeg path - Wire shouldSaveOnCancel through DownloadManager options - Service worker: track URLs in savePartialDownloads Set, handle STOP_AND_SAVE_DOWNLOAD by marking the set and aborting the controller, clean up in cleanupDownloadResources - Popup: add .btn-stop-save CSS and a "Stop & Save" button in the DOWNLOADING progress bar for HLS/M3U8 videos Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
URL.revokeObjectURL called from the service worker had no effect on blob URLs created in the offscreen document — they are separate JS contexts with separate blob URL registries, so the full MP4 blob was never freed. Add a REVOKE_BLOB_URL message type. After Chrome finishes saving the file (or on error), handlers send this message to the offscreen document, which calls URL.revokeObjectURL in the same context that created the blob. Applies to HlsDownloadHandler, M3u8DownloadHandler, and HlsRecordingHandler. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Object.setPrototypeOf(this, MediaBridgeError.prototype) in the base error class broke prototype chains for all subclasses, causing `instanceof CancellationError` to always return false. The partial save code path was never reached. Fixed by using new.target.prototype. Also allow progress updates through during partial save — the onProgress callback was dropping MERGING/SAVING/COMPLETED state transitions because the abort signal was already set. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ards The REC button had class "video-btn btn-rec", causing the regular download handler (.video-btn selector) to also fire — pre-empting the recording handler. Removed video-btn class from REC, stop-rec, and stop-save buttons so only their specific handlers fire. Also deduplicate HLS detection by origin+pathname to prevent duplicate video cards when the player re-fetches playlists with different query params (auth tokens, timestamps). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Show recording progress bar, REC badge, and Stop button in Downloads tab (matching the Videos tab card) - Hide Download/Redownload button for live streams, keep Select Quality and REC - Add "Live Stream Detected" banner in Manifest tab with Record button that routes to START_RECORDING - Send tabTitle/website in REC payload for proper filename generation - Persist FAILED state to IndexedDB when recording errors occur Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…est tab Pass the selected variant URL instead of the master playlist URL when starting a recording from the Manifest tab, so the recording handler uses the chosen quality instead of always picking the highest bitrate. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…of every render Move sorting from renderDownloads() (called on every progress event, poll, and focus) to loadDownloadStates() using createdAt, preventing cards from jumping around during active downloads. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Check HTTP status codes in fetchResource to reject non-2xx responses instead of silently storing error pages as video chunks - Propagate actual error messages through fetchWithRetry instead of generic "Fetch error" - Reset FFmpeg WASM instance after failures to prevent corrupted state from breaking subsequent downloads - Use downloadId for FFmpeg temp filenames to avoid collisions between concurrent downloads - Force .mp4 extension for HLS/M3U8 downloads since FFmpeg always outputs MP4 - Truncate long filenames at word boundaries instead of mid-word - Add chunk concatenation logging for diagnosing download issues Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… errors Recording downloads use full URLs as their downloadId, which contain characters (: / ? & =) invalid for filesystem paths in FFmpeg's MEMFS. Also replace inline onerror handlers with addEventListener to comply with extension CSP. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nt ID generation Recording downloads previously used raw URLs as IDs, causing FFmpeg path failures. Now all download IDs are generated via a single shared function that produces filesystem-safe IDs, removing the need for the sanitizeForFilename workaround. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…LS 404s Browsers silently strip Origin and Referer from fetch() calls since they are forbidden headers. CDNs like phncdn.com require these headers, causing segment downloads to fail with 404. Use chrome.declarativeNetRequest dynamic rules to inject headers at the network layer instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…eferences Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request introduces several improvements and fixes to HLS/M3U8 video detection and download management, with a focus on deduplication, live stream detection, partial download handling, and codebase maintainability. The changes enhance reliability when detecting streams (especially live and variant playlists), allow saving partial downloads on cancellation, and improve header injection and chunk management for downloads.
HLS/M3U8 Detection Improvements:
src/core/detection/hls/hls-detection-handler.ts) [1] [2] [3] [4]#EXT-X-ENDLIST.src/core/detection/hls/hls-detection-handler.ts) [1] [2] [3] [4] [5]Download Management Enhancements:
shouldSaveOnCancelcallback passed throughDownloadManagerand into download handlers. (src/core/downloader/download-manager.ts,src/core/downloader/hls/hls-download-handler.ts) [1] [2] [3] [4] [5]getChunkCountfor more robust handling, and improved header injection by importingaddHeaderRulesandremoveHeaderRulesfor network requests. (src/core/downloader/hls/hls-download-handler.ts) [1] [2]Refactoring and Maintainability:
generateDownloadIdutility to a shared location and updated its usage inDownloadManager. (src/core/downloader/download-manager.ts) [1] [2] [3]pageUrlfrom video metadata to download handlers for improved context. (src/core/downloader/download-manager.ts) [1] [2]Documentation:
I will start using Claude here, yay!
CLAUDE.mdfile describing the architecture, build commands, component interactions, and advanced features of the Chrome extension, serving as a guide for contributors and code assistants. (CLAUDE.md)