I am trying to develop an app that presents videos to the user. I am using VideoPlayerController
for loading the videos, and ChewieController
for the UI.
It works great, but when the user closes the app, the video stops. I would like the video to keep playing its audio even when closing the app/locking the device.
I couldn't find anything about it on the VideoPlayerController
and in the ChewieController
documentations.
Is this functionality possible in Flutter and Dart?
Thank you!
Unfortunately Flutter's video_player
package doesn't support background video or audio playing. But you can use flutter_playout
which wraps ExoPlayer
on Android and AVPlayer
framework on iOS with the ability to playback video in background or even lock screen. You can find out more about it here. Below is an example code provided by library's GitHub repo which plays a video and it keeps playing in background
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_playout/multiaudio/HLSManifestLanguage.dart';
import 'package:flutter_playout/multiaudio/MultiAudioSupport.dart';
import 'package:flutter_playout/player_observer.dart';
import 'package:flutter_playout/player_state.dart';
import 'package:flutter_playout/video.dart';
import 'package:flutter_playout_example/hls/getManifestLanguages.dart';
class VideoPlayout extends StatefulWidget {
final PlayerState desiredState;
final bool showPlayerControls;
const VideoPlayout({Key key, this.desiredState, this.showPlayerControls})
: super(key: key);
@override
_VideoPlayoutState createState() => _VideoPlayoutState();
}
class _VideoPlayoutState extends State<VideoPlayout>
with PlayerObserver, MultiAudioSupport {
final String _url = null;
List<HLSManifestLanguage> _hlsLanguages = List<HLSManifestLanguage>();
@override
void initState() {
super.initState();
Future.delayed(Duration.zero, _getHLSManifestLanguages);
}
Future<void> _getHLSManifestLanguages() async {
if (!Platform.isIOS && _url != null && _url.isNotEmpty) {
_hlsLanguages = await getManifestLanguages(_url);
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
/* player */
AspectRatio(
aspectRatio: 16 / 9,
child: Video(
autoPlay: true,
showControls: widget.showPlayerControls,
title: "MTA International",
subtitle: "Reaching The Corners Of The Earth",
preferredAudioLanguage: "eng",
isLiveStream: true,
position: 0,
url: _url,
onViewCreated: _onViewCreated,
desiredState: widget.desiredState,
),
),
/* multi language menu */
_hlsLanguages.length < 2 && !Platform.isIOS
? Container()
: Container(
child: Row(
children: _hlsLanguages
.map((e) => MaterialButton(
child: Text(
e.name,
style: Theme.of(context)
.textTheme
.button
.copyWith(color: Colors.white),
),
onPressed: () {
setPreferredAudioLanguage(e.code);
},
))
.toList(),
),
),
],
),
);
}
void _onViewCreated(int viewId) {
listenForVideoPlayerEvents(viewId);
enableMultiAudioSupport(viewId);
}
@override
void onPlay() {
// TODO: implement onPlay
super.onPlay();
}
@override
void onPause() {
// TODO: implement onPause
super.onPause();
}
@override
void onComplete() {
// TODO: implement onComplete
super.onComplete();
}
@override
void onTime(int position) {
// TODO: implement onTime
super.onTime(position);
}
@override
void onSeek(int position, double offset) {
// TODO: implement onSeek
super.onSeek(position, offset);
}
@override
void onDuration(int duration) {
// TODO: implement onDuration
super.onDuration(duration);
}
@override
void onError(String error) {
// TODO: implement onError
super.onError(error);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With