Flutter视频播放插件fplayer的使用

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

Flutter视频播放插件fplayer的使用

fplayer 是一个基于 fplayer-core 的 Flutter 媒体播放器插件,适用于 iOS 和 Android 平台。

您的支持是我们开发的动力。 欢迎 Star,欢迎 PR~。 反馈欢迎并 Pull Requests 最受欢迎!

文档

开发文档 包含首页、入门指南、基础、内核、fplayer 中的概念理解:

安装

pubspec.yaml 文件中添加 fplayer 作为依赖项:

dependencies:
  fplayer: ^{{latest version}}

替换 {{latest version}} 为上面 badge 中显示的版本号。

如果需要使用未发布的 git 分支:

dependencies:
  fplayer:
    git:
      url: https://github.com/FlutterPlayer/fplayer.git
      ref: develop # 可以替换为分支或标签名称

示例

下面是一个完整的示例代码,展示了如何使用 fplayer 插件来播放视频:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:fplayer/fplayer.dart';
import 'package:screen_brightness/screen_brightness.dart';

import 'app_bar.dart';

class VideoScreen extends StatefulWidget {
  final String url;

  const VideoScreen({super.key, required this.url});

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

class VideoScreenState extends State<VideoScreen> {
  final FPlayer player = FPlayer();

  // 视频列表
  List<VideoItem> videoList = [
    VideoItem(
      title: '第一集',
      subTitle: '视频1副标题',
      url: 'http://player.alicdn.com/video/aliyunmedia.mp4',
    ),
    VideoItem(
      title: '第二集',
      subTitle: '视频2副标题',
      url: 'https://www.runoob.com/try/demo_source/mov_bbb.mp4',
    ),
    VideoItem(
      title: '第三集',
      subTitle: '视频3副标题',
      url: 'http://player.alicdn.com/video/aliyunmedia.mp4',
    ),
  ];

  // 倍速列表
  Map<String, double> speedList = {
    "2.0": 2.0,
    "1.5": 1.5,
    "1.0": 1.0,
    "0.5": 0.5,
  };

  // 清晰度列表
  Map<String, ResolutionItem> resolutionList = {
    "480P": ResolutionItem(
      value: 480,
      url: 'https://www.runoob.com/try/demo_source/mov_bbb.mp4',
    ),
    "270P": ResolutionItem(
      value: 270,
      url: 'http://player.alicdn.com/video/aliyunmedia.mp4',
    ),
  };

  // 视频索引, 单个视频可不传
  int videoIndex = 0;

  // 模拟播放记录视频初始化完需要跳转的进度
  int seekTime = 100000;

  VideoScreenState();

  [@override](/user/override)
  void initState() {
    super.initState();
    startPlay();
  }

  void startPlay() async {
    // 视频播放相关配置
    await player.setOption(FOption.hostCategory, "enable-snapshot", 1);
    await player.setOption(FOption.hostCategory, "request-screen-on", 1);
    await player.setOption(FOption.hostCategory, "request-audio-focus", 1);
    await player.setOption(FOption.playerCategory, "reconnect", 20);
    await player.setOption(FOption.playerCategory, "framedrop", 20);
    await player.setOption(FOption.playerCategory, "enable-accurate-seek", 1);
    await player.setOption(FOption.playerCategory, "mediacodec", 1);
    await player.setOption(FOption.playerCategory, "packet-buffering", 0);
    await player.setOption(FOption.playerCategory, "soundtouch", 1);

    // 播放传入的视频
    setVideoUrl(widget.url);

    // 播放视频列表的第一个视频
    // setVideoUrl(videoList[videoIndex].url);
  }

