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

news2024/12/22 19:05:59

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 cache
  Future<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.coloradmin.cn/o/850595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python中文官网下载安装,python官方中文文档下载

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python官网下载步骤图解&#xff0c;python官方中文文档下载&#xff0c;现在让我们一起来看看吧&#xff01; python官网网址 python官方网站 python官网网址中文。像我们想要抓住一门好的编程语言&#xff0c;如何开始…

Yolov5缺陷检测/目标检测 Jetson nx部署Triton server

使用AI目标检测进行缺陷检测时&#xff0c;部署到Jetson上即小巧算力还高&#xff0c;将训练好的模型转为tensorRT再部署到Jetson 上供http或GRPC调用。1 Jetson nx 刷机 找个ubuntu 系统NVIDIA官网下载安装Jetson 的sdkmanager一步步刷机即可。 本文刷的是JetPack 5.1, 其中包…

PS透明屏,在科技展示中,有哪些优点展示?

PS透明屏是一种新型的显示技术&#xff0c;它将传统的显示屏幕与透明材料相结合&#xff0c;使得屏幕能够同时显示图像和透过屏幕看到背后的物体。 这种技术在商业展示、广告宣传、产品展示等领域有着广泛的应用前景。 PS透明屏的工作原理是利用透明材料的特性&#xff0c;通…

(树) 剑指 Offer 36. 二叉搜索树与双向链表 ——【Leetcode每日一题】

❓ 剑指 Offer 36. 二叉搜索树与双向链表 难度&#xff1a;中等 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个 排序的循环双向链表。要求不能创建任何新的节点&#xff0c;只能调整树中节点指针的指向。 为了让您更好地理解问题&#xff0c;以下面的二叉搜索树为…

python+vue生成条形码码并展示

需求 最近想做一个小工具&#xff0c;大概要实现这样的效果&#xff1a;后端生成条形码后&#xff0c;不保存到服务器&#xff0c;直接返回给前端展示。 大概思路是&#xff0c;通过 python-barcode库 生成条码的字节流&#xff0c;生成字节流后直接编码成base64格式返回给前…

关于Vue构建低代码平台的思考

一、前言 在项目实战开发中&#xff0c;尤其是大平台系统的搭建&#xff0c;针对不同业务场景&#xff0c;需要为用户多次编写用于录入、修改、展示操作的相应表单页面。一旦表单需求过多&#xff0c;对于开发人员来说&#xff0c;算是一种重复开发&#xff0c;甚至是繁杂的工作…

国产语音芯片里面可重复擦写语音芯片有哪些?可以在线烧写语音

目录 详细测试 主要是做一个测试板&#xff0c;对KT148A一线通讯的芯片进行测试和验证&#xff0c;实现的功能有两点。 2.1 第一步--硬件环境的搭建 2.2 第二步--自己更换声音的测试 三、总结 简介 基本目前的语音芯片&#xff0c;尤其是SOP8的封装类型的芯片&#xff0c;都绕…

网络安全---正则回溯

目录 一、题目引入 二、举出回溯例子进行分析 第一步&#xff1a; 正则往前匹配 第二步&#xff1a;匹配到头 第三步&#xff1a;往回匹配 第四步&#xff1a;直到分号结束 &#xff08;匹配上&#xff09; 原因&#xff1a; 三、进入正题一&#xff08;分析题型&#x…

【MOOC】北京理工大学Python网络爬虫与信息提取慕课答案-综合挑出了一些很难评的慕课测验题

1 Requests库中的get()方法最常用&#xff0c;下面哪个说法正确&#xff1f;‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬…

解决 Android Studio 的 Gradle 面板上只有关于测试的 task 的问题

文章目录 问题描述解决办法 笔者出问题时的运行环境&#xff1a; Android Studio Flamingo | 2022.2.1 Android SDK 33 Gradle 8.0.1 JDK 17 问题描述 笔者最近发现一个奇怪的事情。笔者的 Android Studio 的 Gradle 面板上居然除了用于测试的 task 之外&#xff0c;其它什…

【架构设计】如何设计一个高性能短链系统

一、前言 所谓系统设计&#xff0c;就是给一个场景&#xff0c;让你给出对应的架构设计&#xff0c;需要考虑哪些问题&#xff0c;采用什么方案解决。很多面试官喜欢出这么一道题来考验你的知识广度和逻辑思考能力。 虽然各个系统千差万别&#xff0c;但是设计思想基本一致&a…

sql刷题

文章目录 section A1 各部门工资最高的员工&#xff08;难度&#xff1a;中等&#xff09;2 换座位&#xff08;难度&#xff1a;中等&#xff09;3 分数排名&#xff08;难度&#xff1a;中等&#xff09;4 连续出现的数字&#xff08;难度&#xff1a;中等&#xff09;5 树节…

leetcode每日一练-第70题-爬楼梯

一、思路 动态规划 二、解题方法 使用一个动态规划数组 dp 来记录到达每个台阶的不同方法数。初始情况下&#xff0c;当台阶数为 1 时&#xff0c;方法数为 1&#xff0c;当台阶数为 2 时&#xff0c;方法数为 2。然后&#xff0c;我们从第 3 阶开始逐步计算每一阶的方法数&…

剑指Offer12.矩阵中的路径 C++

1、题目描述 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平…

vue去掉所有输入框两边空格,封装指令去空格,支持Vue2和Vue3,ElementUI Input去空格

需求背景 就是页面很多表单输入框&#xff0c;期望在提交的时候&#xff0c;都要把用户两边的空格去掉 ❌使用 vue 的指令 .trim 去掉空格 中间会输入不了空格&#xff0c; 比如我想输入 你好啊 中国, 这中间的空格输入不了&#xff0c;只能变成 你好啊中国 ❌在提交的时候使用…

[HDLBits] Exams/m2014 q4i

Implement the following circuit: module top_module (output out);assign out1b0; endmodule

适配器模式来啦

网上的大多数的资料中适配器模式和代理模式都是紧挨着进行介绍的&#xff0c;为什么呢&#xff1f;&#xff1f;&#xff1f; 是因为适配器模式和代理模式有太多的相似之处&#xff0c;可以进行联动记忆但是也要做好区分。 在菜鸟教程中&#xff0c;适配器模式的定义是作为两…

Intellij IDEA 导入 eclipse web 项目详细操作

Eclipse当中的web项目都会有这两个文件。但是idea当中应该是没有的&#xff0c;所以导入会出现兼容问题。但是本篇文章会教大家如何导入&#xff0c;并且导入过后还能使用tomcat运行。文章尽可能以图片的形式进行演示。我的idea使用的版本是2022.3.3版本。当然按正常来说版本之…

Flink源码之RPC

Flink是一个典型的Master/Slave分布式实时处理系统&#xff0c;分布式系统组件之间必然涉及通信&#xff0c;也即RPC&#xff0c;以下图展示Flink组件之间的关系&#xff1a; RPCGateWay 一般RPC框架可根据用户业务类生成客户端和服务器端通信底层代码&#xff0c;此时只需定…

基于Dlib库+SVM+Tensorflow+PyQT5智能面相分析-机器学习算法应用(含全部工程源码)+训练及测试数据集

目录 前言总体设计系统整体结构图系统流程图模型流程 运行环境Python 环境TensorFlow环境界面编程环境 模块实现1. 数据预处理2. 模型构建1&#xff09;定义模型结构2&#xff09;交叉验证模型优化 3. 模型训练及保存4. 模型测试1&#xff09;摄像头调用2&#xff09;模型导入及…