I have a video_player which played a video from network(VideoPlayerController.network(
https://...mp4)) and It’s working fine. But I want to take it to another step by playing a video that I get from a snapShot (StreamBuilder) as a video file(ex. 8296971978270266602.mp4) and download it by storage.ref('videos/$videoFile').getDownloadURL();
For me to get a link Url of course. Then I want to put the Url that I get from DownloadURL in the VideoPlayer so I can play the video. Please take a look at the code then you’ll understand on what I am trying to achieve.
code:
final FirebaseStorage storage = FirebaseStorage.instance;
late Future<void> initializeVideoPlayerFuture;
VideoPlayerController? _videoPlayerController;
@override
void initState() {
super.initState();
_videoPlayerController = VideoPlayerController.network(
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
);
initializeVideoPlayerFuture = _videoPlayerController!.initialize();
}
@override
void dispose() {
_videoPlayerController!.dispose();
super.dispose();
}
//My StreamBuilder to get snapShot from FB fireStore
StreamBuilder(
stream: FirebaseFirestore.instance
.collection("groups")
.doc(groupId)
.snapshots(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
var videoFile = snapshot.data?["videoFile"];
//ListView that I want to display all the video
ListView.builder(
itemCount: videoFile.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return FutureBuilder(
future: initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return AspectRatio(aspectRatio: _videoPlayerController!
.value.aspectRatio,
child: VideoPlayer(_videoPlayerController!
),
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}},
);
//Download the videoFile from Fb storage(Get the url and play it in the video_player)
Future<String> downloadVideoURL(String videoFile) async {
try {
String downloadURL =
await storage.ref('videos/$videoFile').getDownloadURL();
setState(() {
videoUrl = downloadURL;
});
// ignore: avoid_print
print(downloadURL);
return downloadURL;
} on FirebaseException catch (e) {
// ignore: avoid_print
print(e);
}
return downloadURL(videoFile);
}
Images:
To summary: As you can see in the code I only play a video by manually putting the Link to that video. But what I want is to put the videoUrl link that I get from downloadVideoUrl. And display all the video as a ListView. How can I do that?
You can make a separate widget for video player and call that widget inside your stream builder as following.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
class VideoPage extends StatefulWidget {
const VideoPage({Key? key}) : super(key: key);
@override
State<VideoPage> createState() => _VideoPageState();
}
class _VideoPageState extends State<VideoPage> {
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection("groups")
.doc('groupId')
.snapshots(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
/// Your code to show the error or loading according to snapshot state
var videoFile = snapshot.data?["videoFile"];
return ListView.builder(
itemCount: videoFile.length,
shrinkWrap: true,
itemBuilder: (ctx, index) {
return VideoPlayerWidget(name: videoFile[index]);
},
);
},
);
}
}
class VideoPlayerWidget extends StatefulWidget {
const VideoPlayerWidget({
Key? key,
required this.name,
}) : super(key: key);
final String name;
@override
State<VideoPlayerWidget> createState() => _VideoPlayerWidgetState();
}
class _VideoPlayerWidgetState extends State<VideoPlayerWidget> {
VideoPlayerController? _videoPlayerController;
var _isLoading = true;
late Future<void> initializeVideoPlayerFuture;
@override
void initState() {
super.initState();
_initPlayer();
}
void _initPlayer() async {
final _url = await downloadVideoURL(widget.name);
_videoPlayerController = VideoPlayerController.network(_url);
initializeVideoPlayerFuture = _videoPlayerController!.initialize();
_isLoading = false;
setState(() {});
}
Future<String> downloadVideoURL(String videoFile) async {
try {
String downloadURL =
await storage.ref('videos/$videoFile').getDownloadURL();
// ignore: avoid_print
print(downloadURL);
return downloadURL;
} on FirebaseException catch (e) {
// ignore: avoid_print
print(e);
}
return '';
}
@override
Widget build(BuildContext context) {
if(_isLoading) {
return CircularProgressIndicator();
}
return FutureBuilder(
future: initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return AspectRatio(
aspectRatio: _videoPlayerController!.value.aspectRatio,
child: VideoPlayer(_videoPlayerController!),
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
);
}
}