当前位置: 首页 > news >正文

Flutter_学习记录_video_player、chewie 播放视频

1. video_player 视频播放

插件地址:https://pub.dev/packages/video_player

  1. 添加插件
    在这里插入图片描述
  2. 导入头文件
import 'package:video_player/video_player.dart';
  1. Android配置(iOS不用配置)

修改这个文件:/android/app/src/main/AndroidManifest.xml;
添加下面的配置:

<uses-permission android:name="android.permission.INTERNET"/>
  1. 添加核心代码

初始化播放器:

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();
  }
  1. 完整代码
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
            );
          }),
      ),
    );
  }
}
  1. 效果图如下:
    在这里插入图片描述

2. chewie 播放视频

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

插件地址:https://pub.dev/packages/chewie

  1. 引入插件
    chewie基于video_player,所以要使用chewie必须配置video_player
    在这里插入图片描述
  2. 导入头文件
import 'package:video_player/video_player.dart';
import 'package:chewie/chewie.dart';
  1. Android配置(iOS不用配置)

修改这个文件:/android/app/src/main/AndroidManifest.xml;
添加下面的配置:

<uses-permission android:name="android.permission.INTERNET"/>
  1. 核心代码
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();
  }
  1. 完整代码
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(),
      ),
    );
  }
}
  1. 效果图:
    在这里插入图片描述

相关文章:

  • Github 2025-03-12 C开源项目日报Top5
  • [洛谷]P1123 取数游戏
  • 文献分享: 对ColBERT段落多向量的剪枝——基于学习的方法
  • 设计模式Python版 模板方法模式(上)
  • Linux:基本指令与内涵理解
  • 初阶数据结构--复杂度
  • 前端发布缓存导致白屏解决方案
  • 解决webdriver和Chrome不匹配的办法
  • 请简述一下String、StringBuffer和“equals”与“==”、“hashCode”的区别和使用场景
  • 解锁数据结构分享图:高效知识传播的关键
  • Kubernetes教程(七)了解集群、标签、Pod和Deployment
  • linux docker 安装dify本地运行,及部署后运行出现502问题
  • Hot 3D 人体姿态估计 HPE Demo复现过程
  • [算法] 判断是否为字符串重排(simple, 面试)
  • 以 ArcGIS Pro 为笔,绘就水墨地图画卷
  • 【Go学习】04-1-Gin框架-路由请求响应参数
  • JVM内存结构笔记03-方法区
  • 计算机网络:计算机网络的分类
  • 重生之我在学Vue--第9天 Vue 3 项目整合
  • postgresql 数据库使用
  • 武汉大学新闻与传播学院已由“80后”副院长吴世文主持工作
  • 王受文已任中华全国工商业联合会领导班子成员
  • 澎湃回声丨23岁小伙“被精神病8年”续:今日将被移出“重精”管理系统
  • 比黄油年糕热量还高,这个火爆全网的甜品劝你慎吃
  • 浙江官宣:五一假期,没电、没气、没油车辆全部免费拖离高速
  • 法院为“外卖骑手”人身权益撑腰:依法认定实际投保人地位