dart_cast 0.5.1
dart_cast: ^0.5.1 copied to clipboard
A pure Dart cross-platform casting package supporting Chromecast (CASTV2), AirPlay, and DLNA with built-in HTTP proxy for header injection.
0.5.1 #
Fixed #
- Pub points (static analysis): Resolved the six pana lints under
lib/that kept the 0.5.0 static-analysis score at 40/50:curly_braces_in_flow_control_structuresints_keyframe_scanner.dartandairplay/auth/airplay_auth.dart— single-statementifbodies now wrapped in braces.use_super_parameterson the twoCastMessage_*enum constructors — converted to super-parameter syntax.camel_case_typeson the hand-writtenCastMessage_ProtocolVersion/CastMessage_PayloadTypebindings inchromecast/proto/cast_channel.dart— suppressed via a file-level// ignore_for_file: camel_case_types, since these identifiers intentionally mirror the namesprotoc --dart_outwould emit for Chromium'scast_channel.proto.
0.5.0 #
Changed #
- protobuf: Upgraded
protobufdependency from^3.1.0to^6.0.0for the latest performance improvements and bug fixes (#6). Hand-written CastMessage bindings remain compatible; no API changes. - Minimum Dart SDK: Bumped
sdkconstraint from^3.0.0to^3.7.0(required byprotobuf4.1.1+).
0.4.3 #
Fixed #
- Analyzer warnings: Resolved pre-existing unused variable warnings in test files
- Code formatting: Applied
dart formatto all source files
0.4.2 #
Fixed #
- Proxy IP selection: MediaProxy now picks the local interface on the same subnet as the target cast device, fixing casting failures on Android where the proxy would bind to a non-WiFi address unreachable by the cast device
- Concurrent loadMedia guard: All protocol sessions (Chromecast, AirPlay, DLNA) now ignore duplicate
loadMedia()calls while one is already in progress, preventing multiple LOAD messages from being sent to the device - Socket disconnect detection: Chromecast session now handles message stream errors and unexpected closures, transitioning to disconnected state so the app can react (previously the session stayed "connected" after a network drop)
0.4.1 #
Fixed #
- DLNA start position: seek now deferred until TV confirms PLAYING state (immediate seek was ignored by TVs still loading)
- Chromecast subtitles for local files: subtitle files now served via HTTP/1.1 with CORS headers (HTTP/1.0 path lacked
Access-Control-Allow-Originrequired by Shaka Player) Http10FileServer: returns 416 Range Not Satisfiable for invalid/out-of-bounds rangesSubtitleConverter.vttToSrt(): uses targeted regex for timestamp dots (no longer corrupts non-timestamp content), expands 2-component MM:SS timestamps to HH:MM:SS- Removed stray
response.close()after socket detach in synthetic content handler
New #
- Updated example app with optimistic slider state, keyboard shortcuts, mute toggle, and responsive layout
- Added protocol feature indicators in example device picker
- Updated README with "What Works Where" feature matrix, protocol notes, and DLNA local files guide
0.4.0 #
Breaking #
- DLNA file serving now uses HTTP/1.0 via raw sockets instead of Dart's HttpServer response. This fixes playback on TCL Google TV and other renderers that reject HTTP/1.1.
- Removed DLNA-specific HTTP headers (
transferMode.dlna.org,contentFeatures.dlna.org,Connection: close) from file responses — these caused some DLNA renderers to reject content. - Cleared Dart's default security headers (
x-frame-options,x-xss-protection,x-content-type-options) from the proxy server.
New #
Http10FileServer— reusable HTTP/1.0 file server class for DLNA compatibilityCastMediaType.mkv— MKV container support for casting with embedded subtitlesSubtitleConverter.vttToSrt()— WebVTT to SRT conversionSubtitleConverter.toAss()— VTT/SRT to ASS conversion with customizable styling (font, outline, shadow, margins)MediaProxy.registerSubtitleVariants()— registers both SRT and VTT subtitle variants for maximum TV compatibility- DLNA subtitle variants: DIDL-Lite now includes both SRT and VTT subtitle URLs with proper format/type attributes
- DLNA seek instantly updates position without waiting for next polling cycle
- MKV content type detection and proxy URL extension support
Fixed #
- DLNA playback failing on TCL Google TV and similar renderers that reject HTTP/1.1 responses
- DLNA flags mismatch between DIDL-Lite protocolInfo (
21500000) and HTTP headers (01700000) — now aligned to01700000matching VLC and MiniDLNA - Missing
DLNA.ORG_PNprofile name in protocolInfo (AVC_MP4_HP_HD_AACfor MP4,MPEG_TS_HD_NA_ISOfor TS) - DLNA seeking not working — Range responses now correctly return 206 with Content-Range
- Subtitle file proxy URLs missing file extensions (
.vtt,.srt) — some TVs need extensions to recognize subtitle files - Synthetic content (subtitle playlists, converted subtitles) now served via HTTP/1.0 for DLNA compatibility
0.3.1 #
- Added protocol status table to README with testing coverage and known limitations
- Documented DLNA MP4 playback issues (TV-dependent, some reject proxy-served MP4)
- Documented DLNA subtitle limitations (
sec:CaptionInfoExnot universally supported) - Documented AirPlay video casting limitations (404 on some Google TV devices)
- Recommended Chromecast as the primary tested protocol for local file casting
0.3.0 #
Breaking changes #
DefaultMediaTransformerno longer wraps local TS files in HLS — it serves them directly via the proxy. UseTsHlsMediaTransformerorFfmpegMediaTransformerfor Chromecast-compatible local TS casting.CastMedia.useChunkedHlsis deprecated and will be removed in a future release.TsHlsMediaTransformeralways uses chunked HLS.ChromecastSessionnow defaults toTsHlsMediaTransformerinstead ofDefaultMediaTransformer.
New #
TsHlsMediaTransformer— wraps local TS files in keyframe-aligned HLS playlists for Chromecast compatibilityMediaProxy.setPatPmt()/MediaProxy.setFirstPts()— enable correct PAT/PMT prepending and PTS offset for virtual HLS segmentsFfmpegMediaTransformerreference implementation in example app — remuxes TS→MP4 via ffmpeg with progress callbacks and mobile platform supportdoc/LOCAL_FILE_CASTING.md— comprehensive guide covering remux, HLS wrapping, and transcode approaches with tradeoffs
Migration guide #
Replace direct DefaultMediaTransformer usage for local TS files:
// Before (0.2.x) — DefaultMediaTransformer handled local TS→HLS internally
final session = await device.connect();
// After (0.3.0) — choose your transformer explicitly
// Option A: FFmpeg remux (recommended)
final session = await device.connect(
mediaTransformer: FfmpegMediaTransformer(),
);
// Option B: Built-in HLS wrapping (no external tools)
final session = await device.connect(
mediaTransformer: TsHlsMediaTransformer(),
);
0.2.1 #
Local file casting #
- Local file support with
CastMedia.file()constructor MediaTransformerinterface for extensible media format preparationTsKeyframeScannerfor keyframe-aligned HLS segment boundaries- Virtual segment URLs for Chromecast compatibility (replaces EXT-X-BYTERANGE)
useChunkedHlsflag for chunked vs single-segment HLS- Local subtitle support with automatic SRT-to-VTT conversion
Chromecast fixes #
- Fixed local file casting — HLS playlists and file routes were destroyed by cleanup before the device could fetch them
- CORS preflight (OPTIONS) handler for HLS segment requests
- RFC 8216-compliant TARGETDURATION calculation
- Consistent
application/x-mpegURLcontent type across all HLS responses - File extension on proxy URLs for HLS player format detection
- Volume updates via RECEIVER_STATUS instead of optimistic update
DLNA improvements #
- Duration metadata via DIDL-Lite
<res duration="HH:MM:SS">attribute - DLNA-specific HTTP headers (
transferMode.dlna.org,DLNA.ORG_OP=01flags) - Serve local TS files directly (not piped through HLS)
Other #
- Retry mDNS queries 3 times for slow-responding devices
- Comprehensive logging for all discovery providers and sessions
- Subtitle proxy for Chromecast (CORS + SRT conversion)
- Log viewer and custom media input in example app
0.2.0 #
- AirPlay feature flag detection via mDNS TXT records (
AirPlayFeaturesclass parsesfeatures/ftbitmask) AirPlayMediaControllerwith V1/V2/playformat auto-negotiation (V1 binary plist → V1 text/parameters → V2 with RTSP SETUP)UnsupportedFeatureExceptionthrown immediately when a device lacks video support bits (0 and 49)PlaybackExceptionthrown when all/playformat attempts are rejected by the device- Breaking:
HapSessionno longer hasplay,stop,scrub, orratemethods — useAirPlayMediaControllerinstead - Added
docs/PROTOCOL_REFERENCES.mdwith links to AirPlay, Chromecast, and DLNA specs - Added
docs/FUTURE_WORK.mddocumenting AirPlay screen mirroring and RAOP audio streaming roadmap
0.1.0 #
- Initial release
- Chromecast (CASTV2) protocol support with default media receiver
- AirPlay 1 video casting support
- DLNA/UPnP protocol support with AVTransport and RenderingControl
- Built-in HTTP proxy server for custom header injection
- HLS m3u8 playlist URL rewriting through proxy
- Local file serving for downloaded content
- Subtitle support across all protocols (WebVTT, SRT)
- Cross-platform: Android, iOS, macOS, Windows, Linux
- Pluggable device discovery (default: multicast_dns, injectable: bonsoir)
- 366+ tests with mock servers for each protocol
- Flutter example app with device picker and remote control