The complete, production-grade video player for Flutter.
One unified controller. Native performance. Zero bloated binaries.
Documentation • Live Demo • Migrating from video_player • Migrating from chewie • Migrating from media_kit • Example App
Stop stitching video_player, separate UI packages, abandoned caching plugins, and custom DRM code together. Better Player packs the full video stack into a single, cohesive engine.
| Feature | Better Player | video_player + chewie | media_kit |
|---|---|---|---|
| App Size Overhead | ~1-2 MB (Native OS engines) | ~1-2 MB | +30MB to 50MB (Bundled mpv binaries) |
| Out-of-the-box UI | Built-in & customizable | Chewie required | Built-in |
| HLS / DASH | Full native support | Basic | Native |
| DRM (Widevine / FairPlay) | Native support | None | None |
| Smart Caching | Built-in offline cache | None (3rd party needed) | None |
| Subtitles & Closed Captions | SRT, WebVTT, TTML, CEA-608 / CEA-708 | SRT only | Advanced |
| Picture in Picture (PiP) | Built-in | None | Platform-dependent |
| Playlists | Built-in | None | Built-in |
| VAST / VMAP Ads | Client-side ad engine (VAST 2.0-4.x, VMAP) | None | None |
| Telemetry & QoE | Real-time video metrics, offline retention & cloud export | None | None |
| Video Feeds & Pooling | Built-in (BetterPlayerFeed, BetterPlayerPool) |
None | None |
![]() Mobile Overview |
![]() Native Picture-in-Picture (PiP) |
![]() Web & Desktop Overview |
![]() Touch & Fullscreen Controls |
![]() Adaptive HLS Quality & Track Switching |
![]() Styled Subtitles (WebVTT, TTML, SRT) |
flutter pub add better_playerPlay a network video with full controls in three lines:
import 'package:better_player/better_player.dart';
AspectRatio(
aspectRatio: 16 / 9,
child: BetterPlayer.network(
"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
),
)Configure caching, custom headers, or DRM with a single controller:
final controller = BetterPlayerController(
const PlayerConfiguration(
aspectRatio: 16 / 9,
autoPlay: true,
),
betterPlayerDataSource: PlayerDataSource(
DataSourceType.network,
"https://example.com/stream.m3u8",
// Cache video locally for instant playback:
cacheConfiguration: const CacheConfiguration(useCache: true),
// Or protect content with DRM:
drmConfiguration: DrmConfiguration(
drmType: DrmType.widevine,
licenseUrl: "https://license.example.com",
),
),
);
BetterPlayer(controller: controller);Better Player uses a federated architecture. Each platform runs on its native, hardware-accelerated media engine:
Switching from another package? Follow the step-by-step migration guides:
- Migrating from video_player: Replace
VideoPlayerControllerand remove separate UI packages. - Migrating from chewie: Consolidate your player and controls into a single controller.
- Migrating from media_kit: Reclaim 30-50 MB of mobile app size and switch to native OS media engines.
Better Player supports Dart package skills so tools like Cursor, Claude Code, Gemini, and Copilot understand the API out of the box:
dart run skills@ get -p better_player- Official Documentation: Full guides for caching, DRM, subtitles, VAST ads, and playlists.
- Example Application: Complete working samples covering every feature.
- API Reference: Generated Dart doc reference.
Found a bug or missing a feature? Open an issue or submit a pull request.
Need a custom video source adapter, bespoke DRM implementation, or tailored UI controls? I am available for consulting.






