Flutter视频播放插件extended_video_player_avfoundation的使用

Flutter视频播放插件extended_video_player_avfoundation的使用

extended_video_player_avfoundation 是一个用于在iOS和macOS平台上播放视频的插件。它是 video_player 插件的iOS和macOS实现。

使用

该插件是被支持的,这意味着你可以直接使用 video_player。当你这样做的时候,这个包会自动包含在你的应用中,所以你不需要在 pubspec.yaml 文件中添加它。

然而,如果你导入这个包以使用其任何API,则应该像往常一样将其添加到你的 pubspec.yaml 文件中。

完整示例代码

以下是一个完整的示例代码,展示了如何使用 extended_video_player_avfoundation 来播放本地和远程视频。

// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: public_member_api_docs

import 'package:extended_video_player_platform_interface/video_player_platform_interface.dart';
import 'package:flutter/material.dart';

import 'mini_controller.dart';

void main() {
  runApp(
    MaterialApp(
      home: _App(),
    ),
  );
}

class _App extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 4,
      child: Scaffold(
        key: const ValueKey<String>('home_page'),
        appBar: AppBar(
          title: const Text('Video player example'),
          bottom: const TabBar(
            isScrollable: true,
            tabs: <Widget>[
              Tab(
                icon: Icon(Icons.cloud),
                text: '远程mp4',
              ),
              Tab(
                icon: Icon(Icons.cloud),
                text: '远程缓存mp4',
              ),
              Tab(
                icon: Icon(Icons.favorite),
                text: '远程加密m3u8',
              ),
              Tab(icon: Icon(Icons.insert_drive_file), text: '本地资源mp4'),
            ],
          ),
        ),
        body: TabBarView(
          children: <Widget>[
            _BumbleBeeRemoteVideo(),
            _BumbleBeeRemoteCacheVideo(),
            _BumbleBeeEncryptedLiveStream(),
            _ButterFlyAssetVideo(),
          ],
        ),
      ),
    );
  }
}

class _ButterFlyAssetVideo extends StatefulWidget {
  [@override](/user/override)
  _ButterFlyAssetVideoState createState() => _ButterFlyAssetVideoState();
}

class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> {
  late MiniController _controller;

  [@override](/user/override)
  void initState() {
    super.initState();
    _controller = MiniController.asset('assets/Butterfly-209.mp4');

    _controller.addListener(() {
      setState(() {});
    });
    _controller.initialize().then((_) => setState(() {}));
    _controller.play();
  }

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(
            padding: const EdgeInsets.only(top: 20.0),
          ),
          const Text('使用本地资源mp4'),
          Container(
            padding: const EdgeInsets.all(20),
            child: AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              child: Stack(
                alignment: Alignment.bottomCenter,
                children: <Widget>[
                  VideoPlayer(_controller),
                  _ControlsOverlay(controller: _controller),
                  VideoProgressIndicator(_controller),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _BumbleBeeRemoteVideo extends StatefulWidget {
  [@override](/user/override)
  _BumbleBeeRemoteVideoState createState() => _BumbleBeeRemoteVideoState();
}

class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> {
  late MiniController _controller;

  [@override](/user/override)
  void initState() {
    super.initState();
    _controller = MiniController.network(
      'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
    );

    _controller.addListener(() {
      setState(() {});
    });
    _controller.initialize();
  }

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(padding: const EdgeInsets.only(top: 20.0)),
          const Text('使用远程mp4'),
          Container(
            padding: const EdgeInsets.all(20),
            child: AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              child: Stack(
                alignment: Alignment.bottomCenter,
                children: <Widget>[
                  VideoPlayer(_controller),
                  _ControlsOverlay(controller: _controller),
                  VideoProgressIndicator(_controller),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _BumbleBeeRemoteCacheVideo extends StatefulWidget {
  [@override](/user/override)
  _BumbleBeeRemoteCacheVideoState createState() => _BumbleBeeRemoteCacheVideoState();
}

class _BumbleBeeRemoteCacheVideoState extends State<_BumbleBeeRemoteCacheVideo> {
  late MiniController _controller;

  [@override](/user/override)
  void initState() {
    super.initState();
    _controller = MiniController.network(
        'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
        videoPlayerParameters: VideoPlayerParameters(
            videoPlayerOptions: VideoPlayerOptions(enableCache: true)));

    _controller.addListener(() {
      setState(() {});
    });
    _controller.initialize();
  }

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(padding: const EdgeInsets.only(top: 20.0)),
          const Text('使用远程缓存mp4'),
          Container(
            padding: const EdgeInsets.all(20),
            child: AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              child: Stack(
                alignment: Alignment.bottomCenter,
                children: <Widget>[
                  VideoPlayer(_controller),
                  _ControlsOverlay(controller: _controller),
                  VideoProgressIndicator(_controller),
                ],
              ),
            ),
          ),
          TextButton(
            style: ButtonStyle(
              foregroundColor: MaterialStateProperty.all<Color>(Colors.blue),
            ),
            onPressed: () {
              _controller.clearCache();
            },
            child: const Text('清除缓存'),
          )
        ],
      ),
    );
  }
}

class _BumbleBeeEncryptedLiveStream extends StatefulWidget {
  [@override](/user/override)
  _BumbleBeeEncryptedLiveStreamState createState() => _BumbleBeeEncryptedLiveStreamState();
}

class _BumbleBeeEncryptedLiveStreamState extends State<_BumbleBeeEncryptedLiveStream> {
  late MiniController _controller;

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

    _controller = MiniController.network(
        'https://flutter.github.io/assets-for-api-docs/assets/videos/hls/encrypted_bee.m3u8');

    _controller.addListener(() {
      setState(() {});
    });
    _controller.initialize();

    _controller.play();
  }

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(padding: const EdgeInsets.only(top: 20.0)),
          const Text('使用远程加密m3u8'),
          Container(
            padding: const EdgeInsets.all(20),
            child: _controller.value.isInitialized
                ? AspectRatio(
                    aspectRatio: _controller.value.aspectRatio,
                    child: VideoPlayer(_controller),
                  )
                : const Text('加载中...'),
          ),
        ],
      ),
    );
  }
}

