video_view is a lightweight media player with subtitle rendering1 and audio track switching support, leveraging system or app-level components for seamless playback. For API documentation, please visit here.
- Complete platform coverage: Android, iOS, macOS, Windows, Web, Linux.
- Internal subtitle rendering, audio track switching, max bitrate/resolution limits.
- Fine-grained status notification with reentrancy prevention.
- Small, widget-first API: drop-in
VideoView(source: ...)to start.
NOTE: video_view requires Flutter 3.32 or higher.
You may try the online demo, or run the demo app locally by cloning this repository:
git clone -c core.symlinks=true https://github.com/xxoo/flutter_video_view.git
cd flutter_video_view/example
flutter pub getFor basic usage, just run:
flutter runFor advanced usage, please run:
flutter run lib/main_advanced.dart- Add dependency in your project by running:
flutter pub add video_view- Reference
video_viewin your Dart code:
import 'package:video_view/video_view.dart';- If your project has web support, you may also need to initialize the web entry point by running the following command after installing or updating this package:
dart run video_view:webinitWithout controller:
import 'package:flutter/widgets.dart';
import 'package:video_view/video_view.dart';
void main() => runApp(VideoView(
source: 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
autoPlay: true,
looping: true,
));Custom controller:
import 'package:flutter/material.dart';
import 'package:video_view/video_view.dart';
void main() => runApp(MaterialApp(builder: (_, _) => const MyApp()));
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _player = VideoController();
@override
initState() {
super.initState();
_player.open(
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
);
_player.playbackState.addListener(() => setState(() {}));
}
@override
dispose() {
_player.dispose();
super.dispose();
}
@override
build(_) => Stack(
alignment: Alignment.center,
children: [
VideoView(controller: _player),
IconButton(
iconSize: 64,
icon: const Icon(Icons.play_arrow),
isSelected:
_player.playbackState.value == VideoControllerPlaybackState.playing,
selectedIcon: const Icon(Icons.pause),
onPressed: () =>
_player.playbackState.value == VideoControllerPlaybackState.playing
? _player.pause()
: _player.play(),
),
],
);
}| Platform | Version | Backend |
|---|---|---|
| Android | 6+ | ExoPlayer |
| iOS | 15+ | AVPlayer |
| macOS | 12+ | AVPlayer |
| Windows | 10+ | MediaPlayer2 |
| Linux | N/A | mpv3 |
| Web | Chrome 84+ / Safari 15+ / Firefox 90+ | <video>, ShakaPlayer4 |
For user who only cares about Android and iOS, the following formats are supported without condition:
| Type | Formats |
|---|---|
| Video Codec | h.264, h.265 |
| Audio Codec | aac, mp3 |
| Container Format | mp4, ts |
| Subtitle Format | WebVTT, CEA-608/708 |
| Stream Protocol | HLS, LL-HLS |
| URL Scheme | http(s), file, asset |
A more complete list with conditions:
| Type | Formats |
|---|---|
| Video Codec | h.264, h.2655, av16 |
| Audio Codec | aac, mp3 |
| Container Format | mp4, ts, webm6 |
| Subtitle Format | WebVTT7, CEA-608/708 |
| Stream Protocol | HLS, LL-HLS, DASH8, MSS8 |
| URL Scheme | http(s), file, asset |
Most backends don't support manually specifying media format, with Android and Web being the exceptions. Therefore, no formal API planned for this feature. However, supported platforms can still automatically detect stream format from URL. You may simply append a file extension to the query string or hash fragment to specify the format. Please note that only 3 extensions are recognized: .m3u8, .mpd, and .ism/manifest. If multiple extensions are found, the last one takes precedence. For example:
// No need to specify format, the url already contains `.m3u8`
final example0 = 'https://example.com/video.m3u8';
// Missing extension in path, add `.m3u8` in hash fragment
final example1 = 'https://example.com/video#.m3u8';
// Or in query string
final example1 = 'https://example.com/video?.m3u8';
// Override HLS to DASH
final example2 = 'https://example.com/video.m3u8#.mpd';Footnotes
-
Only internal subtitle tracks are supported. ↩
-
MediaPlayermay lead to crash on certain Windows builds when rendering subtitles. ↩ -
video_viewrequiresmpv(v0.4+) orlibmpv(akampv-libs) on Linux. Developers integrating this plugin into Linux app should installlibmpv-dev(akampv-libs-devel) instead. If unavailable in your package manager, please buildmpvfrom source. For details refer to mpv-build. ↩ -
video_viewrequires ShakaPlayer v4.15+ to enable HLS, DASH, MSS support on web platforms. ↩ -
Windows user may need to install a free h.265 decoder from Microsoft Store. Web platforms may lack h.265 support except for Apple webkit. ↩
-
WebVTT subtitles within HLS are not supported by Linux backend. ↩