# [package:media_kit](https://github.com/media-kit/media-kit)
#### A cross-platform video player & audio player for Flutter & Dart.
[](https://discord.gg/h7qf2R9n57) [](https://github.com/media-kit/media-kit/actions/workflows/ci.yml)
Sponsored with 💖 by
Try the Flutter Chat tutorial
Clever Apps for Film Professionals
## Installation
[package:media_kit](https://github.com/media-kit/media-kit) is split into multiple packages to improve modularity & reduce bundle size.
#### For apps that need video playback:
```yaml
dependencies:
media_kit: ^1.1.10 # Primary package.
media_kit_video: ^1.2.4 # For video rendering.
media_kit_libs_video: ^1.0.4 # Native video dependencies.
```
#### For apps that need audio playback:
```yaml
dependencies:
media_kit: ^1.1.10 # Primary package.
media_kit_libs_audio: ^1.0.4 # Native audio dependencies.
```
**Notes:**
- The video libraries should be selected if both video & audio support is needed.
- The `media_kit_libs_video` & `media_kit_libs_audio` packages should not be mixed.
- The performance in ["Release" mode](https://docs.flutter.dev/testing/build-modes#release) is substantially higher than in ["Debug" mode](https://docs.flutter.dev/testing/build-modes#debug).
- [Enable --split-per-abi](https://docs.flutter.dev/deployment/android#what-is-a-fat-apk) or [use app bundle (instead of APK)](https://docs.flutter.dev/deployment/android#when-should-i-build-app-bundles-versus-apks) on Android.
## Platforms
| Platform | Video | Audio | Notes | Demo |
| -------- | ----- | ----- | ----- | ---- |
| Android | ✅ | ✅ | Android 5.0 or above. | [Download](https://github.com/media-kit/media-kit/releases/download/media_kit-v1.1.10/media_kit_test_android-arm64-v8a.apk) |
| iOS | ✅ | ✅ | iOS 9 or above. | [Download](https://github.com/media-kit/media-kit/releases/download/media_kit-v1.1.10/media_kit_test_ios_arm64.7z) |
| macOS | ✅ | ✅ | macOS 10.9 or above. | [Download](https://github.com/media-kit/media-kit/releases/download/media_kit-v1.1.10/media_kit_test_macos_universal.7z) |
| Windows | ✅ | ✅ | Windows 7 or above. | [Download](https://github.com/media-kit/media-kit/releases/download/media_kit-v1.1.10/media_kit_test_win32_x64.7z) |
| GNU/Linux | ✅ | ✅ | Any modern GNU/Linux distribution. | [Download](https://github.com/media-kit/media-kit/releases/download/media_kit-v1.1.10/media_kit_test_linux_x64.7z) |
| Web | ✅ | ✅ | Any modern web browser. | [Visit](https://media-kit.github.io/media-kit/) |
|
Android
|
iOS
|
|
|
|
macOS
|
Windows
|
|
|
|
GNU/Linux
|
Web
|
|
|
- ✅ Video playback
- ✅ Audio playback
- ✅ Cross platform
- ✅ Wide format/codec support
- ✅ Hardware/GPU acceleration
- ✅ Playlist support with next/previous/jump/shuffle
- ✅ Volume/Rate/Pitch change
- ✅ Video/Audio/Subtitle track selection
- ✅ External audio/subtitle track selection
- ✅ HTTP headers
- ✅ Video controls
- ✅ Subtitle styling
- ✅ Screenshot
## TL;DR
A quick usage example.
```dart
// Make sure to add following packages to pubspec.yaml:
// * media_kit
// * media_kit_video
// * media_kit_libs_video
import 'package:flutter/material.dart';
import 'package:media_kit/media_kit.dart'; // Provides [Player], [Media], [Playlist] etc.
import 'package:media_kit_video/media_kit_video.dart'; // Provides [VideoController] & [Video] etc.
void main() {
WidgetsFlutterBinding.ensureInitialized();
// Necessary initialization for package:media_kit.
MediaKit.ensureInitialized();
runApp(
const MaterialApp(
home: MyScreen(),
),
);
}
class MyScreen extends StatefulWidget {
const MyScreen({Key? key}) : super(key: key);
@override
State createState() => MyScreenState();
}
class MyScreenState extends State {
// Create a [Player] to control playback.
late final player = Player();
// Create a [VideoController] to handle video output from [Player].
late final controller = VideoController(player);
@override
void initState() {
super.initState();
// Play a [Media] or [Playlist].
player.open(Media('https://user-images.githubusercontent.com/28951144/229373695-22f88f13-d18f-4288-9bf1-c3e078d83722.mp4'));
}
@override
void dispose() {
player.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.width * 9.0 / 16.0,
// Use [Video] widget to display video output.
child: Video(controller: controller),
),
);
}
}
```
**Note:** You may need to add required [permissions](#permissions) to your project.
## Guide
A usage guide for [package:media_kit](https://github.com/media-kit/media-kit).
**Tip:** Use Ctrl + F to quickly search for things.
### Contents
- [Initialization](#initialization)
- [Create a `Player`](#create-a-player)
- [Dispose a `Player`](#dispose-a-player)
- [Open a `Media` or `Playlist`](#open-a-media-or-playlist)
- [Play, pause or play/pause](#play-pause-or-playpause)
- [Seek](#seek)
- [Loop or repeat](#loop-or-repeat)
- [Set volume, rate or pitch](#set-volume-rate-or-pitch)
- [Handle playback events](#handle-playback-events)
- [Shuffle the queue](#shuffle-the-queue)
- [Use HTTP headers](#use-http-headers)
- [Use `extras` to store additional data with `Media`](use-extras-store-additional-data-with-media)
- [Go to next, previous or any other position in queue](#go-to-next-previous-or-any-other-position-in-queue)
- [Modify `Player`'s queue](#modify-players-queue)
- [Select video, audio or subtitle track](#select-video-audio-or-subtitle-track)
- [Select audio device](#select-audio-device)
- [Display the video](#display-the-video)
- [Capture screenshot](#capture-screenshot)
- [Customize subtitles](#customize-subtitles)
- [Load external subtitle track](#load-external-subtitle-track)
- [Load external audio track](#load-external-audio-track)
- [Video controls](#video-controls)
- [Next steps](#next-steps)
### Initialization
`MediaKit.ensureInitialized` must be called before using the package:
```dart
void main() {
WidgetsFlutterBinding.ensureInitialized();
// Make sure to add the required packages to pubspec.yaml:
// * https://github.com/media-kit/media-kit#installation
// * https://pub.dev/packages/media_kit#installation
MediaKit.ensureInitialized();
runApp(const MyApp());
}
```
The method also has some optional arguments to customize the global behavior. To handle any initialization errors, this may be surrounded by `try`/`catch`.
### Create a `Player`
A `Player` instance is used to start & control the playback of a media source e.g. URL or file.
```dart
final Player player = Player();
```
Additional options may be provided using the `configuration` argument in the constructor. In general situations, you will never require this.
```dart
final Player player = Player(
configuration: PlayerConfiguration(
// Supply your options:
title: 'My awesome package:media_kit application',
ready: () {
print('The initialization is complete.');
},
),
);
```
### Dispose a `Player`
It is extremely important to release the allocated resources back to the system:
```dart
await player.dispose();
```
### Open a `Media` or `Playlist`
A `Playable` can either be a `Media` or a `Playlist`.
- `Media`: Single playback source (file or URL).
- `Playlist`: Queue of playback sources (file or URL).
Use the `Player.open` method to load & start playback.
#### `Media`
```dart
final playable = Media('https://user-images.githubusercontent.com/28951144/229373695-22f88f13-d18f-4288-9bf1-c3e078d83722.mp4');
await player.open(playable);
```
#### `Playlist`
```dart
final playable = Playlist(
[
Media('https://user-images.githubusercontent.com/28951144/229373695-22f88f13-d18f-4288-9bf1-c3e078d83722.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373709-603a7a89-2105-4e1b-a5a5-a6c3567c9a59.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373716-76da0a4e-225a-44e4-9ee7-3e9006dbc3e3.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373718-86ce5e1d-d195-45d5-baa6-ef94041d0b90.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373720-14d69157-1a56-4a78-a2f4-d7a134d7c3e9.mp4'),
],
);
await player.open(playable);
```
**Notes:**
1. By default, this will automatically start playing the playable. This may be disabled as follows:
```dart
await player.open(
playable,
play: false,
);
```
2. By default, the playlist will start at the index `0`. This may be changed as follows:
```dart
final playable = Playlist(
[
Media('https://user-images.githubusercontent.com/28951144/229373695-22f88f13-d18f-4288-9bf1-c3e078d83722.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373709-603a7a89-2105-4e1b-a5a5-a6c3567c9a59.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373716-76da0a4e-225a-44e4-9ee7-3e9006dbc3e3.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373718-86ce5e1d-d195-45d5-baa6-ef94041d0b90.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373720-14d69157-1a56-4a78-a2f4-d7a134d7c3e9.mp4'),
],
// Declare the starting position.
index: 0,
);
await player.open(playable);
```
### Play, pause or play/pause
The 3 methods are:
```dart
await player.play();
```
```dart
await player.pause();
```
```dart
await player.playOrPause();
```
### Stop
The `stop` method may be used to stop the playback of currently opened `Media` or `Playlist`.
```dart
await player.stop();
```
It does not release allocated resources back to the system (unlike [`dispose`](#dispose-a-player)) & `Player` still stays usable.
### Seek
Supply the final position to `Player.seek` method as `Duration`:
```dart
await player.seek(
const Duration(
minutes: 6,
seconds: 9,
),
);
```
### Loop or repeat
Three `PlaylistMode`s are available:
- `PlaylistMode.none`: End playback once end of the playlist is reached.
- `PlaylistMode.single`: Indefinitely loop over the currently playing file in the playlist.
- `PlaylistMode.loop`: Loop over the playlist & restart it from beginning once end is reached.
```dart
await player.setPlaylistMode(PlaylistMode.single);
```
### Set volume, rate or pitch
#### Set the volume
This controls the loudness of audio output. The maximum volume is `100.0`.
```dart
await player.setVolume(50.0);
```
#### Set the rate
This controls the playback speed.
```dart
await player.setRate(1.5);
```
#### Set the pitch
This controls the pitch of the audio output.
```dart
await player.setPitch(1.2);
```
**Note:** This requires `pitch` argument to be `true` in `PlayerConfiguration`.
### Handle playback events
You can access or subscribe to `Player`'s state changes.
Event handling is an extremely important part of media playback. It is used to show changes in the UI, handle errors, detect the occurrence of play/pause, end-of-file, position updates etc.
- `Player.stream.*`: Provides access to `Player`'s state as [`Stream`](https://dart.dev/tutorials/language/streams)(s).
- `Player.state.*`: Provides access to `Player`'s state directly (for instantaneous access).
A typical example will be:
```dart
player.stream.playing.listen(
(bool playing) {
if (playing) {
// Playing.
} else {
// Paused.
}
},
);
player.stream.position.listen(
(Duration position) {
setState(() {
// Update UI.
});
},
);
```
The following state(s) are available as events:
| Type | Name | Description |
| --------------------------- | -------------- | -------------------------------------------------------------------------------------------------------- |
| `Stream` | `playlist` | Currently opened media sources. |
| `Stream` | `playing` | Whether playing or not. |
| `Stream` | `completed` | Whether end of currently playing media source has been reached. |
| `Stream` | `position` | Current playback position. |
| `Stream` | `duration` | Current playback duration. |
| `Stream` | `volume` | Current volume. |
| `Stream` | `rate` | Current playback rate. |
| `Stream` | `pitch` | Current pitch. |
| `Stream` | `buffering` | Whether buffering or not. |
| `Stream` | `buffer` | Current buffer position. This indicates how much of the stream has been decoded & cached by the demuxer. |
| `Stream` | `playlistMode` | Current playlist mode. |
| `Stream` | `audioParams` | Audio parameters of the currently playing media source e.g. sample rate, channels, etc. |
| `Stream` | `videoParams` | Video parameters of the currently playing media source e.g. width, height, rotation etc. |
| `Stream` | `audioBitrate` | Audio bitrate of the currently playing media source. |
| `Stream` | `audioDevice` | Currently selected audio device. |
| `Stream>` | `audioDevices` | Currently available audio devices. |
| `Stream