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

需要装依赖:

  gallery_saver: ^2.3.2
  video_player: ^2.8.3

AndroidManifest.xml

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

实现代码

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();
  }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入理解栈和队列(二):队列

个人主页&#xff1a;17_Kevin-CSDN博客 专栏&#xff1a;《数据结构》 一、队列的概念和结构 队列是只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出 FIFO(First In First Out) 入队列&#xff1a;进行插入操作的…

OC对象 - 关联对象(如何给分类添加成员变量)

文章目录 OC对象 - 关联对象&#xff08;如何给分类添加成员变量&#xff09;1. 基本使用1.1 提供的API1.1.1 添加关联对象1.1.2 获得关联对象1.1.3 移除所有关联对象1.1.3 修饰符 1.2 使用方法1.2 Key的常见用法1.2.1 使用的get方法的selecor作为key1.2.2 使用指针的地址作为k…

【Node.js】zlib

gzip 和 deflate 的基本使用 const zlib require("zlib"); const fs require(fs)// 压缩 1. createGzip .gz 2. createDeflate .deflate // const readStream fs.createReadStream(index.txt) // const writeStream fs.createWriteStream(index.txt.gz) // rea…

Python Flask 自定义404错误

from flask import Flask, abort, make_response, request, render_templateapp Flask(__name__)# 重定向到百度 app.route(/index, methods["GET", "POST"]) def index():if request.method "GET":return render_template("index.html&q…

Python Flask 自定义过滤器

{{ data.list | li2 }} li2就是自定义的 from flask import Flask, render_templateapp Flask(__name__)app.route("/index") def index():data {name: "张三","age": 18,list: [123123, 41, 123]}return render_template("index2.html…

nodejs+vue高校二手商品交易平台的设计与实现python-flask-django-php

当今社会已经步入了科学技术进步和经济社会快速发展的新时期&#xff0c;国际信息和学术交流也不断加强&#xff0c;计算机技术对经济社会发展和人民生活改善的影响也日益突出&#xff0c;人类的生存和思考方式也产生了变化。传统高校二手商品交易采取了人工的管理方法&#xf…

BUG未解之谜01-指针引用之谜

在leetcode里面刷题出现的问题&#xff0c;当我在sortedArrayToBST里面给root赋予初始值NULL之后&#xff0c;问题得到解决&#xff01; 理论上root是未初始化的变量&#xff0c;然后我进入insert函数之后&#xff0c;root引用的内容也是未知值&#xff0c;因此无法给原来的二叉…

array go 语言的数组 /切片

内存地址通过& package mainimport "fmt"func main() {var arr [2][3]int16fmt.Println(arr)fmt.Printf("arr的地址是: %p \n", &arr)fmt.Printf("arr[0]的地址是 %p \n", &arr[0])fmt.Printf("arr[0][0]的地址是 %p \n"…

【Linux 09】进程优先级

文章目录 &#x1f308; Ⅰ 什么是优先级&#x1f308; Ⅱ 为什么存在优先级&#x1f308; Ⅲ 查看进程优先级&#x1f308; Ⅳ 修改进程优先级 &#x1f308; Ⅰ 什么是优先级 优先级本质 指定进程获取某种资源的先后顺序。在 Linux 中&#xff0c;使用 task_struct 进程控制…

电子电器架构 —— 诊断数据DTC具体故障

电子电器架构 —— 诊断数据DTC具体故障 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师 (Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,喝完再挣…

【CDA二级数据分析备考思维导图】

CDA二级数据分析备考思维导图 CDA二级复习备考资料共计七个章节&#xff0c;如需资料&#xff0c;请留言&#xff0c;概览如下图&#xff1a;一、数据采集与处理1.数据采集方法2.市场调研和数据录入3、数据探索与可视化4、数据预处理方法 总结&#xff1a;以上为自己学习数据分…

现代化应用部署工具-Docker

Docker 简介 什么是Docker Docker 是一个开源的应用容器引擎&#xff0c;可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上。 Docker部署的优势 通过使用Docker等容器技术&#xff0c;可以将应用程序及其依赖项…

R-Linux 免费ext2 / 3 / 4文件系统恢复软件简介(推荐)

R-Linux&#xff1a;只适合 3种类型的发行版使用。 R-Linux 免费ext2 / 3 / 4文件系统恢复软件简介&#xff08;推荐&#xff09; https://blog.csdn.net/allway2/article/details/102632495 R-Linux for Linux Technical Documentation https://www.r-studio.com/free-linux…

【docker常用命令】

1. 什么是docker Docker 是一种开源的容器化平台&#xff0c;用于开发、交付和运行应用程序。它允许开发人员将应用程序及其依赖项&#xff08;如库、环境变量、配置文件等&#xff09;打包到一个被称为容器的标准化单元中。这个容器包含了一切应用程序需要运行的所有内容&…

漫画之家”系统设计与实现|SpringBoot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;…

nodejs+vue高校工作室管理系统python-flask-django-php

系统根据现有的管理模块进行开发和扩展&#xff0c;采用面向对象的开发的思想和结构化的开发方法对高校工作室管理的现状进行系统调查。采用结构化的分析设计&#xff0c;该方法要求结合一定的图表&#xff0c;在模块化的基础上进行系统的开发工作。在设计中采用“自下而上”的…

OpenCV4.9.0开源计算机视觉库核心功能(核心模块)

转到&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV 介绍使用 下一篇&#xff1a;如何使用OpenCV扫描图像、查找表和时间测量 ​ OpenCV核心功能主要有以下各个&#xff1a;本文将开始介绍下列内容&#xff1a; Mat - 基…

ubuntu18安装opensips3.4,开启ws/wss/http接口模块

、如果是centos 7安装则使用yum 命令。 添加库地址注意系统类型&#xff0c;选择对应的系统类型和版本 curl https://apt.opensips.org/opensips-org.gpg -o /usr/share/keyrings/opensips-org.gpg echo "deb [signed-by/usr/share/keyrings/opensips-org.gpg] https:/…

client-go中ListAndWatch机制,informer源码详解

文章首发地址&#xff1a; 学一下 (suxueit.com)https://suxueit.com/article_detail/s9UMb44BWZdDRfKqFv22 先上一张&#xff0c;不知道是那个大佬画的图 简单描述一下流程 client-go封装部分 以pod为例 、先List所有的Pod资源&#xff0c;然后通过已经获取的pod资源的最大版…

nodejs+vue高校社团管理系统设计与实现python-flask-django-php

系统根据现有的管理模块进行开发和扩展&#xff0c;采用面向对象的开发的思想和结构化的开发方法对高校社团的现状进行系统调查。采用结构化的分析设计&#xff0c;该方法要求结合一定的图表&#xff0c;在模块化的基础上进行系统的开发工作。在设计中采用“自下而上”的思想&a…