flutter实现视频播放器,可根据指定视频地址播放、设置声音,进度条拖动,下载等

news2024/11/15 7:53:45

需要装依赖:

  gallery_saver: ^2.3.2
  video_player: ^2.8.3

实现代码

import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:gallery_saver/gallery_saver.dart';
import 'package:path_provider/path_provider.dart';
import 'package:video_player/video_player.dart';
import 'package:http/http.dart' as http;

void main() => runApp(const VideoApp());

class VideoApp extends StatefulWidget {
  const VideoApp({super.key});

  @override
  _VideoAppState createState() => _VideoAppState();
}

class _VideoAppState extends State<VideoApp> {
  late VideoPlayerController _controller;
  bool isMuted = false;
  double _currentSliderValue = 0.0;
  Timer? _timer;
  double _playbackSpeed = 1.0;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.networkUrl(Uri.parse(
        '你的播放地址'
    ))
      ..initialize().then((_) {
        setState(() {});
      });
    _controller.setLooping(true);
    _controller.play();

    _timer = Timer.periodic(Duration(seconds: 1), (Timer timer) {
      if (_controller.value.isPlaying) {
        setState(() {
          _currentSliderValue = _controller.value.position.inMilliseconds.toDouble();
        });
      }
    });
  }

  Future<void> downloadAndSaveVideo(String url) async {
    var httpClient = http.Client();
    var response = await httpClient.get(Uri.parse(url));
    var bytes = response.bodyBytes;
    var tempDir = await getTemporaryDirectory();
    var tempFile = File('${tempDir.path}/temp_video.mp4');
    await tempFile.writeAsBytes(bytes);

    final result = await GallerySaver.saveVideo(tempFile.path);
    print('Video saved to gallery: $result,path: ${tempFile.path}');
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Video Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Video Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              _controller.value.isInitialized
                  ? AspectRatio(
                aspectRatio: _controller.value.aspectRatio,
                child: VideoPlayer(_controller),
              )
                  :const  CircularProgressIndicator(),
              const SizedBox(height: 5),
              ElevatedButton(
                onPressed: () {
                  setState(() {
                    isMuted = !isMuted;
                    _controller.setVolume(isMuted ? 0.0 : 1.0);
                  });
                },
                child: Text(isMuted ? '静音模式' : '开启声音模式'),
              ),
              ElevatedButton(
                onPressed: () {
                  setState(() {
                    if (_controller.value.isPlaying) {
                      _controller.pause();
                    } else {
                      _controller.play();
                    }
                  });
                },
                child: Text(_controller.value.isPlaying ? '暂停' : '播放'),
              ),
              Slider(
                value: _currentSliderValue,
                min: 0.0,
                max: _controller.value.duration.inMilliseconds.toDouble(),
                onChanged: (double value) {
                  setState(() {
                    _currentSliderValue = value;
                    _controller.seekTo(Duration(milliseconds: value.toInt()));
                  });
                },
              ),
              const SizedBox(height: 5),
              Text('Playback Speed: ${_playbackSpeed.toStringAsFixed(1)}x'),
              Slider(
                value: _playbackSpeed,
                min: 0.5,
                max: 2.0,
                divisions: 15,
                label: '${_playbackSpeed.toStringAsFixed(1)}x',
                onChanged: (double value) {
                  setState(() {
                    _playbackSpeed = value;
                    _controller.setPlaybackSpeed(_playbackSpeed);
                  });
                },
              ),
              ElevatedButton(
                onPressed: () {
                  downloadAndSaveVideo(_controller.dataSource);
                },
                child: Text('下载'),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
    _timer?.cancel();
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1534921.html

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

相关文章

前端框架推荐 Arco Design

Arco Design - 企业级产品的完整设计和开发解决方案 预览地址&#xff1a;Arco Design Pro - 开箱即用的中台前端/设计解决方案 一 开发 有vue3、React版本。 文档地址&#xff1a;Arco Design - 企业级产品的完整设计和开发解决方案 还配有对应脚手架&#xff1a;GitHub -…

sonarqube使用指北(二)-如何启动一次完整的本地扫描

一、引言 上一篇文章之后 我们应该已经成功的部署了sonarqube程序,这一篇文章我们就来进行一次简单的本地扫描。 优点: 安全性:你可以在任何你信任的环境下执行扫描工作,而不是依赖外部安全能力即时反馈: 开发者可以在编写代码时获得即时反馈,了解其代码的质量和潜在问题…

【Godot4.2】随机数应用案例 - 制作骰子组件

概述 在学习随机数之后&#xff0c;我们就来用随机数实现骰子。 初期&#xff1a;不要拘泥于形式。只要表现了随机&#xff0c;骰子可以不必做成骰子的样子。刚开始因为技术力的原因&#xff0c;可能无法实现比较真实和动态的骰子效果&#xff0c;但是这并不意为着不可以做出…

MATLAB | R2024a更新了哪些好玩的东西?

Hey 好久不见&#xff0c;大家一看三月中下旬这个时间节点也应该能猜到这篇更新什么内容&#xff0c;没错MATLAB R2024a正式版发布啦啦拉拉&#xff0c;直接来看看有啥我认为比较有意思的更新点吧&#xff1a; 1 极坐标表达式绘制 将会使用使用fpolarplot函数来替换ezpolar&a…

探索数据结构:顺序栈与链式栈的原理、实现与应用

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 栈的定义 栈简单来说就是一种只允许在一端进行操作(插入与删除&…

将OpenCV与gdb驱动的IDE结合使用

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV4.9.0开源计算机视觉库在 Linux 中安装 下一篇&#xff1a;将OpenCV与gcc和CMake结合使用 ​ 能力 这个漂亮的打印机可以显示元素类型、、标志is_continuous和is_subm…

【论文阅读】基于多特征融合的智能合约缺陷检测方法

摘要&#xff1a; 1、预处理&#xff1a;颜色标记、词汇提取、字符转换、合约之间的继承关系的提取 2、 使用融合模型进行特征提取&#xff08;BERT、CNN、BiLSTM&#xff09; 3、使用node2vec随机游走算法&#xff0c;将合约之间的继承关系作为输入得到合约关系的特征向量。 4…

通过 Socket 手动实现 HTTP 协议

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

如何让uni-app开发的H5页面顶部原生标题和小程序的顶部标题不一致?

如何让标题1和标题2不一样&#xff1f; 修改根目录下的App.vue&#xff08;核心代码如下&#xff09; <script>export default {onLaunch() {// 监听各种跳转----------------------------------------[navigateTo, redirectTo, reLaunch, switchTab, navigateBack, ].…

[论文笔记] ChatDev:Communicative Agents for Software Development

Communicative Agents for Software Development&#xff08;大模型驱动的全流程自动化软件开发框架&#xff09; 会议arxiv 2023作者Chen Qian Xin Cong Wei Liu Cheng Yang团队Tsinghua University论文地址https://arxiv.org/pdf/2307.07924.pdf代码地址https://github.com/O…

HTML_CSS学习:表格、表单、框架标签

一、表格_跨行与跨列 1.相关代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>表格_跨行与跨列</title> </head> <body><table border"1" cellspacing"0&qu…

(一)基于IDEA的JAVA基础4

注释文本&#xff0c;注释模版 单行注释://开头放在代码前面&#xff0c;对少部分。 多行注释:快捷方式ctrlshift/,对段落代码注 释。 文档注释:/**……**/&#xff0c;用于声明作者或创作时 间。 文档注释如何设置&#xff0c;首先找到File中…

【前端Vue】Vue3+Pinia小兔鲜电商项目第2篇:什么是pinia,1. 创建空Vue项目【附代码文档】

全套笔记资料代码移步&#xff1a; 前往gitee仓库查看 感兴趣的小伙伴可以自取哦&#xff0c;欢迎大家点赞转发~ 全套教程部分目录&#xff1a; 部分文件图片&#xff1a; 什么是pinia Pinia 是 Vue 的专属状态管理库&#xff0c;可以实现跨组件或页面共享状态&#xff0c;是…

html5cssjs代码 033 SVG元素示例

html5&css&js代码 033 SVG元素示例 一、代码二、解释 一个SVG图形&#xff0c;该图形由一个椭圆、一个圆形和一个矩形组成。 一、代码 <!DOCTYPE html> <html lang"zh-cn"> <head><title>编程笔记 html5&css&js SVG元素示例…

公司系统中了.rmallox勒索病毒如何恢复数据?

早晨上班时刻&#xff1a; 当阳光逐渐洒满大地&#xff0c;城市的喧嚣开始涌动&#xff0c;某公司的员工们纷纷踏入办公大楼&#xff0c;准备开始新的一天的工作。他们像往常一样打开电脑&#xff0c;准备接收邮件、查看日程、浏览项目进展。 病毒悄然发作&#xff1a; 就在员…

Databend x CubeFS:面向未来的企业级云原生数据存储与分析

用场景的丰富&#xff0c;企业面临着前所未有的数据存储挑战。大规模数据存储变得日常化&#xff0c;伴随着超大容量和快速变化的I/O需求&#xff0c;传统的存储解决方案已经难以满足企业对弹性、运维效率及总体拥有成本&#xff08;TCO&#xff09;的更高要求。这些挑战促使基…

三角形重心坐标插值法 Interpolation Across Triangles: Barycentric Coordinates

本专栏内容整理了GAMES101的计算机图形学课程的主要内容&#xff0c;作为我学习计算机图形学的一份复习备份或叫做笔记。内容中如有错误&#xff0c;或有其他建议&#xff0c;欢迎大家指出。 附上GAMES101计算机图形学课程&#xff1a;GAMES101: 现代计算机图形学入门正在上传…

Django日志(二)

一、Handler Handler决定如何处理logger中的每条消息。它表示一个特定的日志行为,例如 将消息写入屏幕、文件或网络Socket handler对应的是个字典,每一个键都是一个handler的名字,每个值又一个字典,描述了如何配置对应的handler实例 2.1、内置Handler class(必需):处理…

【每日八股】Java基础经典面试题4

前言&#xff1a;哈喽大家好&#xff0c;我是黑洞晓威&#xff0c;25届毕业生&#xff0c;正在为即将到来的秋招做准备。本篇将记录学习过程中经常出现的知识点以及自己学习薄弱的地方进行总结&#x1f970;。 本篇文章记录的Java基础面试题&#xff0c;如果你也在复习的话不妨…

Scikit-Learn逻辑回归(二)

Scikit-Learn逻辑回归二&#xff1a;多项式与正则化 1、多项式回归回顾1.1、逻辑回归为什么要使用多项式1.2、多项式回归及原理 2、逻辑回归与多项式 1、多项式回归回顾 本文接上篇&#xff1a;Scikit-Learn逻辑回归(一) 上篇中&#xff0c;我们详细介绍了逻辑回归的概念、原理…