Я использую video_player в моем приложении флаттера на iOS для воспроизведения и воспроизведения видео из локального файла после его загрузки. Я следовал руководству " Воспроизведение и приостановка видео " из поваренной книги флаттера.
Чтобы воспроизвести видео один раз после завершения загрузки, я использую addPostFrameCallback из WidgetsBinding. Затем пользователь может воспроизвести видео, нажав на него.
WidgetsBinding.instance.addPostFrameCallback((_) => afterBuild());
Это работает хорошо в большинстве случаев, но на старых устройствах, таких как iPad air 1-го поколения, иногда рендеринг видео происходит не плавно и падает некоторые кадры или немного звука при запуске, создавая впечатление прерывистого звука или видео.
Обратите внимание, что я играю очень короткие видео (от ~ 1 до ~ 3 секунд), я не знаю, может ли это повлиять на производительность video_player (который может потребоваться немного для запуска видео и воспроизводить его плавно?)
Ниже приведен мой текущий код.
Уже давно я занимаюсь этим вопросом и не знаю, как устранить неполадки. Я уже пытался немного задержать первый звонок для воспроизведения видео (что дало игроку немного больше времени), но это не решило проблему. Иногда видео по-прежнему не воспроизводится гладко.
Есть идеи, что еще попробовать?
Вот мой код:
class MyVideoPlayer extends StatefulWidget {
final File videoFile;
MyVideoPlayer({Key key, this.videoFile}) : super(key: key);
@override
_MyVideoPlayerState createState() => _MyVideoPlayerState();
}
class _MyVideoPlayerState extends State<MyVideoPlayer> {
VideoPlayerController _controller;
Future<void> _initializeVideoPlayerFuture;
@override
void initState() {
_controller = VideoPlayerController.file(widget.videoFile);
WidgetsBinding.instance.addPostFrameCallback((_) => afterBuild());
_controller.addListener(() async {
if (_controller.value.duration != null &&
_controller.value.position >= _controller.value.duration) {
await _controller.seekTo(Duration(seconds: 0));
await _controller.pause();
}
});
_initializeVideoPlayerFuture = _controller.initialize();
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
_videoPressed() async {
if (!_controller.value.isPlaying) {
_controller.play();
}
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: GestureDetector(
onTap: () {
_videoPressed();
},
child: VideoPlayer(_controller),
),
);
} else {
return CircularProgressIndicator();
}
},
);
}
void afterBuild() {
_videoPressed();
}
}