  Future<void> setVideoUrl(String url) async {
    try {
      await player.setDataSource(url, autoPlay: true, showCover: true);
    } catch (error) {
      print("播放-异常: $error");
      return;
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    MediaQueryData mediaQueryData = MediaQuery.of(context);
    Size size = mediaQueryData.size;
    double videoHeight = size.width * 9 / 16;
    return Scaffold(
      appBar: const FAppBar.defaultSetting(title: "Video"),
      body: Column(
        children: [
          FView(
            player: player,
            width: double.infinity,
            height: videoHeight,
            color: Colors.black,
            fsFit: FFit.contain, // 全屏模式下的填充
            fit: FFit.fill, // 正常模式下的填充
            panelBuilder: fPanelBuilder(
              // 单视频配置
              title: '视频标题',
              subTitle: '视频副标题',
              // 右下方截屏按钮
              isSnapShot: true,
              // 右上方按钮组开关
              isRightButton: true,
              // 右上方按钮组
              rightButtonList: [
                InkWell(
                  onTap: () {},
                  child: Container(
                    padding: const EdgeInsets.all(10),
                    decoration: BoxDecoration(
                      color: Theme.of(context).primaryColorLight,
                      borderRadius: const BorderRadius.vertical(
                        top: Radius.circular(5),
                      ),
                    ),
                    child: Icon(
                      Icons.favorite,
                      color: Theme.of(context).primaryColor,
                    ),
                  ),
                ),
                InkWell(
                  onTap: () {},
                  child: Container(
                    padding: const EdgeInsets.all(10),
                    decoration: BoxDecoration(
                      color: Theme.of(context).primaryColorLight,
                      borderRadius: const BorderRadius.vertical(
                        bottom: Radius.circular(5),
                      ),
                    ),
                    child: Icon(
                      Icons.thumb_up,
                      color: Theme.of(context).primaryColor,
                    ),
                  ),
                )
              ],
              // 字幕功能:待内核提供api
              // caption: true,
              // 视频列表开关
              isVideos: true,
              // 视频列表列表
              videoList: videoList,
              // 当前视频索引
              videoIndex: videoIndex,
              // 全屏模式下点击播放下一集视频按钮
              playNextVideoFun: () {
                setState(() {
                  videoIndex += 1;
                });
              },
              settingFun: () {
                print('设置按钮点击事件');
              },
              // 自定义倍速列表
              speedList: speedList,
              // 清晰度开关
              isResolution: true,
              // 自定义清晰度列表
              resolutionList: resolutionList,
              // 视频播放错误点击刷新回调
              onError: () async {
                await player.reset();
                setVideoUrl(videoList[videoIndex].url);
              },
              // 视频播放完成回调
              onVideoEnd: () async {
                var index = videoIndex + 1;
                if (index < videoList.length) {
                  await player.reset();
                  setState(() {
                    videoIndex = index;
                  });
                  setVideoUrl(videoList[index].url);
                }
              },
              onVideoTimeChange: () {
                // 视频时间变动则触发一次,可以保存视频播放历史
              },
              onVideoPrepared: () async {
                // 视频初始化完毕,如有历史记录时间段则可以触发快进
                try {
                  if (seekTime >= 1) {
                    /// seekTo必须在FState.prepared
                    print('seekTo');
                    await player.seekTo(seekTime);
                    // print("视频快进-$seekTime");
                    seekTime = 0;
                  }
                } catch (error) {
                  print("视频初始化完快进-异常: $error");
                }
              },
            ),
          ),
          // 自定义小屏列表
          Container(
            width: double.infinity,
            height: 30,
            margin: const EdgeInsets.all(20),
            child: ListView.builder(
              scrollDirection: Axis.horizontal,
              padding: EdgeInsets.zero,
              itemCount: videoList.length,
              itemBuilder: (context, index) {
                bool isCurrent = videoIndex == index;
                Color textColor = Theme.of(context).primaryColor;
                Color bgColor = Theme.of(context).primaryColorDark;
                Color borderColor = Theme.of(context).primaryColor;
                if (isCurrent) {
                  textColor = Theme.of(context).primaryColorDark;
                  bgColor = Theme.of(context).primaryColor;
                  borderColor = Theme.of(context).primaryColor;
                }
                return GestureDetector(
                  onTap: () async {
                    await player.reset();
                    setState(() {
                      videoIndex = index;
                    });
                    setVideoUrl(videoList[index].url);
                  },
                  child: Container(
                    margin: EdgeInsets.only(left: index == 0 ? 0 : 10),
                    padding: const EdgeInsets.symmetric(horizontal: 5),
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(5),
                      color: bgColor,
                      border: Border.all(
                        width: 1.5,
                        color: borderColor,
                      ),
                    ),
                    alignment: Alignment.center,
                    child: Text(
                      videoList[index].title,
                      style: TextStyle(
                        fontSize: 15,
                        color: textColor,
                      ),
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }

  [@override](/user/override)
  void dispose() async {
    super.dispose();
    try {
      await ScreenBrightness().resetScreenBrightness();
    } catch (e) {
      print(e);
      throw 'Failed to reset brightness';
    }
    player.release();
  }
}

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

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用fplayer插件来播放视频的示例代码。fplayer是一个流行的Flutter视频播放器插件,它提供了丰富的功能和自定义选项。

首先,你需要在你的pubspec.yaml文件中添加fplayer依赖:

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

然后,运行flutter pub get来安装依赖。

接下来,你可以在你的Flutter应用中使用fplayer来播放视频。以下是一个简单的示例:

import 'package:flutter/material.dart';
import 'package:fplayer/fplayer.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> {
  late FPlayerController _controller;

  @override
  void initState() {
    super.initState();
    // 初始化视频控制器
    _controller = FPlayerController.network(
      'https://www.example.com/your-video-file.mp4',  // 替换为你的视频URL
    )..initialize().then((_) {
      // 可以在这里设置初始状态,比如自动播放等
      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: FPlayer(controller: _controller),
              )
            : Container(
                child: CircularProgressIndicator(),
              ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            if (_controller.value.isPlaying) {
              _controller.pause();
            } else {
              _controller.play();
            }
          });
        },
        tooltip: 'Play/Pause',
        child: Icon(
          _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个视频播放器。以下是代码的主要部分:

  1. 依赖导入:首先,我们导入了fplayer包。
  2. 视频控制器初始化:在_VideoPlayerScreenStateinitState方法中,我们创建了一个FPlayerController对象,并通过调用initialize()方法来初始化它。这里我们使用的是网络视频URL,但你也可以使用本地视频文件。
  3. 视频播放器构建:在build方法中,我们使用AspectRatioFPlayer小部件来显示视频。如果视频尚未初始化,则显示一个加载指示器。
  4. 播放/暂停控制:我们添加了一个浮动操作按钮(FAB),用于控制视频的播放和暂停。

请注意,你需要将示例中的视频URL替换为你自己的视频文件的URL或路径。此外,确保你已经按照fplayer插件的文档正确配置了项目(例如,在iOS和Android项目中添加必要的权限和配置)。

这个示例代码提供了一个基本的框架,你可以根据需要进行扩展和自定义,比如添加全屏支持、音量控制、进度条等。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!