video_player_watchos
The watchOS implementation of video_player.
Playback runs on AVFoundation (AVPlayer) over dart:ffi; rendering is a
native platform view — the plugin ships a SwiftUI VideoPlayer (AVKit)
surface that the app runner composites under the Flutter frame, so Flutter
content (controls, progress overlays) draws over the video and gestures stay
in Dart, matching upstream's texture semantics. VideoEvents are derived by
polling a natively cached state snapshot.
Requires a flutter-watchos with platform-view support and
flutter_watchos≥ 0.1.0-beta.9. With flutter-watchos 0.1.0-beta.12 and an olderflutter_watchos, playback works but the video area stays black.
Usage
This is a federated plugin implementation. Apps that already depend on
video_player and target watchOS only need to add this package alongside it:
dependencies:
video_player: ^<latest>
video_player_watchos: ^0.0.1
The plugin registers automatically via Flutter's federated registry — no explicit imports required from app code.
Behaviour on watchOS
| Feature | watchOS |
|---|---|
| Network / file / asset sources | supported (AVPlayer; HLS included) |
| Play, pause, seek, position, duration | supported |
| Volume, playback speed, looping | supported |
VideoPlayer widget rendering |
supported (native AVKit surface as a platform view; Flutter content stacked over it draws on top) |
| Buffering / play-state / completed events | supported (poll-derived) |
setMixWithOthers |
supported (AVAudioSession) |
| Content URIs | not supported (Android-only concept) |
Audio track selection (getAudioTracks / selectAudioTrack) |
supported via AVMediaCharacteristicAudible selection groups — empty for regular MP4s, populated for HLS streams (same as the upstream Apple impl) |
| Subtitles/captions rendering | as upstream: ClosedCaptionFile is Dart-side and works; embedded-track selection is not implemented |
Because the video surface is a native view composited by the watch host rather than drawn into the Flutter scene, widgets that rely on snapshotting the scene (e.g. screenshot-based golden tests) do not capture the video pixels. With flutter-watchos 0.1.0-beta.12 and later the view follows the layer tree (ancestor clips, opacity and transforms apply); with older releases its rect is axis-aligned and it sits in a transparent hole under the Flutter frame.
Paused playback shows AVKit's controls
While the video is paused, watchOS draws its own playback chrome over the video surface — a Done button, the remaining time, a play glyph and a scrubber — even when your app drives playback entirely from Dart. This is a platform limitation, not a plugin choice, and there is currently no way to turn it off:
- SwiftUI's
VideoPlayeris the only video surface watchOS offers. watchOS AVKit exports noAVPlayerViewController(it has no Objective-C classes at all), andAVPlayerLayer,AVPlayerItemVideoOutput,AVAssetImageGeneratorandAVAssetReaderare allAPI_UNAVAILABLE(watchos)— so there is no alternative renderer and no way to obtain decoded frames to draw the video yourself. VideoPlayerexposes no controls-hiding modifier on watchOS, and the chrome follows the player'stimeControlStatus, so.disabled(true)and.allowsHitTesting(false)do not suppress it (verified on-device-class simulator).
The chrome auto-hides again as soon as playback resumes, so it only affects the paused state.
Simulator note: simulators play video without sound routing peculiarities; on a physical Apple Watch, audio follows the system's audio route (Bluetooth headphones or the built-in speaker, per watchOS rules).
Status
| Platform | Implemented |
|---|---|
Apple Watch (watchos) |
yes |
Watch simulator (watchsimulator) |
yes |
Example on the watch screen
The package ships the upstream example app and its official integration
tests verbatim. The upstream UI is phone-designed (nested tab bars), so
the example's runner opts into the flutter-watchos content scale
(watchos/Runner/Info.plist):
<key>FlutterWatchOSContentScale</key>
<real>0.6</real>
This lays the app out in a proportionally larger logical space rendered smaller — same layout, smaller components — without touching the example's Dart code.
License
The FlutterWatch Authors under a BSD-3-Clause license. See LICENSE for the full text.