Flutter视频播放插件flutter_alpha_player_plugin的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter视频播放插件flutter_alpha_player_plugin的使用

一个可以播放透明通道视频的播放器,基于AlphaPlayer改造成plugin插件,适用于Android和iOS平台,支持文件播放。

AlphaPlayer

AlphaPlayer是直播中台使用的一个视频动画特效SDK,可以通过制作Alpha通道分离的视频素材,再在客户端上通过OpenGL ES重新实现Alpha通道和RGB通道的混合,从而实现在端上播放带透明通道的视频。

方案对比

目前较常见的动画实现方案有原生动画、帧动画、gif/webp、lottie/SVGA、cocos引擎,对于复杂动画特效的实现做个简单对比:

方案 实现成本 还原程度 接入成本
原生动画 复杂动画实现成本高 中等
帧动画 实现成本低,但资源消耗大 中等
gif/webp 实现成本低,但资源消耗大 只支持8位颜色
Lottie/SVGA 实现成本低,部分复杂特效不支持 部分复杂特效不支持
cocos2d引擎 实现成本高 较高 较高
AlphaPlayer 开发无任何实现成本,一次接入永久使用

优势

相比于上面提到的几个方案,AlphaPlayer的接入体积极小(只有40KB左右),而且对动画资源的还原程度极高,资源制作时不用考虑特效是否支持的问题,对开发者和设计师都非常友好。通过接入ExoPlayer或者自研播放器可以解决系统播放器在部分机型上可能存在的兼容性问题,且能带来更好的解码性能。

运行效果

运行效果

基本原理

主要有两个核心,一个是IMediaPlayer,负责视频解码,支持外部自行实现;另一个是VideoRenderer,负责将解析出来的每一帧画面进行透明度混合,再输出到GLTextureView或者GLSurfaceView上。

大致的混合过程可以看下图示例: 基本原理图 原素材的画面中左边部分使用RGB通道存储了原透明视频的Alpha值,右边部分使用RGB通道存储了原透明视频的RGB值,然后在端上通过OpenGL重新将每个像素点的Alpha值和RGB值进行组合,重新得到ARGB视频画面,实现透明视频的动画效果。

快速接入

添加依赖:

flutter_alpha_player_plugin: ^1.0.5

或者执行:

flutter pub add flutter_alpha_player_plugin

使用方式

[@override](/user/override)
void initState() {
  super.initState();
  /// 注册监听器
  AlphaPlayerController.setAlphaPlayerCallBack(
    /// 播放结束回调
    endAction: () {

    },
    /// 播放开始回调
    startAction: () {

    },
    /// 播放器监听
    monitorCallbacks: (expand) {

    },
    /// 视频尺寸变化回调
    onVideoSizeChanged: (expand) {

    },
    /// 扩展回调
    platformCallback: (ex) {
      log("message $ex");
    },
  );
}

.....

const IgnorePointer(
  /// 添加透明视频布局,添加到合适的位置
  child: AlphaPlayerView(),
),

/// 播放视频
/// [path] 文件存放路径
/// [fileName] 路径下面的源文件
/// [isLooping] 是否循环 默认false 
/// [portraitPath] 竖向, 默认2
/// [landscapePath] 横向, 默认8
///                  ScaleToFill(0),             //  拉伸铺满全屏
///                  ScaleAspectFitCenter(1),    //  等比例缩放对齐全屏,居中,屏幕多余留空
///                  ScaleAspectFill(2),         //  等比例缩放铺满全屏,裁剪视频多余部分
///                  TopFill(3),                 //  等比例缩放铺满全屏,顶部对齐
///                  BottomFill(4),              //  等比例缩放铺满全屏,底部对齐
///                  LeftFill(5),                //  等比例缩放铺满全屏,左边对齐
///                  RightFill(6),               //  等比例缩放铺满全屏,右边对齐
///                  TopFit(7),                  //  等比例缩放至屏幕宽度,顶部对齐,底部留空
///                  BottomFit(8),               //  等比例缩放至屏幕宽度,底部对齐,顶部留空
///                  LeftFit(9),                 //  等比例缩放至屏幕高度,左边对齐,右边留空
///                  RightFit(10);               //  等比例缩放至屏幕高度,右边对齐,左边留空
var result = await AlphaPlayerController.playVideo(dir.path, "1.mp4",portraitPath: 1, landscapePath: 8);

/// 添加视图
AlphaPlayerController.attachView();

/// 移除视图
AlphaPlayerController.detachView();

/// 释放播放器
AlphaPlayerController.releasePlayer();

示例代码

import 'dart:log';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_alpha_player_plugin/alpha_player_controller.dart';
import 'package:flutter_alpha_player_plugin/alpha_player_view.dart';

import 'package:oktoast/oktoast.dart';
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(const MyApp());
}

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

  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> downloadPathList = [];
  bool isDownload = false;

  [@override](/user/override)
  void initState() {
    super.initState();
    AlphaPlayerController.setAlphaPlayerCallBack(
      endAction: () {},
      startAction: () {},
      monitorCallbacks: (expand) {},
      onVideoSizeChanged: (expand) {},
      platformCallback: (ex) {
        log("message $ex");
      },
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return OKToast(
      child: MaterialApp(
        home: Scaffold(
          body: SizedBox(
            width: double.infinity,
            height: double.infinity,
            child: Stack(
              alignment: Alignment.center,
              children: [
                Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    CupertinoButton(
                      color: Colors.purple,
                      child: Text("播放demo_play.mp4"),
                      onPressed: () async {
                        if (Platform.isAndroid) {
                          /// 安卓路径读取方式
                          var dir = await getExternalStorageDirectory();
                          log("-------------${dir?.path}-&gt;");
                          Directory(dir!.path).create(recursive: true);

                          var result = await AlphaPlayerController.playVideo(
                              dir.path, "1.mp4",
                              portraitPath: 1, landscapePath: 8);
                        } else if (Platform.isIOS) {
                          /// iOS 路径读取方式
                          var dir = await getLibraryDirectory();
                          var library = dir.path;

                          /// 此路径为自己调试的沙盒存储路径,开发者可根据自己的文件存储路径进行相应替换,完整路径应该为($library/自定义文件夹/x/x.mp4)
                          var filePath = "$library/ttyy/1";
                          var result = await AlphaPlayerController.playVideo(
                              filePath, "1.mp4",
                              portraitPath: 2, landscapePath: 8);
                        }
                      },
                    ),
                    CupertinoButton(
                      color: Colors.purple,
                      child: Text("播放assets demo1.mp4"),
                      onPressed: () {
                        if (Platform.isAndroid) {
                          /// 安卓路径读取方式
                          AlphaPlayerController.playVideo(
                              "/assets/", "demo.mp4");
                        } else if (Platform.isIOS) {
                          /// iOS 路径读取方式
                          /// iOS 由于基于字节播放器的二次封装,内部需要解析config.json 文件来读取资源,所以,视频同级目录内都要有一个对应的config.json文件
                          /// assets 文件夹,也可替换为自定义的文件夹
                          AlphaPlayerController.playAssetVideo(
                              "assets", "demo1.mp4");
                        }
                      },
                    ),
                    CupertinoButton(
                      color: Colors.purple,
                      child: Text("attachView"),
                      onPressed: () {
                        AlphaPlayerController.attachView();
                      },
                    ),
                    CupertinoButton(
                      color: Colors.purple,
                      child: Text("detachView"),
                      onPressed: () {
                        AlphaPlayerController.detachView();
                      },
                    ),
                    CupertinoButton(
                      color: Colors.purple,
                      child: Text("releasePlayer"),
                      onPressed: () {
                        AlphaPlayerController.releasePlayer();
                      },
                    ),
                  ],
                ),
                const IgnorePointer(
                  child: AlphaPlayerView(),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter视频播放插件flutter_alpha_player_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter视频播放插件flutter_alpha_player_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用 flutter_alpha_player_plugin 进行视频播放的示例代码。这个插件提供了一些高级的视频播放功能,以下是一个基本的实现示例。

首先,确保你已经在 pubspec.yaml 文件中添加了依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_alpha_player_plugin: ^最新版本号  # 请替换为实际的最新版本号

然后运行 flutter pub get 来获取依赖。

接下来,在你的 Flutter 项目中实现视频播放功能。以下是一个完整的示例:

import 'package:flutter/material.dart';
import 'package:flutter_alpha_player_plugin/flutter_alpha_player_plugin.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Video Player Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: VideoPlayerScreen(),
    );
  }
}

class VideoPlayerScreen extends StatefulWidget {
  @override
  _VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}

class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  AlphaPlayerController? _controller;

  @override
  void initState() {
    super.initState();
    // 初始化视频控制器
    _controller = AlphaPlayerController.network(
      'https://www.example.com/path/to/your/video.mp4',  // 替换为你的视频URL
      autoPlay: true,
      looping: false,
    )
      ..initialize().then((_) {
        // 初始化完成后可以执行一些操作,比如设置监听器
        _controller!.addListener(() {
          setState(() {});
        });
      });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Video Player Demo'),
      ),
      body: Center(
        child: _controller!.value.isInitialized
            ? AspectRatio(
                aspectRatio: _controller!.value.aspectRatio,
                child: AlphaPlayer(
                  controller: _controller!,
                ),
              )
            : Container(
                child: CircularProgressIndicator(),
              ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _controller!.value.isPlaying
                ? _controller!.pause()
                : _controller!.play();
          });
        },
        tooltip: 'Play/Pause',
        child: Icon(
          _controller!.value.isPlaying ? Icons.pause : Icons.play_arrow,
        ),
      ),
    );
  }
}

代码解释

  1. 依赖添加:在 pubspec.yaml 文件中添加 flutter_alpha_player_plugin 依赖。
  2. 初始化控制器:在 initState 方法中初始化 AlphaPlayerController,这里使用的是网络视频 URL。你可以根据需要设置为本地视频或其他配置。
  3. 监听器:在控制器初始化完成后,添加一个监听器来更新 UI。
  4. UI 构建:在 build 方法中,根据视频是否初始化完成来显示不同的内容。如果视频已初始化,显示 AlphaPlayer 组件;否则显示加载指示器。
  5. 播放/暂停控制:使用 FloatingActionButton 来控制视频的播放和暂停。

确保你替换了示例中的视频 URL 为你自己的视频 URL。这个示例展示了如何使用 flutter_alpha_player_plugin 进行基本的视频播放和控制。如果需要更多高级功能,请参考插件的官方文档。

回到顶部