Flutter Video_player:增强位置精度
我目前正在使用 video_player 来精确分析视频。 不幸的是,我似乎无法提高 VideoPlayer 实例的不同“位置”获取器的精度。顶部每次刷新之间的间隔为 500ms。它对应于进度指示器的更新。 500 毫秒来检索体育数据(例如短跑)太大了。
可以实时更新吗?越精确越好,比如流什么的。
下面是代码,从他们的示例来看非常简单,我使用内置 Stream,它仅在完成时发送事件,并且位置获取器与其他刷新器相同(500ms)
class AssistantHome extends StatefulWidget {
final UserTest test;
final Player player;
const AssistantHome({Key key, @required this.test, @required this.player})
: super(key: key);
@override
State<AssistantHome> createState() => _AssistantHomeState();
}
class _AssistantHomeState extends State<AssistantHome> {
VideoPlayerController _controller;
int _positionInMs;
Stream<Duration> durationStream;
@override
void initState() {
super.initState();
_controller = VideoPlayerController.network(widget.test.videoUrl);
durationStream = _controller.position.asStream();
_controller.addListener(() {
setState(() {
_positionInMs = _controller.value.position.inMilliseconds;
});
});
_controller.setLooping(true);
_controller.initialize().then((_) => setState(() {}));
_controller.play();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column(
children: <Widget>[
Text('${widget.test.uid}'),
Container(
height: 600,
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: SizedBox(
height: 600,
child: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
VideoPlayer(_controller),
_ControlsOverlay(controller: _controller),
VideoProgressIndicator(_controller,
allowScrubbing: true),
],
),
),
),
),
StreamBuilder(builder: ((context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.connectionState ==
ConnectionState.active ||
snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return const Text('Error');
} else if (snapshot.hasData) {
return Text(snapshot.data.toString(),
style: const TextStyle(
color: Colors.teal, fontSize: 36));
} else {
return const Text('Empty data');
}
} else {
return Text(
'Duration: ${_controller.value.position.inMicroseconds} us');
}
})),
Text("Current position: $_positionInMs ms"),
const Text('Footer'),
],
),
),
],
),
);
}
}
class _ControlsOverlay extends StatelessWidget {
const _ControlsOverlay({Key key, @required this.controller})
: super(key: key);
final VideoPlayerController controller;
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
AnimatedSwitcher(
duration: const Duration(milliseconds: 50),
reverseDuration: const Duration(milliseconds: 200),
child: controller.value.isPlaying
? const SizedBox.shrink()
: Container(
color: Colors.black26,
child: const Center(
child: Icon(
Icons.play_arrow,
color: Colors.white,
size: 100.0,
semanticLabel: 'Play',
),
),
),
),
GestureDetector(
onTap: () {
controller.value.isPlaying ? controller.pause() : controller.play();
},
),
],
);
}
}
I'm currently using the video_player to analyse the videos with precision.
Unfortunately, I can't seem to be able to enhance the precision of the different "position" getter of the VideoPlayer instance. The top is 500ms interval between each refresh. It corresponds to the update of the progress indicator. 500ms to retrieve sports data such s a sprint is way too big.
Would it be possible to have a real time update ? The more precise the better, such as a stream or something.
Below is the code, super simple from their example, I'm using the builtin Stream which only sends an event when completed, and the position getter is the same refresh than the other (500ms)
class AssistantHome extends StatefulWidget {
final UserTest test;
final Player player;
const AssistantHome({Key key, @required this.test, @required this.player})
: super(key: key);
@override
State<AssistantHome> createState() => _AssistantHomeState();
}
class _AssistantHomeState extends State<AssistantHome> {
VideoPlayerController _controller;
int _positionInMs;
Stream<Duration> durationStream;
@override
void initState() {
super.initState();
_controller = VideoPlayerController.network(widget.test.videoUrl);
durationStream = _controller.position.asStream();
_controller.addListener(() {
setState(() {
_positionInMs = _controller.value.position.inMilliseconds;
});
});
_controller.setLooping(true);
_controller.initialize().then((_) => setState(() {}));
_controller.play();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column(
children: <Widget>[
Text('${widget.test.uid}'),
Container(
height: 600,
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: SizedBox(
height: 600,
child: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
VideoPlayer(_controller),
_ControlsOverlay(controller: _controller),
VideoProgressIndicator(_controller,
allowScrubbing: true),
],
),
),
),
),
StreamBuilder(builder: ((context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.connectionState ==
ConnectionState.active ||
snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return const Text('Error');
} else if (snapshot.hasData) {
return Text(snapshot.data.toString(),
style: const TextStyle(
color: Colors.teal, fontSize: 36));
} else {
return const Text('Empty data');
}
} else {
return Text(
'Duration: ${_controller.value.position.inMicroseconds} us');
}
})),
Text("Current position: $_positionInMs ms"),
const Text('Footer'),
],
),
),
],
),
);
}
}
class _ControlsOverlay extends StatelessWidget {
const _ControlsOverlay({Key key, @required this.controller})
: super(key: key);
final VideoPlayerController controller;
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
AnimatedSwitcher(
duration: const Duration(milliseconds: 50),
reverseDuration: const Duration(milliseconds: 200),
child: controller.value.isPlaying
? const SizedBox.shrink()
: Container(
color: Colors.black26,
child: const Center(
child: Icon(
Icons.play_arrow,
color: Colors.white,
size: 100.0,
semanticLabel: 'Play',
),
),
),
),
GestureDetector(
onTap: () {
controller.value.isPlaying ? controller.pause() : controller.play();
},
),
],
);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尝试使用
smooth_video_progress
包:https://pub.dev/packages/smooth_video_progress!来自 https://pub.dev/packages/smooth_video_progress#usage:
Try using the
smooth_video_progress
package: https://pub.dev/packages/smooth_video_progress!From https://pub.dev/packages/smooth_video_progress#usage: