Changelog โ
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased] โ
[0.2.2] - 2026-04-26 โ
Added โ
postertimeAttribute: Generate a native-resolution poster from any timestamp without an explicitposterURL. Accepts"10%","5","1:30", or"0:01:30". Uses an isolated thumbnail pipeline (WASM +ThumbnailBindings), respects rotation metadata, and is race-guarded so in-flight generators can't paint stale frames after asrcchange.dispose()Method: Tears down the internal player and resets transient UI (subtitles, timeline, time, title, generated poster) back to the no-source state. Called automatically on everysrcchange so playlist-style flows never leak state between sources. Safe to call when nothing is loaded.playingGetter: Read-only boolean that'strueonly while the player is actively playing โ distinguishes it fromready,loading,seeking, andbufferingstates (precise inverse ofpaused).MoviElement.cleanVideoTitle(filename)Static: Utility exposed for playlist UIs to derive the same cleaned title the player uses internally โ useful for computing the resume localStorage key (movi-resume:<cleanVideoTitle(name)>).- Folder Playlist (web demo app): Sidebar/below-player playlist via File System Access API (with
webkitdirectoryfallback). YouTube-style items with thumbnail, duration, HDR chip, codec/quality/size meta, and watched-progress bar. Lazy thumbnail generation, natural-sort, autoplay-next toggle, drag-and-drop multi-file support.
Changed โ
play()Semantics: Now queues a play intent duringisLoadingand flushes it frominitializePlayer()'s finally block โ matchesHTMLMediaElementbehavior. Previously bailed silently when called during load.- Software Decoder Fallback Per-Source: Choosing "Try software" no longer sticks across
srcchanges. The next video gets a fresh hardware-decode attempt; theswattribute is cleared on dispose. - Encrypted Playback Protocol:
EncryptedHttpSourcerewritten โ block prefetch high-water/low-water tuning, concurrent-stream cap,getPosition()reports the real read cursor, and parent position field is kept in sync so buffer math stays honest. Encrypted-server ported to match the new protocol. - Buffer Tuning: Runtime tuning of prefetch high-water, refill threshold, and block cache cap via the existing
buffersizeattribute. README/docs corrected to clarify the value is in megabytes (not seconds) and applies to both HTTP and encrypted sources. - Production Bundles: Re-enabled terser
drop_consoleanddrop_debuggerso release builds ship without dev-only logging. - Build Stability:
app:releasescript ties build + R2 upload + worker deploy into a single command. Build version cache-bust scoped to the quoted__BUILD_VERSION__literal so unrelated lines aren't rewritten.
Fixed โ
- Post-Seek A/V Sync: Cap the post-seek audio gap at 200ms โ when the first video frame after a seek arrives late (sparse keyframes / slow HEVC+HDR decoders), sync the clock to video time and drop stale audio instead of syncing to the earliest audio packet. Small gaps still prefer audio for continuity.
- Pre-Play Seek Position: Scrubbing the timeline before pressing play no longer resets to 0 โ the first-play poster-seek now reads
clock.getTime()instead of a hardcoded start time. Pipeline is flushed on user seek so prebuffered start audio doesn't briefly play before jumping to the target. - Fully-Cached Buffered Duration: Buffered range now reports the full media duration when the file is fully cached, instead of stopping at the last network read.
- Buffer Indicator Race: Collapsed the seek-race scan sweep that could draw a phantom buffered range mid-seek.
- Encrypted Thumbnails: Share the main source for thumbnail reads instead of opening a parallel session โ cuts redundant token churn. Concurrent stream cap prevents seek-storm thrash. Hardened thumbnail read failures (no more fragile retry/cooldown loop).
- Worker
/proxyEmpty 206: Retry empty 206 responses from upstream before streaming back, so transient origin hiccups don't surface as broken playback. - Worker Probe Failures: Transient probe errors no longer get misreported as
415 Unsupported Media Type. - TMDb Title Parser: Detect TV shows when the episode title trails the
SxxExxcode (e.g.,Show.S05E01.Title).
Security โ
- Worker Referer Allowlist:
/proxyand/eproxyendpoints now gate requests by Referer to block hotlinking from unauthorized origins. - Worker Magic-Byte Validation:
/proxyresponses are validated against expected media magic bytes before being streamed back, mitigating MIME confusion attacks.
[0.2.1] - 2026-04-16 โ
Added โ
- Persistent Preferences:
stableVolume,ambientMode, andhdrtoggles now persist via OPFS alongsidevolume,muted, andplaybackRate. User toggles win over HTML attribute defaults on subsequent loads. - Split-Source Volume Control: Volume button now visible when a separate native audio element is loaded, even if the video file has no muxed audio track.
- Smart Title Extraction: VLC-style filename cleaning strips release tags, codecs, and quality markers from tab titles.
Content-Dispositionfilename used when the server provides one. - Chrome Extension: Local file playback via popup file picker, drag-and-drop onto the player page, and a redesigned popup layout.
Changed โ
- Context Menu: Slide-panel variant now only used on touch devices (
pointer: coarse); narrow desktop windows get the regular hover-driven menu. - Context Menu Scrolling: Max-height clamped to player height with subtle scrollbar styling so tall menus stay accessible on short players.
- Theme Color Cascade:
themecolorattribute now flows to--movi-primary-lightand--movi-primary-darkviacolor-mix, so active menu items and highlights follow the custom theme. titleAttribute: No longer triggers the browser's native tooltip on hover โ title is rendered only by the in-player overlay.- Subtitle/Audio Track Menus: Show language codes alongside track labels for clarity.
Fixed โ
- Short Video Stutter: Prebuffer media before
readysoplay()doesn't immediately stall on short clips. - Background Audio at 50/60 fps: Skip video decode while hidden so audio keeps flowing on high-fps content.
- Narrow Viewport Controls: Buttons, gaps, and center play button tightened on viewports โค 480px to prevent the controls bar from overflowing the player box on iPhone 12 Pro-class widths.
- Empty State Placement: "No Video" placeholder no longer clips into the controls bar on short/narrow players.
- OSD Speed Icon: Correct speed icon shown when playback rate changes via hotkeys/context menu.
[0.2.0] - 2026-04-09 โ
Added โ
- Ambient Mode: Dynamic letterbox glow that samples video colors in real-time. Smooth 60fps color transitions via WebGL clearColor. Toggle with
Gkey or context menu. Works in fullscreen (letterbox) and normal mode (external wrapper).ambientmodeattribute. - Split Source Support: Separate video, audio, and subtitle file URLs via
videosrc,audiosrc,subtitlesrcattributes. - PGS Image Subtitles: Bitmap subtitle decoding with zlib decompression support.
- Network Disconnect Recovery: Intelligent CORS vs transient network failure detection (3-strike threshold). Online-event-aware backoff for instant retry on reconnection. Auto re-seek on recovery. 30s timeout on offline wait.
- Document Picture-in-Picture: Floating video window with play/pause, seek, mute, progress bar, time display, keyboard shortcuts, and back-to-tab button. Portrait video sizing. Rotation save/restore on PiP enter/exit.
- DRM Support:
drmandlicenseurlattributes for HLS streams with Widevine/FairPlay via EME API. - HLS Quality Menu: Duplicate resolutions show bitrate (e.g., "1080p ยท 5000 kbps").
- HLS Nerd Stats: Video codec, resolution, quality, frame rate, bitrate, buffer, HLS level, bandwidth, live latency, frames decoded/dropped.
- VLC-style Shortcuts:
Vsubtitles,Baudio,+/-speed,Lloop,Ustable volume,HHDR,PPiP,Gambient,Aaspect ratio. - Aspect Ratio Controls:
Akey cycles contain/cover/fill/zoom. Sub-menu with icons in context menu and bottom controls. - Stable Volume: DynamicsCompressorNode for loudness normalization. Opt-in via
stablevolumeattribute. - Nerd Stats: Press
Ifor codec, resolution, FPS, decoder type, buffer health, color info, and live network/disk activity graph. - Timeline: Press
Tfor auto-generated thumbnail strip with chapter support. Arrow key navigation, click-to-seek. - Chapter Support: Extract chapters from video metadata. Chapter markers on progress bar, chapter titles in seek tooltip.
- Video Rotation: Press
Rto rotate 90ยฐ. Metadata rotation auto-applied. Disabled during PiP. - Keyboard Shortcuts Panel: Press
?to view all shortcuts. - Resume Playback:
resumeattribute saves position to localStorage with resume/start-over dialog. - Encrypted Playback: AES-256-GCM chunked encryption with HMAC-SHA256 signed requests.
- Background Audio: Video keeps playing audio when tab is in background via Web Worker timer fallback.
- Chrome Extension: Popup with "Paste & Play" and "Play from Computer", context menu on video links, play button overlay on detected URLs.
- Privacy Policy: Published at docs site for Chrome Web Store compliance.
Changed โ
- Buffering state now stops presentation loop so frames accumulate for reliable recovery.
- Buffering exit requires video frames ready (with 3s fallback for async decoder delays).
- Pause during buffering allowed from all UI controls (click, keyboard, buttons, PiP, context menu).
buffering โ endedstate transition allowed for EOF during rebuffer.- Invalid packet size at EOF treated as EOF (not fatal error) for FFmpeg stale buffer data.
- HDR icon changed to text badge style in OSD and context menu (matches bottom controls).
- Extension description rewritten to remove excessive format keywords (Chrome Web Store compliance).
- Console logs dropped in production build.
Fixed โ
- Hardware decoder error recovery with keyframe cache and software fallback.
- Seek and play/pause during buffering state.
- Network disconnect causing permanent CORS misclassification when
navigator.onLinelags. - Stale stream loops from leaked online event listeners during backoff.
- Multiple concurrent fetch loops after network recovery.
- Clock advancing during buffering (presentation loop consuming frames).
- PiP rotation clipping โ rotation reset on PiP enter, restored on close.
- PiP portrait video oversized โ height-limited sizing for portrait aspect ratios.
- Pause-seek loading stuck โ
VideoDecoder.flush()1s timeout with reset+reconfigure fallback. - EOF not triggering โ relaxed condition with 0.5s tolerance.
- PiP canvas restore using
shadowRootdirectly. - PiP frame freeze on tab switch with
isPiPActiveguard. - EncryptedHttpSource network resilience matching HttpSource.
- Nerd stats graph fullscreen positioning and CSS specificity.
[0.1.5] - 2026-02-15 โ
Added โ
- Pitch preservation for playback rate changes
- Pitch preservation support for HLS playback
- MediaSession API integration for background playback and media controls
- HTTPS support for local development environment
Changed โ
- Simplified error messages to be more concise and consistent
- Replaced all hardcoded purple colors with CSS variables (--movi-primary) for full theme customization
- Enhanced center play button with theme color by default
- Updated loading spinner with responsive sizing and theme-aware colors
Fixed โ
- Improved playback stability with enhanced error handling and timeout management
- Resolved audio-video sync issues with hardware decoding
- Distinguished 403/401/404 errors from CORS errors for better error reporting
- CORS errors now propagate immediately instead of waiting for timeout
- Title bar z-index now properly positioned below control menus in mobile view
- Center play button backdrop blur now enabled on mobile/touch devices
- Controls no longer auto-hide when menus are open on mobile
[0.1.4] - 2026-02-11 โ
Fixed โ
- Resolved video stalling during playback and improved A/V sync
- Playback speed changes now take immediate effect on audio
- Auto-unmute when volume slider is moved while muted
- Mute button now correctly toggles audio muting
Previous Versions โ
See git commit history for changes in versions prior to 0.1.4.