class _ControlsOverlay extends StatelessWidget {
  const _ControlsOverlay({required this.controller});

  static const List<double> _examplePlaybackRates = <double>[
    0.25,
    0.5,
    1.0,
    1.5,
    2.0,
    3.0,
    5.0,
    10.0,
  ];

  final MiniController controller;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        AnimatedSwitcher(
          duration: const Duration(milliseconds: 50),
          reverseDuration: const Duration(milliseconds: 200),
          child: controller.value.isPlaying
              ? const SizedBox.shrink()
              : const ColoredBox(
                  color: Colors.black26,
                  child: Center(
                    child: Icon(
                      Icons.play_arrow,
                      color: Colors.white,
                      size: 100.0,
                      semanticLabel: '播放',
                    ),
                  ),
                ),
        ),
        GestureDetector(
          onTap: () {
            controller.value.isPlaying ? controller.pause() : controller.play();
          },
        ),
        Align(
          alignment: Alignment.topRight,
          child: PopupMenuButton<double>(
            initialValue: controller.value.playbackSpeed,
            tooltip: '播放速度',
            onSelected: (double speed) {
              controller.setPlaybackSpeed(speed);
            },
            itemBuilder: (BuildContext context) {
              return <PopupMenuItem<double>>[
                for (final double speed in _examplePlaybackRates)
                  PopupMenuItem<double>(
                    value: speed,
                    child: Text('${speed}x'),
                  )
              ];
            },
            child: Padding(
              padding: const EdgeInsets.symmetric(
                // 使用较少的垂直间距,因为文本在水平方向上也更长,
                // 所以它看起来需要更多的水平空间(匹配视频的宽高比)。
                vertical: 12,
                horizontal: 16,
              ),
              child: Text('${controller.value.playbackSpeed}x'),
            ),
          ),
        ),
      ],
    );
  }
}

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

1 回复

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


extended_video_player_avfoundation 是一个基于 Flutter 的视频播放插件,它使用 iOS 的 AVFoundation 框架来实现视频播放功能。这个插件提供了比 Flutter 默认的 video_player 插件更多的功能和灵活性,尤其是在 iOS 平台上。

安装

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

dependencies:
  flutter:
    sdk: flutter
  extended_video_player_avfoundation: ^版本号

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

基本使用

  1. 导入插件

    在你的 Dart 文件中导入插件:

    import 'package:extended_video_player_avfoundation/extended_video_player_avfoundation.dart';
    
  2. 创建视频播放器控制器

    final VideoPlayerController controller = VideoPlayerController.asset('assets/videos/sample.mp4');
    

    你也可以使用网络视频:

    final VideoPlayerController controller = VideoPlayerController.network('https://www.example.com/sample.mp4');
    
  3. 初始化控制器

    initState 中初始化控制器:

    [@override](/user/override)
    void initState() {
      super.initState();
      controller.initialize().then((_) {
        setState(() {});
      });
    }
    
  4. 显示视频播放器

    使用 VideoPlayer 小部件来显示视频:

    [@override](/user/override)
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Video Player'),
        ),
        body: Center(
          child: controller.value.isInitialized
              ? AspectRatio(
                  aspectRatio: controller.value.aspectRatio,
                  child: VideoPlayer(controller),
                )
              : CircularProgressIndicator(),
        ),
      );
    }
    
  5. 控制播放

    你可以通过控制器来控制视频的播放、暂停、停止等操作:

    FloatingActionButton(
      onPressed: () {
        setState(() {
          controller.value.isPlaying ? controller.pause() : controller.play();
        });
      },
      child: Icon(
        controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
      ),
    ),
    
  6. 释放资源

    dispose 中释放控制器资源:

    [@override](/user/override)
    void dispose() {
      controller.dispose();
      super.dispose();
    }
    

高级功能

extended_video_player_avfoundation 提供了许多高级功能,例如:

  • 播放速度控制:你可以通过 controller.setPlaybackSpeed(double speed) 来调整播放速度。
  • 音量控制:通过 controller.setVolume(double volume) 来调整音量。
  • 视频缩放模式:使用 controller.setVideoScalingMode(VideoScalingMode mode) 来设置视频的缩放模式。
  • 播放列表:支持播放列表功能,可以连续播放多个视频。

示例代码

以下是一个完整的示例代码:

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

class VideoPlayerScreen extends StatefulWidget {
  [@override](/user/override)
  _VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}

class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  late VideoPlayerController _controller;

  [@override](/user/override)
  void initState() {
    super.initState();
    _controller = VideoPlayerController.asset('assets/videos/sample.mp4')
      ..initialize().then((_) {
        setState(() {});
      });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Video Player'),
      ),
      body: Center(
        child: _controller.value.isInitialized
            ? AspectRatio(
                aspectRatio: _controller.value.aspectRatio,
                child: VideoPlayer(_controller),
              )
            : CircularProgressIndicator(),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _controller.value.isPlaying ? _controller.pause() : _controller.play();
          });
        },
        child: Icon(
          _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
        ),
      ),
    );
  }

  [@override](/user/override)
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

void main() => runApp(MaterialApp(
  home: VideoPlayerScreen(),
));
回到顶部