Flutter_学习记录_video_player、chewie 播放视频
1. video_player 视频播放
插件地址:https://pub.dev/packages/video_player
- 添加插件

- 导入头文件
import 'package:video_player/video_player.dart';
- Android配置(iOS不用配置)
修改这个文件:
/android/app/src/main/AndroidManifest.xml;
添加下面的配置:
<uses-permission android:name="android.permission.INTERNET"/>
- 添加核心代码
初始化播放器:
Uri url = Uri.parse("https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4");_videoPlayerController = VideoPlayerController.networkUrl(url);_videoPlayerController.initialize().then((_){print("播放器初始化完成");// 添加播放器的监听_videoPlayerController.addListener(_onVideoChange);// 设置自动播放_videoPlayerController.play();_isPlaying = true;setState(() {print("111111");});});
添加播放器的视图:
return VideoPlayer(_videoPlayerController);
退出页面时,需要销毁播放器:
void dispose() {_videoPlayerController.dispose();super.dispose();}
- 完整代码
import 'dart:async';import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';class VideoPlayerDemo extends StatefulWidget {const VideoPlayerDemo({super.key});State<VideoPlayerDemo> createState() => _VideoPlayerDemoState();
}class _VideoPlayerDemoState extends State<VideoPlayerDemo> {late VideoPlayerController _videoPlayerController;bool _isPlaying = false;double _progress = 0.0;// 添加播放状态的订阅,避免每次调用setState 重刷页面late StreamController _isPlayingController;// 添加播放进度的订阅,避免每次调用setState 重刷页面late StreamController _progressController;void initState() {super.initState();_isPlayingController = StreamController.broadcast();_progressController = StreamController.broadcast();Uri url = Uri.parse("https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4");_videoPlayerController = VideoPlayerController.networkUrl(url);_videoPlayerController.initialize().then((_){print("播放器初始化完成");// 添加播放器的监听_videoPlayerController.addListener(_onVideoChange);// 设置自动播放_videoPlayerController.play();_isPlaying = true;setState(() {});});}void dispose() {_videoPlayerController.dispose();_isPlayingController.close();_progressController.close();super.dispose();}// 自定义播放器的监听回调的方法void _onVideoChange() {print("播放器的监听回调");if (_videoPlayerController.value.isInitialized) {final isPlaying = _videoPlayerController.value.isPlaying;if (isPlaying != _isPlaying) {_isPlaying = isPlaying;_isPlayingController.sink.add(_isPlaying);}// 更新播放进度final position = _videoPlayerController.value.position;final duration = _videoPlayerController.value.duration;if (duration != null) {_progress = position.inMilliseconds / duration.inMilliseconds;print("进度 = $_progress");_progressController.sink.add(_progress);}// 检查视频是否播放完毕if (position >= duration) {print('Video has completed playing.');_videoPlayerController.seekTo(Duration.zero); // 重置到开始位置_videoPlayerController.pause(); // 暂停播放_isPlaying = false;_isPlayingController.add(_isPlaying);}}}// 播放器的视图Widget _palyerViewWidget() {if (_videoPlayerController.value.isInitialized) {// 初始化成功return AspectRatio(aspectRatio: _videoPlayerController.value.aspectRatio,child: Stack(children: [// 播放器VideoPlayer(_videoPlayerController),// 添加进度条Align(alignment: Alignment.bottomCenter,child: _progressWidget(),)],));} else {// loading视图return CircularProgressIndicator();}}// 进度条Widget _progressWidget() {// 进度条变化比较频繁:用 StreamBuilder 减少内存的消耗return StreamBuilder(stream: _progressController.stream, builder: (context, snapshot) {print("更新进度条");return SizedBox(height: 35,child: Slider(value: _progress,onChanged: (value) {print("onChanged");setState(() {_videoPlayerController.seekTo(Duration(milliseconds: (value * _videoPlayerController.value.duration.inMilliseconds).round()));});},),);});}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Video_Player_demo"),),body: Center(child: _palyerViewWidget(),),floatingActionButton: FloatingActionButton(onPressed: (){if (_isPlaying) {// 正在播放_videoPlayerController.pause();_isPlaying = false;} else {_videoPlayerController.play();_isPlaying = true;}_isPlayingController.add(_isPlaying);},// 这个按钮变化比较频繁:用 StreamBuilder 减少内存的消耗child: StreamBuilder(stream: _isPlayingController.stream, builder: (context, snapshot) {return Icon(_isPlaying ? Icons.pause : Icons.play_arrow);}),),);}
}
- 效果图如下:

2. chewie 播放视频
在 Flutter 里官方提供了一个
video_player插件可以播放视频,但video_player有一些局限性:没法控制底部播放进度等。
所以可以用另外一个三方的视频播放库chewie。
chewie是一个非官方的第三方视频播放组件,看起来好像是基于 HTML5 播放的组件。
chewie 相对 video_player 来说,有控制栏和全屏的功能。
Chewie使用video_player引擎并将其包裹在友好的 Material 或 Cupertino UI中!
插件地址:https://pub.dev/packages/chewie
- 引入插件
chewie基于video_player,所以要使用chewie必须配置video_player

- 导入头文件
import 'package:video_player/video_player.dart';
import 'package:chewie/chewie.dart';
- Android配置(iOS不用配置)
修改这个文件:
/android/app/src/main/AndroidManifest.xml;
添加下面的配置:
<uses-permission android:name="android.permission.INTERNET"/>
- 核心代码
import 'package:chewie/chewie.dart';
import 'package:video_player/video_player.dart';final videoPlayerController = VideoPlayerController.networkUrl(Uri.parse('https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4'));await videoPlayerController.initialize();final chewieController = ChewieController(videoPlayerController: videoPlayerController,autoPlay: true,looping: true,
);final playerWidget = Chewie(controller: chewieController,
);
退出页面时,需要销毁播放器:
void dispose() {_videoPlayerController.dispose();_chewieController.dispose();super.dispose();}
- 完整代码
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:chewie/chewie.dart';class ChewieDemo extends StatefulWidget {const ChewieDemo({super.key});State<ChewieDemo> createState() => _ChewieDemoState();
}class _ChewieDemoState extends State<ChewieDemo> {late VideoPlayerController _videoPlayerController;late ChewieController _chewieController;void initState() {super.initState();// 初始化播放器_initVideo();}void dispose() {_videoPlayerController.dispose();_chewieController.dispose();super.dispose();}// 初始化播放器void _initVideo() async {Uri url = Uri.parse("https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4");_videoPlayerController = VideoPlayerController.networkUrl(url);await _videoPlayerController.initialize();_chewieController = ChewieController(videoPlayerController: _videoPlayerController,aspectRatio: _videoPlayerController.value.aspectRatio,autoPlay: true,looping: false);setState(() {});}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Chewie demo-在线播放视频"),),body: Center(child: _videoPlayerController.value.isInitialized ? AspectRatio(aspectRatio: _videoPlayerController.value.aspectRatio,child: Chewie(controller: _chewieController),) : CircularProgressIndicator(),),);}
}
- 效果图:

相关文章:
Flutter_学习记录_video_player、chewie 播放视频
1. video_player 视频播放 插件地址:https://pub.dev/packages/video_player 添加插件 导入头文件 import package:video_player/video_player.dart;Android配置(iOS不用配置) 修改这个文件:/android/app/src/main/AndroidMani…...
【MySQL】增删改查进阶
目录 一、数据库约束 约束类型 NULL约束:非空约束 UNIQUE:唯一约束 DEFAULT:默认值约束 PRIMARY KEY:主键约束 FOREIGN KEY:外键约束 二、表的设计 三、新增 四、查询 聚合查询 聚合函数 GROUP BY子句 HA…...
为什么会出现redis数据库?redis是什么?
什么是 Redis? 为什么要用 Redis? 下面我将从 Redis 出现的背景、Redis 的解决方案个来回答。 1、Redis 出现的背景 互联网的应用越来越多,例如社交网络、电商、实时服务发展的十分迅速,这就导致了传统技术栈(如关系型数据库)…...
静态时序分析:SDC约束命令set_ideal_latency详解
相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 当使用set_ideal_network命令将当前设计中的一组端口或引脚标记为理想网络源后,理想属性会沿着组合逻辑进行传播,理想网络中的线网和单元…...
达梦数据库查看字符集编码
select SF_GET_UNICODE_FLAG(); 返回 0 代表数据库字符集编码为 GB18030 1 代表数据库字符集编码为 UTF-8 2 代表数据库字符集编码为韩文字符集 EUC-KR...
LPDDR5x电源使用Si电容对PI和PSIJ影响分析
SoC可能包含许多高速接口,其中LPDDR5X目前因为高带宽、低功耗、大容量等性能优势开始逐渐在AI计算、5G通信、视频处理等领域开始使用。LPDDR5X目前的速率高达8.533 GT/s,以及多个为这些接口供电的IO电压轨,而这些IO轨的PDN需要提供低阻抗&…...
【玩转23种Java设计模式】结构型模式篇:组合模式
软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。 汇总目录链接&…...
Pac-Man(吃豆人) 游戏
目录 前言 1. Pygame游戏开发基础 1.1 Pygame简介 1.2 游戏开发基本概念 1.3 Pygame核心模块介绍 2. 游戏设计与规划 2.1 游戏规则设计 2.2 游戏对象规划 2.3 技术方案选择 3. 创建游戏窗口与初始化 3.1 初始化Pygame环境 3.2 设置游戏窗口 3.3 定义颜色和游戏参数…...
内网安全防护新思路 —— HFish + ELK 与 T-Pot 全面蜜罐系统比较分析
在当前网络安全环境日益复杂的背景下,企业和组织面临着来自外部与内部的多种威胁。为了更好地了解攻击者行为、捕获恶意活动并及时响应,部署蜜罐(Honeypot)系统已成为提升内网安全防护的重要手段。本文将重点介绍两种内网蜜罐防护…...
贪心算法(5)(java)k次取反后最大化的数组和
题目:给定一个整数数组 nums 和一个整数 k,你可以进行最多 k 次取反操作。每次操作可以选择数组中的一个元素并将其取反(即 x 变为 -x)。最终返回经过 k 次取反操作后,数组可能的最大总和。 解法:分情况讨…...
【Spring】@PostConstruct详解
在 Java 开发中,尤其是在基于 Spring 框架的项目里,我们常常会遇到需要在对象创建并完成依赖注入后,执行一些初始化操作的场景。PostConstruct注解正是为解决此类问题而诞生的,它为我们提供了一种便捷且优雅的方式来处理对象的初始…...
OEM SQL Details and Session Details 5s 或者parallel 才会在sql monitor显示
从企业管理器 13.4 版本更新 10 (RU10) 开始,ASH Analytics 的 SQL 详细信息和会话详细信息深入屏幕已更新为使用 Oracle JET UI。 在 Ash Analytics 中,单击左下角区域中“热门 SQL”中的 SQL ID 即可深入了解 SQL 详细信息。 单击右下角“热门会话”区…...
JSAR 基础 1.2.1 基础概念_空间小程序
JSAR 基础 1.2.1 基础概念_空间小程序 空间空间自由度可嵌入空间空间小程序 最新的技术进展表明,官网之前的文档准备废除了,基于xsml的开发将退出历史舞台,three.js和普通web结合的技术将成为主导。所以后续学习请移步three.js学习路径&#…...
Spring Security的作用
一、概述 Spring Security是一个框架,提供认证(authentication)、授权(authorization)和保护,以抵御常见攻击。对 常见漏洞 的保护提供了全面的支持,它对保护命令式和响应式应用程序有一流的支…...
数据结构与算法效率分析:时间复杂度与空间复杂度详解(C语言)
1. 算法效率 1.1 如何衡量一个算法的好坏? 在计算机程序设计中,衡量算法优劣的核心标准是效率。但效率不仅指运行速度,还需要综合以下因素: 时间因素:算法执行所需时间 空间因素:算法运行占用的内存空间…...
数据类设计_图片类设计之4_规则类图形混合算法(前端架构)
前言 学的东西多了,要想办法用出来.C和C是偏向底层的语言,直接与数据打交道.尝试做一些和数据方面相关的内容 引入 接续上一篇,讨论图片类型设计出来后在场景中如何表达,以及图片的混合算法.前面的内容属于铺垫和基础,这篇内容和实际联系起来了. 背景图和前景图 这里笔者想先…...
从零使用docker并安装部署mysql8.3.0容器
在开始使用docker到完成mysql的安装部署,中间有很多的坑等着 安装docker并配置 sudo yum install docker-ce 启动docker并设置开机启动项 sudo systemctl start docker sudo systemctl enable docker查看docker是否启动 sudo systemctl status docker 或者直接…...
【从零开始学习计算机科学】编译原理(二)高级编程语言及其语法描述
【从零开始学习计算机科学】编译原理(二)高级编程语言及其语法描述 高级语言及其语法描述程序语言的定义形式语言与自动机文法的类型语言的类型自动机词法规则语法规则四则运算的语法描述布尔表达式语法描述赋值、分支、循环、程序块语句语法描述数组说明语句过程调用语句语义…...
STM32全系大阅兵(2)
接前一篇文章:STM32全系大阅兵(1) 本文内容参考: STM32家族系列的区别_stm32各个系列区别-CSDN博客 STM32--STM32 微控制器详解-CSDN博客...
cpu 多级缓存L1、L2、L3 与主存关系
现代 CPU 的多级缓存(L1、L2、L3)和主存(DRAM)构成了一个层次化的内存系统,旨在通过减少内存访问延迟和提高数据访问速度来优化计算性能。以下是对多级缓存和主存的详细解析: 1. 缓存层次结构 现代 CPU 通…...
MyBatis 的核心配置文件是干什么的? 它的结构是怎样的? 哪些是必须配置的,哪些是可选的?
MyBatis 的核心配置文件(通常命名为 mybatis-config.xml)是 MyBatis 应用程序的入口点,它定义了 MyBatis 的全局配置信息 。 核心配置文件的作用: 配置 MyBatis 的运行时行为: 通过 <settings> 标签设置全局参数ÿ…...
哪些业务场景更适合用MongoDB?何时比MySQL/PostgreSQL好用?
哪些业务场景更适合用MongoDB?何时比MySQL/PostgreSQL好用? 就像淘宝的个性化推荐需要灵活调整商品标签,MongoDB这种"变形金刚"式的数据库,在处理以下三类中国特色业务场景时更具优势: 一、动态数据就像&q…...
Java学习——day20
文章目录 1. 异常处理与优化1.1 在文件操作中使用 try-catch1.2 try-with-resources 语法1.3 使用 finally 块关闭资源1.4 代码健壮性与优化 2. 实践任务2.1 改进思路2.2 示例改进要点2.3 检查点 3. 总结3.1 改进后的完整代码: 4. 今日生词 今日学习目标:…...
基于Python+SQLite实现校园信息化统计平台
一、项目基本情况 概述 本项目以清华大学为预期用户,作为校内信息化统计平台进行服务,建立网页端和移动端校内信息化统计平台,基于Project_1的需求实现。 本项目能够满足校内学生团体的几类统计需求,如活动报名、实验室招募、多…...
[多线程]基于阻塞队列(Blocking Queue)的生产消费者模型的实现
标题:[多线程]基于阻塞队列(Blocking Queue)的生产消费者模型的实现 水墨不写bug 文章目录 一、生产者消费者模型特点:二、实现2.1详细解释1. 成员变量2. 构造函数3. Isfull 和 Isempty4. Push 函数5. Pop 函数6. 析构函数7. GetSize 函数 三、总结与多线…...
vue组件库el-menu导航菜单设置index,地址不会变更的问题
请先确认 1.路由已配置好 route-index.js如下, 2.view-ProHome.vue中已预留路由展示位 3.导航菜单复制组件库,并做修改 其中index与路由配置的地址一致 运行后发现点击菜单,url地址还是不变,查看组件库 Element - The worlds …...
JavaScript通过文件地址获取文件名称
在 JavaScript 中,可以通过文件链接地址提取文件名称。文件名称通常是链接中最后一个 / 之后的部分,可能还包含查询参数或哈希片段。以下是几种常见的提取文件名称的方法: 方法 1:使用 URL 对象和 pathname URL 对象可以解析链接…...
MySQL 优化方案
一、MySQL 查询过程 MySQL 查询过程是指从客户端发送 SQL 语句到 MySQL 服务器,再到服务器返回结果集的整个过程。这个过程涉及多个组件的协作,包括连接管理、查询解析、优化、执行和结果返回等。 1.1 查询过程的关键组件 连接管理器:管理…...
智能对话小程序功能优化day1-登录鉴权
目录 1.数据库表构建。 2.完善登录相关的实例对象。 3.登录相关功能实现。 4.小程序效果。 最近尝试下trae加入claude3.7后的读图生成代码功能,可以看到简单的页面一次性生成确实准确率高了不少,想起来之前笔记中开发的智能问答小程序功能还是有些简…...
【架构艺术】Go语言微服务monorepo的代码架构设计
近期因为项目架构升级原因,笔者着手调研一些go项目monorepo的代码架构设计,目标是长期把既有微服务项目重要的部分都转移到monorepo上面,让代码更容易维护,协作开发更加方便。虽然经验不多,但既然有了初步的调研&#…...
