NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #4636 most downloaded on pub.dev
A pure Dart cross-platform casting package supporting Chromecast (CASTV2), AirPlay, and DLNA with built-in HTTP proxy for header injection.
Last release 1 months ago
16 Aug 2026
Ships fairly regularly
a new release about every 5 weeks
Nearly every release is documented
notes for 14 of 14 stable releases
Nothing withdrawn
no release was ever pulled
6 months old
14 releases · first in 2026
One column per month.
fix(chromecast): default subtitle honor, stale LOAD corpse attribution, resume track re-assert by @abdelaziz-mahdy in #19
Full Changelog: v0.7.3...v0.7.4
CastMedia.defaultSubtitle names the subtitle track playback starts with (matched by URL against subtitles). Honoured by Chromecast (activeTrackIds on LOAD) and DLNA (picked over subtitles.first)defaultSubtitle now means no subtitle shownIDLE/ERROR broadcast from a session that neither answers the in-flight LOAD's requestId nor matches its session id is now ignored as a stale corpse (and its session deprecated). Observed live: a next-episode LOAD was declared failed 1ms after being sent — the corpse of the failed first attempt — while the receiver went on to play the episode fine, leaving the app convinced the old episode was still playingFull Changelog : v0.7.2...v0.7.3
Full Changelog: v0.7.2...v0.7.3
MediaSource readers may now open asynchronously — an async function satisfies the reader, so sources backed by Android content:// URIs, network handles or a decrypt handshake no longer need a Stream.fromFuture(...) workaround (#12). Existing synchronous readers are unaffected; an async* reader needs a declared return type, which the MediaSource docs showfix: offer AirPlay 1 to receivers that advertise both video versions by @abdelaziz-mahdy in #18
Full Changelog: v0.7.1...v0.7.2
/play returns 404. 0.7.0 sent every AirPlay 2 device down the V2 path and never offered V1, so a device implementing only the older endpoints could not play at all. The retry is gated on the device advertising bit 0 — it is not a return of the blind version probe 0.7.0 removedFull Changelog : v0.7.0...v0.7.1
Full Changelog: v0.7.0...v0.7.1
Documentation only — no code changes.
doc/AIRPLAY.mdfix: report HLS duration and make seeking work on DLNA renderers by @abdelaziz-mahdy in #14
Full Changelog: v0.6.0...v0.7.0
AirPlay 2 and DLNA fixes plus caller-supplied byte sources, driven by testing against a TCL Google TV.
AirPlay selects its protocol version from the advertised feature bits instead of probing /play; devices with no video bit throw UnsupportedFeatureException immediately
AirPlaySession.connect() pairs with every AirPlay 2 receiver, so it can now throw NeedsPairingException where it previously returned a session. If you call connect() on an AirPlay 2 device and do not catch that exception, this release will start throwing at you. The old behaviour was not useful — the session it returned had fallen back to a legacy path those devices reject, so it could not cast anything — but it did not fail either. Handle it by prompting for the on-screen passcode and calling pairSetup(pin), or by catching it and offering Chromecast/DLNA instead:
try {
await session.connect();
} on NeedsPairingException {
// Show the code on the TV, then:
await session.pairSetup(pinTheUserTyped);
await session.connect();
}
Most smart TVs use PIN-less transient pairing and never reach this path; it is devices that demand a passcode which now surface it.
AirPlayMediaController.dispose() returns Future<void>; play() takes startPositionSeconds: instead of startPosition:
ClientException: Connection closed before full header was received when the renderer drops an idle connection — the action is retried once (#9)startPosition). Unverified end to end — no receiver tested accepts a video URL, so nothing past the handshake can be exercised yetMediaSource + MediaProxy.registerSource() + CastMedia.source() — cast bytes the package cannot open itself: Android content:// URIs, Flutter assets, decrypted or in-memory content (#12). The application supplies a range-aware reader; the proxy handles HTTP, byte ranges and seeking. Works on Chromecast, DLNA and AirPlay, since it uses the same route local files already useAirPlayTimingServer, transient pairing, PlaybackInfo.errorHlsParser.totalDuration / extractSegments, MediaProxy.probeHlsDuration / parseTimeSeekRangetool/airplay_probe.dart, tool/airplay_hardware_check.dart, tool/dlna_hardware_check.dart, tool/chromecast_hardware_check.dart — hardware verification scripts/play endpoint, and Apple's own QuickTime fails on it identically — use Chromecastfeat: alt-audio HLS remuxer + Chromecast LOAD diagnostics (0.6.0) by @abdelaziz-mahdy in #10
Full Changelog: v0.5.1...v0.6.0
MediaProxy.registerAltAudioMuxed() — synthetic single-stream HLS master backed by per-segment muxingHlsParser.extractAudioRenditions + audioGroup on extractVariants entriesvideo/mp2t, on by default; opt out via registerMedia(stripDvbTables: false)MediaLoadFailedException from loadMedia() on LOAD_FAILED / IDLE+ERROR / 15s timeout, carrying the receiver-reported reasonrequestId / mediaSessionId filtering against stale responsesChromecastSession.enableReceiverDebugNamespaces (default false) — opt-in CaC + debugoverlay subscribe and verbose receiver logging for debuggingsetSubtitle() activates the correct track (was always trackId=1)Access-Control-Allow-Origin echoes the receiver Origin when the LOAD includes a tracks arrayloading → {buffering, paused, idle} and idle → {buffering, playing, paused}loadMedia returns to idle instead of stuck in loadingContent-Length only forwarded when the body streams through unchanged.ts / .vtt for the Chromecast URL-extension probeimage/* Content-Type on proxied MPEG-TS subresources rewritten to video/mp2tPatch release to reclaim the 10 pub points pana docked on 0.5.0's static-analysis check (40/50 → 50/50, total 160/160 ).
Patch release to reclaim the 10 pub points pana docked on 0.5.0's static-analysis check (40/50 → 50/50, total 160/160).
No API, behavior, or dependency changes — pure lint cleanup under `lib/`.
See #8 for the full diff and CLAUDE.md pre-PR checklist run used to verify.
Full Changelog: v0.5.0...v0.5.1
lib/ that kept the 0.5.0 static-analysis score at 40/50:
curly_braces_in_flow_control_structures in ts_keyframe_scanner.dart and airplay/auth/airplay_auth.dart — single-statement if bodies now wrapped in braces.use_super_parameters on the two CastMessage_* enum constructors — converted to super-parameter syntax.camel_case_types on the hand-written CastMessage_ProtocolVersion / CastMessage_PayloadType bindings in chromecast/proto/cast_channel.dart — suppressed via a file-level // ignore_for_file: camel_case_types, since these identifiers intentionally mirror the names protoc --dart_out would emit for Chromium's cast_channel.proto.protobuf : Upgraded from ^3.1.0 to ^6.0.0 for the latest performance improvements and bug fixes from the protobuf.dart 4.0 → 6.0 releases. Hand-writte
Closes #6.
^3.1.0 to ^6.0.0 for the latest performance improvements and bug fixes from the protobuf.dart 4.0 → 6.0 releases. Hand-written CastMessage bindings use only stable GeneratedMessage / BuilderInfo / PbFieldType APIs, so no code changes were needed — CastMessage also lives under lib/src/ and is not re-exported, so the major bump does not leak into this package's public API.sdk constraint from ^3.0.0 to ^3.7.0 (required by protobuf 4.1.1+). The SDK bump also switches the default formatter to the Dart 3.7 tall style, so the lib/ and test/ tree was reformatted in this release.! non-null assertions in cast_service.dart and airplay/auth/airplay_auth.dart that a newer analyzer (pulled in by the SDK bump) started flagging as warnings.example/: the Image.network errorBuilder signature now uses Dart 3.7 wildcard parameters ((_, _, _)) instead of multiple underscore names.CLAUDE.md with a pre-PR verification checklist that replays every CI step locally and calls out three gotchas that tripped this release (warning-level analyzer exits, formatter style flips on SDK bumps, and flutter analyze being stricter than dart analyze).Full Changelog: v0.4.3...v0.5.0
protobuf dependency from ^3.1.0 to ^6.0.0 for the latest performance improvements and bug fixes (#6). Hand-written CastMessage bindings remain compatible; no API changes.sdk constraint from ^3.0.0 to ^3.7.0 (required by protobuf 4.1.1+).fix: analyzer warnings + bump to 0.4.3 by @abdelaziz-mahdy in #5
Full Changelog: v0.4.2...v0.4.3
dart format to all source filesfeat: local file casting, MediaTransformer refactor, ffmpeg reference by @abdelaziz-mahdy in #1
Full Changelog: v0.2.0...v0.4.2
loadMedia() calls while one is already in progress, preventing multiple LOAD messages from being sent to the deviceDLNA start position: seek now deferred until TV confirms PLAYING state (immediate seek was ignored by TVs still loading)
Access-Control-Allow-Origin required 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:SSresponse.close() after socket detach in synthetic content handlerAdded protocol status table to README with testing coverage and known limitations
sec:CaptionInfoEx not universally supported)CastMedia.useChunkedHls is deprecated and will be removed in a future release. TsHlsMediaTransformer always uses chunked HLS.
DefaultMediaTransformer no longer wraps local TS files in HLS — it
serves them directly via the proxy. Use TsHlsMediaTransformer or
FfmpegMediaTransformer for Chromecast-compatible local TS casting.CastMedia.useChunkedHls is deprecated and will be removed in a future
release. TsHlsMediaTransformer always uses chunked HLS.ChromecastSession now defaults to TsHlsMediaTransformer instead of
DefaultMediaTransformer.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 segmentsFfmpegMediaTransformer reference 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 tradeoffsReplace 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(),
);
AirPlay feature flag detection via mDNS TXT records (AirPlayFeatures class parses features/ft bitmask)
AirPlayFeatures class parses features/ft bitmask)AirPlayMediaController with V1/V2 /play format auto-negotiation (V1 binary plist → V1 text/parameters → V2 with RTSP SETUP)UnsupportedFeatureException thrown immediately when a device lacks video support bits (0 and 49)PlaybackException thrown when all /play format attempts are rejected by the deviceHapSession no longer has play, stop, scrub, or rate methods — use AirPlayMediaController insteaddoc/PROTOCOL_REFERENCES.md with links to AirPlay, Chromecast, and DLNA specsdoc/FUTURE_WORK.md documenting AirPlay screen mirroring and RAOP audio streaming roadmapYour coding agent can read these notes before it upgrades. Set up the MCP server →