我正在构建一个基本上是YouTube克隆的应用。我使用官方的video_player插件进行播放,并使用chewie进行控件。我想实现一个质量切换器,以便用户可以决定他们希望视频以什么质量流式传输
我已经建立了一个带有开关的底页,当用户选择所需的质量时,我运行changeQuality()
。它应该做的就是简单地将一个新的源文件提供给旧播放器,并在视频离开的地方继续播放。
这是在initState()上运行的视频播放器和chewie播放器:
videoPlayer = VideoPlayerController.network(data == null
? dataAll[indexNo]["video"]["480"]
: data[indexNo]["video"]["480"]);
chewieController = ChewieController(
videoPlayerController: videoPlayer,
aspectRatio: 16 / 9,
autoPlay: true,
allowedScreenSleep: false,
placeholder: data == null
? Image(
image: NetworkImage(dataAll[indexNo]["thumbnail"]),
)
: Image(
image: NetworkImage(data[indexNo]["thumbnail"]),
)
);
还有changeQuality()
函数:
changeQuality(String newQuality) {
setState(() {
position = videoPlayer.value.position;
chewieController.pause();
videoPlayer = new VideoPlayerController.network(data == null
? dataAll[indexNo]["video"]["$newQuality"]
: data[indexNo]["video"]["$newQuality"]);
chewieController = ChewieController(
videoPlayerController: videoPlayer,
aspectRatio: 16 / 9,
autoPlay: true,
allowedScreenSleep: false,
startAt: position,
);
});
Navigator.of(context).pop();
}
我还尝试过处置旧的视频播放器,然后设置新值,但是我收到一个错误,指出处置后无法使用变量。
切换器可以工作一点,因为它会改变质量约4到5倍,然后出现错误,无法播放任何内容。
答案 0 :(得分:2)
我在this solution for video_player上进行扩展,并将其扩展为也包括chewie。
我用this.
书写,但在Dart代码中可以省略。
class QuizVideoPlayer extends StatefulWidget {
@override
_QuizVideoPlayerState createState() => _QuizVideoPlayerState();
}
class _QuizVideoPlayerState extends State<QuizVideoPlayer> {
Word _url;
UniqueKey _urlKey;
// Call this method from button or in reaction to model change etc.
// I call it from Provider.of in didChangeDependencies, but I don't think it is
// a necessary detail of the answer as it depends on how you do state management.
// The key in this solution is that state management occur in the outer widget and
// due to some trigger call _changeUrl() which changes _url and _urlKey which then
// swaps out MyVideoPlayer.
@override
void _changeUrl(String newUrl) async {
this.setState(() {
// Rebuild MyVideoPlayer with a new instance => eventually dispose old controllers
this._url = newUrl;
this._urlKey = UniqueKey();
});
}
@override
Widget build(BuildContext context) {
return
/* ... */
this._url != null
? MyVideoPlayer(
this._url,
this._urlKey,
)
: AspectRatio(
aspectRatio: 3 / 2,
child: Container(color: Colors.black),
)
/* ... */
);
}
}
我用this.
书写,但在Dart代码中可以省略。
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:chewie/chewie.dart';
class MyVideoPlayer extends StatefulWidget {
final String videoUrl;
final UniqueKey newKey;
MyVideoPlayer(this.videoUrl, this.newKey): super(key: newKey); // passing Unique key to dispose old class instance and create new with new data
@override
_MyVideoPlayerState createState() => _MyVideoPlayerState();
}
class _MyVideoPlayerState extends State<MyVideoPlayer> {
VideoPlayerController _controller;
ChewieController _chewie;
@override
void initState() {
this._initControllers(this.widget.videoUrl);
super.initState();
}
void _initControllers(String url) {
this._controller = VideoPlayerController.network(url);
this._chewie = ChewieController(
videoPlayerController: this._controller,
autoPlay: true,
);
}
@override
void dispose() {
this._controller?.dispose();
this._chewie?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Chewie(controller: this._chewie);
}
}