import 'package:audio_video_progress_bar/audio_video_progress_bar.dart'; import 'package:fis_common/logger/logger.dart'; import 'package:fis_measure/interfaces/process/player/play_controller.dart'; import 'package:fis_measure/view/player/controller.dart'; import 'package:fis_measure/view/player/events.dart'; import 'package:fis_vid/data_channel/progress_info.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:fis_measure/view/mobile_view/widgets/throttle.dart' as utils; class StreamingProgressBar extends StatefulWidget { const StreamingProgressBar({super.key}); @override State createState() => _StreamingProgressBarState(); } class _StreamingProgressBarState extends State { final controller = Get.find() as VidPlayerController; int totalCount = 0; int currentIndex = 0; double bufferedProgress = 0; int get bufferedCount { int count = (bufferedProgress * totalCount).toInt(); final currentPlayedIndex = controller.currentFrame?.index ?? 0; if (count < currentPlayedIndex) { // 缓冲进度至少需要追平播放(可播放)进度 count = currentPlayedIndex; } return count; } @override void initState() { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { controller.eventHandler.addListener(_onControllerEvent); controller.dataChannel.downloadProgressChanged .addListener(_onDownloadProgressChanged); }); super.initState(); } @override void dispose() { controller.dataChannel.downloadProgressChanged .removeListener(_onDownloadProgressChanged); controller.eventHandler.removeListener(_onControllerEvent); super.dispose(); } @override Widget build(BuildContext context) { return ProgressBar( progress: Duration(milliseconds: currentIndex), total: Duration(milliseconds: totalCount), buffered: Duration(milliseconds: bufferedCount), // baseBarColor: Colors.blueGrey, // progressBarColor: Colors.blue, // bufferedBarColor: Colors.pink[300], barHeight: 12, thumbRadius: 10, thumbColor: Colors.white, timeLabelLocation: TimeLabelLocation.none, onSeek: (timeStamp) { final newIndex = timeStamp.inMilliseconds; if (newIndex != currentIndex) { setState(() { currentIndex = newIndex; }); controller.locateTo(currentIndex); } }, onDragUpdate: (details) { final newIndex = details.timeStamp.inMilliseconds; if (newIndex != currentIndex) { setState(() { currentIndex = newIndex; }); utils.throttle(() { controller.locateTo(currentIndex); }, 'onDragTo', 80); // controller.locateTo(currentIndex); } }, onDragStart: (details) { //手动拖动时移除事件监听【避免重复setstate】 controller.eventHandler.removeListener(_onControllerEvent); }, onDragEnd: () { controller.eventHandler.addListener(_onControllerEvent); }, ); } void _update() { /// 第一帧下标为0 ,所以 totalFramesCount 要减1 totalCount = controller.totalFramesCount - 1; currentIndex = controller.currentFrameIndex; if (mounted) { setState(() {}); } } void _onDownloadProgressChanged(Object sender, VidDownloadProgressInfo e) { if (e.progress == 1) { bufferedProgress = 1; } else { bufferedProgress = _calcRealFramesBufferPercent(); } if (mounted) { setState(() {}); } } void _onControllerEvent(Object sender, VidPlayerEvent e) { if (e is VidPlayerFrameIndexChangeEvent) { if (currentIndex != e.index) { _update(); } } } double _calcRealFramesBufferPercent() { final channel = controller.dataChannel; final int fileSize = channel.getFileSize(); final int bufferredSize = channel.getBufferSize(); final int framesTotalSize = fileSize - controller.vidHeaderSize; final int framesBufferredSize = bufferredSize - controller.vidHeaderSize; double percent = framesBufferredSize / framesTotalSize; return percent; } }