Fix local video add/drag and large-file cast crash (0.29.7) - #412
Conversation
Video files were silently dropped at several UI surfaces because each has its own handler and most excluded video: - Modern and Classic main-window drops passed includeVideo: false, so dropping a video onto the player did nothing (no player launched). Both now accept video; the Track routes to the video player via mediaType. - The library-window drop only appended audio; video files are now routed to MediaLibrary.addVideoFiles and reveal the Movies tab. - "Add Video Files..." added the movie but never switched to the Movies tab, so the import looked like a no-op. It now reveals Movies, and its file picker no longer greys out .mkv/.avi/.webm/.ts. - Track(url:) detected video only via AVAsset track probing, which returns empty for containers AVFoundation can't parse (.mkv/.avi/.webm) — the very formats VLCKit was adopted for — so they were misclassified as audio and dropped by the audio engine. Added an extension fallback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LocalMediaServer served registered local files by reading the whole file into memory: Data(contentsOf:) for full-file GETs, and readData(ofLength: Int(length)) for range requests — where a cast device opens playback with "Range: bytes=0-" (the entire file). Casting a multi-gigabyte movie exhausted memory and the OS killed the process with no crash log, so the app appeared to vanish the instant the cast started. Small files fit in RAM, so only large media was affected. Both handlers now stream through a FileByteStream (an AsyncBufferedSequence of UInt8 backed by a FileHandle, 256 KB chunks) wrapped in HTTPBodySequence(from:count:), mirroring the existing URLSessionByteStream proxy path. Content-Length/Content-Range are unchanged, so seeking still works; memory stays flat regardless of file size. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bump version to 0.29.7 and add changelog entries for the local video add/drag routing fixes and the large-file cast OOM fix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 38 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughLocal video detection and import flows now support additional extensions across player and library windows. Local casting streams full-file and range responses in bounded chunks. Release metadata and documentation now describe version 0.29.7 and these behaviors. ChangesLocal media handling
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant CastingClient
participant LocalMediaServer
participant FileByteStream
CastingClient->>LocalMediaServer: Request full file or byte range
LocalMediaServer->>FileByteStream: Read bounded chunks
FileByteStream-->>LocalMediaServer: Return file bytes
LocalMediaServer-->>CastingClient: Stream response with range metadata
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Sources/NullPlayer/Casting/LocalMediaServer.swift`:
- Around line 208-227: Update FileByteStream initialization and seekIfNeeded to
propagate file-open and seek failures instead of suppressing them with try? or
optional handles. Ensure handleMediaRequest validates successful opening and
seeking before returning the response, and make nextBuffer throw on subsequent
read or seek failures rather than returning nil, while preserving normal EOF
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 8e6fb96e-5e78-47b0-bd63-2fcb2d897d57
📒 Files selected for processing (9)
CHANGELOG.mdSources/NullPlayer/Casting/LocalMediaServer.swiftSources/NullPlayer/Data/Models/Track.swiftSources/NullPlayer/Resources/Info.plistSources/NullPlayer/Windows/MainWindow/MainWindowView.swiftSources/NullPlayer/Windows/ModernLibraryBrowser/ModernLibraryBrowserView.swiftSources/NullPlayer/Windows/ModernMainWindow/ModernMainWindowView.swiftskills/chromecast-casting/SKILL.mdskills/local-library/SKILL.md
Summary
Fixes several local-video handling gaps and a crash when casting large media. Ships as 0.29.7.
Local video add / drag / drop
Each drop/add surface has its own handler, and most silently excluded video:
ModernMainWindowView) and Classic (MainWindowView) skins have separate handlers; both passedincludeVideo: false, so dropping a video did nothing. Now accepted and routed to the video player.MediaLibrary.addVideoFilesand reveals the Movies tab..mkv/.avi/.webm/.ts.Track(url:)detection — relied on AVFoundation track probing, which returns empty for.mkv/.avi/.webm(the formats VLCKit was adopted for), misclassifying them as audio. Added an extension fallback.Large-file cast crash (OOM)
LocalMediaServerserved files by reading the whole file into memory (Data(contentsOf:), andreadData(ofLength:)for thebytes=0-full-file range a Chromecast requests). Casting a multi-GB movie exhausted memory and the OS killed the process with no crash log. Both handlers now stream via aFileByteStream(256 KB chunks) throughHTTPBodySequence(from:count:); memory stays flat and seeking still works.Testing
swift buildclean.Docs
CHANGELOG.md— 0.29.7 entries.skills/local-library/SKILL.md— per-surface video drop/add routing +Trackextension fallback.skills/chromecast-casting/SKILL.md—LocalMediaServermust stream, never buffer.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Documentation