import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:media_kit_video/media_kit_video.dart'; /// media_kit Video 包装:封面兜底、缓冲转圈、暂停态大播放图标 /// /// 封面仅在视频尚未渲染出第一帧时显示(player state 仍在初始 idle), /// 一旦 HLS 起播第一帧,封面立即淡出,避免「有声音没画面被封面挡住」。 class VideoPlayerView extends StatelessWidget { const VideoPlayerView({ super.key, required this.controller, required this.coverUrl, required this.playing, }); final VideoController controller; final String coverUrl; final bool playing; @override Widget build(BuildContext context) { final player = controller.player; return Stack( fit: StackFit.expand, children: [ // 播放器(无控制条,纯画面) Video( controller: controller, controls: NoVideoControls, fit: BoxFit.contain, ), // 封面兜底:仅在视频尚未开始渲染时显示 StreamBuilder( stream: player.stream.position, initialData: player.state.position, builder: (_, snapshot) { final pos = snapshot.data ?? Duration.zero; // position == 0 说明还没渲染出第一帧(含初始加载和播完后) final showCover = coverUrl.isNotEmpty && pos == Duration.zero; return showCover ? CachedNetworkImage( imageUrl: coverUrl, fit: BoxFit.cover, errorWidget: (_, __, ___) => const SizedBox.shrink(), ) : const SizedBox.shrink(); }, ), // 暂停态大播放图标 if (!playing) const IgnorePointer( child: Center( child: Icon( Icons.play_arrow_rounded, size: 88, color: Colors.white70, ), ), ), ], ); } }