Im trying to understand what caching videos means and how exactly it works.
The problem that I had was a high bandwidth in my flutter /firebase application . I had like 19gb a day with 10-20 videos and like up to 10 users. So I could not figure out what the problem was. Therefore I contacted firebase support and they say
Looking at the graph, the high bandwidth comes from the storage bucket where the videos are stored. Even though it looks like there are few videos, your bandwidth will increase more and more if your application doesn't store the videos in cache.
Try to double check your applications and ensure that these ones download the information only once.
And I was like what the hak is chaching? And how to do it ? And will this solve the problem of high bandwidth?
here's how my code looks like
class Videoplayeritem extends StatefulWidget {
final bool mute;
final int pickedvideo;
final int currentPageIndex;
final bool isPaused;
final int pageIndex;
final String videourl;
final String thumbnailUrl;
const Videoplayeritem({
Key key,
this.videourl,
this.currentPageIndex,
this.isPaused,
this.pageIndex,
this.thumbnailUrl,
this.pickedvideo,
this.mute,
}) : super(key: key);
@override
_VideoplayeritemState createState() => _VideoplayeritemState();
}
class _VideoplayeritemState extends State<Videoplayeritem> {
VideoPlayerController videoPlayerController;
bool initialized = false;
bool stopvideo = false;
@override
void initState() {
super.initState();
try {
videoPlayerController = VideoPlayerController.network(
widget.videourl,
videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
)..initialize().then((value) {
if (this.mounted) setState(() {});
try {
videoPlayerController?.play();
videoPlayerController?.setLooping(true);
if (widget.mute) {
videoPlayerController?.setVolume(0);
} else if (!widget.mute) {
videoPlayerController?.setVolume(1);
}
} catch (e) {
print('error: $e');
}
});
} catch (e) {
print('error2: $e');
}
print('init');
}
@override
void dispose() {
try {
if (videoPlayerController.value.isPlaying) {
videoPlayerController?.pause();
}
videoPlayerController?.setVolume(0);
videoPlayerController?.dispose();
videoPlayerController = null;
} catch (e) {
print('error3: $e');
}
print('dispose');
super.dispose();
}
@override
Widget build(BuildContext context) {
if (widget.pageIndex == widget.currentPageIndex &&
!widget.isPaused &&
!stopvideo ||
widget.pageIndex == widget.pickedvideo &&
widget.currentPageIndex == null &&
!stopvideo) {
setState(() {
videoPlayerController?.play();
});
} else {
setState(() {
videoPlayerController?.pause();
});
}
if (widget.mute) {
videoPlayerController?.setVolume(0);
} else if (!widget.mute) {
videoPlayerController?.setVolume(1);
}
return Container(
color: Colors.black,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Center(
child: videoPlayerController.value.isInitialized
? GestureDetector(
onTap: () {
if (videoPlayerController.value.isPlaying) {
if (this.mounted) {
setState(() {
stopvideo = true;
videoPlayerController?.pause();
});
}
} else {
if (this.mounted) {
setState(() {
stopvideo = false;
videoPlayerController?.play();
videoPlayerController?.setLooping(true);
});
}
}
},
child: VisibilityDetector(
key: Key("unique keys"),
onVisibilityChanged: (VisibilityInfo info) {
debugPrint(
"${info.visibleFraction} of my widget is visible");
if (info.visibleFraction == 0) {
print("pause");
if (stopvideo == false) {
if (this.mounted) {
setState(() {
stopvideo = true;
});
}
}
videoPlayerController?.pause();
} else if (widget.pageIndex == widget.currentPageIndex ||
widget.pageIndex == widget.pickedvideo &&
widget.currentPageIndex == null) {
if (this.mounted) {
if (stopvideo == true) {
setState(() {
stopvideo = false;
});
}
}
videoPlayerController?.play();
} else {}
},
child: Stack(children: [
Center(
child: AspectRatio(
aspectRatio: videoPlayerController.value.aspectRatio,
child: VideoPlayer(videoPlayerController),
),
),
PlayPauseOverlay(
controller: videoPlayerController,
stopvideo: stopvideo,
)
]),
))
: Center(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: CachedNetworkImage(
errorWidget: (context, url, error) => Icon(Icons.error),
imageUrl: widget.thumbnailUrl,
fit: BoxFit.cover,
),
),
)),
);
}
}
My app is playing videos in Preloadpageview which are vertical scrollable like reels in instagram. The videos are loaded from stream .
Hope anyone can explain what chaching exactly mean and how it will affect my high bandwidth . Also how to used it in my case ?
The problem that I had was a high bandwidth in my flutter /firebase application . I had like 19gb a day with 10-20 videos and like up to 10 users.
There are two layers where caching can with this problem: initial video download, and subsequent video replay.
For initial video download, one option is to dedicate a server to act as an intermediary cache. It would download and stay in sync with the current videourl
's content and then serve it. The videourl
s would then be pointed to this server so the client pulls videos from it.
This only moves the problem around though, and bandwidth isn't free. But you don't have to host this cache server, there are companies that will host for a fee.
The way caching can help for subsequent video replay is by keeping it in local temporary storage on the video playing client, and when returning to the video, retrieving it from local temporary storage and playing it - thereby avoiding asking it from the server again.
One possibly quick solution could be by using the better_player
library. It allows many configurations, including using a cache. You can find it here