flutter开发实战-video_player视频播放功能及视频缓存

news/2025/3/14 18:22:02/

flutter开发实战-video_player视频播放功能及视频缓存

最近开发过程中video_player播放视频,
在这里插入图片描述
在这里插入图片描述

一、引入video_player

在pubspec.yaml引入video_player

  video_player: ^2.7.0

在iOS上,video_player使用的是AVPlayer进行播放。
在Android上,video_player使用的是ExoPlayer。

二、使用前设置

2.1 在iOS中的设置

在iOS工程中info.plist添加一下设置,以便支持Https,HTTP的视频地址

<key>NSAppTransportSecurity</key>
<dict><key>NSAllowsArbitraryLoads</key><true/>
</dict>

2.2 在Android中的设置

需要在/android/app/src/main/AndroidManifest.xml文件中添加网络权限

<uses-permission android:name="android.permission.INTERNET"/>

三、使用前设置video_player

video_player 使用VideoPlayerController来控制播放与暂停

VideoPlayerController的初始化

_controller = VideoPlayerController.networkUrl(Uri.parse('https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'))..initialize().then((_) {// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.setState(() {});});

显示视频Widget

Center(child: _controller.value.isInitialized? AspectRatio(aspectRatio: _controller.value.aspectRatio,child: VideoPlayer(_controller),): Container(),),

控制播放与暂停

// 播放
_controller.play();
// 暂停
_controller.pause();

完整实例代码

import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';void main() => runApp(const VideoApp());/// Stateful widget to fetch and then display video content.
class VideoApp extends StatefulWidget {const VideoApp({super.key});_VideoAppState createState() => _VideoAppState();
}class _VideoAppState extends State<VideoApp> {late VideoPlayerController _controller;void initState() {super.initState();_controller = VideoPlayerController.networkUrl(Uri.parse('https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'))..initialize().then((_) {// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.setState(() {});});}Widget build(BuildContext context) {return MaterialApp(title: 'Video Demo',home: Scaffold(body: Center(child: _controller.value.isInitialized? AspectRatio(aspectRatio: _controller.value.aspectRatio,child: VideoPlayer(_controller),): Container(),),floatingActionButton: FloatingActionButton(onPressed: () {setState(() {_controller.value.isPlaying? _controller.pause(): _controller.play();});},child: Icon(_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,),),),);}void dispose() {super.dispose();_controller.dispose();}
}

注意:video_player暂时不支持缓存,如果需要可以使用flutter_cache_manager

四 缓存flutter_cache_manager下载文件

使用flutter_cache_manager代码如下

import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'dart:async';
import 'dart:typed_data';
import 'package:file/file.dart';
import 'package:flutter_suprisebox/utils/string_utils.dart';class CustomCacheManager {static const key = 'customCacheKey';static CacheManager instance = CacheManager(Config(key,stalePeriod: const Duration(days: 7),maxNrOfCacheObjects: 20,repo: JsonCacheInfoRepository(databaseName: key),fileService: HttpFileService(),),);Future<File> getSingleFile(String url, {String? key,Map<String, String>? headers,}) async {return await instance.getSingleFile(url, key: key, headers: headers);}Future<FileInfo?> getFileFromCache(String url,{bool ignoreMemCache = false}) async {String? key = StringUtils.toMD5(url);if (key != null && key.isNotEmpty) {return await instance.getFileFromCache(key, ignoreMemCache: ignoreMemCache);}return null;}Future<FileInfo> downloadFile(String url,{String? key,Map<String, String>? authHeaders,bool force = false}) async {return await instance.downloadFile(url, key: key, authHeaders: authHeaders, force: force);}Stream<FileResponse> getFileStream(String url,{String? key, Map<String, String>? headers, bool withProgress = false}) {return instance.getFileStream(url,key: key, headers: headers, withProgress: withProgress);}Future<void> removeFile(String key) async {return instance.removeFile(key);}/// Removes all files from the cacheFuture<void> emptyCache() {return instance.emptyCache();}
}

添加flutter_cache_manager后,flutter_cache_manager会先判断文件是否存在,如果不存在则下载视频文件。

使用CustomCacheManager后的视频初始化代码如下

Future<void> stuVideoPlay() async {_controller?.dispose();if (Platform.isIOS) {_controller = VideoPlayerController.network(widget.videoUrl);} else {FileInfo? fileInfo =await CustomCacheManager().getFileFromCache(widget.videoUrl);if (fileInfo == null) {fileInfo = await CustomCacheManager().downloadFile(widget.videoUrl);// if (fileInfo != null) {_controller = VideoPlayerController.file(fileInfo.file);// } else {//   _controller = VideoPlayerController.network(widget.videoUrl);// }} else {var file = await CustomCacheManager().getSingleFile(widget.videoUrl);_controller = VideoPlayerController.file(file);}}await _controller?.initialize().then((_) {// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.setState(() {});});await _controller!.setLooping(true);if (widget.autoPlay) {await _controller?.play();} else {await _controller?.pause();}}

特别注意:我使用的时候,flutter_cache_manager好像暂时不支持iOS。这点可能还需要其他方案来做缓存处理。如果支持了请留言哦,也可能我记错了。

四、小结

flutter开发实战-video_player视频播放功能及视频缓存。video_player播放视频,flutter_cache_manager处理视频缓存。

学习记录,每天不停进步。


http://www.ppmy.cn/news/1016170.html

相关文章

学习Pull request

我从我的导师Xing Fan指导和帮助&#xff0c;利用我的导师chunlong Li提供ChatGPT&#xff0c;在百度搜索&#xff0c;学习一些资料。以下很多内容都是我的导师Xing Fan做的。谢谢Xing Fan。考虑到隐私&#xff0c;不适合截图公开。 第一步&#xff1a; 打开Git Bash Here 如…

linux安装C++ opencv

1. 安装依赖 opencv中的一些图像、视频相关的功能需要一些依赖&#xff0c;因此在安装opencv之前需要先安装这些依赖&#xff1b;在使用apt安装相关依赖时&#xff0c;会出现无法安装的情况&#xff0c;这时可以用aptitude来降级安装。 名称apt package 名称功能编译系统buil…

ffmpeg源码编译成功,但是引用生成的静态库(.a)报错,报错位置在xxx_list.c,报错信息为某变量未定义

背景&#xff1a;本文是对上一个文章的补充&#xff0c;在源码编译之前&#xff0c;项目是有完整的ffmpeg编译脚本的&#xff0c;只不过新增了断点调试ffmpeg&#xff0c;所以产生的上面的文章&#xff0c;也就是说&#xff0c;我在用make编译成功后&#xff0c;再去做的源码编…

代码分析Java中的BIO与NIO

开发环境 OS&#xff1a;Win10&#xff08;需要开启telnet服务&#xff0c;或使用第三方远程工具&#xff09; Java版本&#xff1a;8 BIO 概念 BIO(Block IO)&#xff0c;即同步阻塞IO&#xff0c;特点为当客户端发起请求后&#xff0c;在服务端未处理完该请求之前&#xff…

CC++内存管理与模版初阶

目录 四、C&C内存管理 (一)C/C内存分布 (二)C内存管理方式 1、new/delete操作内置类型 2、new和delete操作自定义类型 (三)operator new与operator delete函数 (四)new和delete的实现原理 1、内置类型 2、自定义类型 (五)定位new表达式(placement-new) (六)八股文 1、n…

Vue3 动态列 <el-table-column> 实现 formatter 的两种方法

文章目录 动态列实现动态列实现formatter第一种第二种方法 动态列实现 参考此篇文章 Vue3 动态列实现 动态列实现formatter 第一种 以此为例&#xff1a;传递该行的wxUserInfo字段&#xff08;对象&#xff09;中的nickName 假设该行 {prop: "wxUserInfo", label: …

8月8日上课内容 研究nginx组件rewrite

location 匹配uri location 匹配的规则和优先级。&#xff08;重点&#xff0c;面试会问&#xff0c;必须理解和掌握&#xff09; nginx常用的变量&#xff0c;这个要求掌握 rewrite&#xff1a;重定向功能。有需要掌握&#xff0c;有需要理解的。 location匹配&#xff1a;…

leetcode2809. 使数组和小于等于 x 的最少时间 排序+0-1背包

https://leetcode.cn/problems/minimum-time-to-make-array-sum-at-most-x/ 给你两个长度相等下标从 0 开始的整数数组 nums1 和 nums2 。每一秒&#xff0c;对于所有下标 0 < i < nums1.length &#xff0c;nums1[i] 的值都增加 nums2[i] 。操作 完成后 &#xff0c;你…