Flutter视频播放插件video_player_avfoundation的使用

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

Flutter视频播放插件video_player_avfoundation的使用

video_player_avfoundationvideo_player 插件在iOS和macOS平台上的实现。通过这个插件,你可以在Flutter应用中轻松地播放视频文件。本文将详细介绍如何使用该插件,并提供一个完整的示例demo。

使用方法

由于 video_player_avfoundation 是一个被推荐(endorsed)的联合插件(federated plugin),因此你可以直接正常使用 video_player 。当你添加了 video_player 到你的项目后,这个包会自动包含在你的应用程序中,所以你不需要将其添加到 pubspec.yaml 文件中。

但是,如果你需要直接导入此包以使用其API,则应按照常规方式将其添加到 pubspec.yaml 文件中。

dependencies:
  flutter:
    sdk: flutter
  video_player: ^2.4.5 # 确保版本与您的项目兼容

示例代码

下面是一个完整的示例,展示了如何使用 video_player_avfoundation 播放不同类型的视频源,包括本地资源、远程MP4文件以及加密的M3U8直播流。

main.dart

// 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.

import 'package:flutter/material.dart';
import 'mini_controller.dart'; // 假设这是自定义控制器类

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

class _App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      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: 'Remote mp4',
              ),
              Tab(
                icon: Icon(Icons.favorite),
                text: 'Remote enc m3u8',
              ),
              Tab(icon: Icon(Icons.insert_drive_file), text: 'Asset mp4'),
            ],
          ),
        ),
        body: TabBarView(
          children: <Widget>[
            _BumbleBeeRemoteVideo(),
            _BumbleBeeEncryptedLiveStream(),
            _ButterFlyAssetVideo(),
          ],
        ),
      ),
    );
  }
}

class _ButterFlyAssetVideo extends StatefulWidget {
  @override
  _ButterFlyAssetVideoState createState() => _ButterFlyAssetVideoState();
}

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

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

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

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

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(
            padding: const EdgeInsets.only(top: 20.0),
          ),
          const Text('With assets 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
  _BumbleBeeRemoteVideoState createState() => _BumbleBeeRemoteVideoState();
}

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

  @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
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(padding: const EdgeInsets.only(top: 20.0)),
          const Text('With remote 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 _BumbleBeeEncryptedLiveStream extends StatefulWidget {
  @override
  _BumbleBeeEncryptedLiveStreamState createState() =>
      _BumbleBeeEncryptedLiveStreamState();
}

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

  @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
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(padding: const EdgeInsets.only(top: 20.0)),
          const Text('With remote encrypted m3u8'),
          Container(
            padding: const EdgeInsets.all(20),
            child: _controller.value.isInitialized
                ? AspectRatio(
                    aspectRatio: _controller.value.aspectRatio,
                    child: VideoPlayer(_controller),
                  )
                : const Text('loading...'),
          ),
        ],
      ),
    );
  }
}

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
  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: 'Play',
                    ),
                  ),
                ),
        ),
        GestureDetector(
          onTap: () {
            controller.value.isPlaying ? controller.pause() : controller.play();
          },
        ),
        Align(
          alignment: Alignment.topRight,
          child: PopupMenuButton<double>(
            initialValue: controller.value.playbackSpeed,
            tooltip: 'Playback speed',
            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'),
            ),
          ),
        ),
      ],
    );
  }
}

mini_controller.dart

假设 MiniController 是一个自定义的控制器类,用于管理视频播放器的状态和行为。这里我们简单定义一个 MiniController 类来满足上述代码的需求:

import 'package:video_player/video_player.dart';

class MiniController extends VideoPlayerController {
  MiniController.network(String dataSource) : super.network(dataSource);

  MiniController.asset(String assetName) : super.asset(assetName);

  Future<void> setPlaybackSpeed(double speed) async {
    await setPlaybackOptions(VideoPlaybackOptions(speed: speed));
  }
}

请注意,实际开发中你可能需要根据具体需求调整 MiniController 的实现。

以上就是关于 video_player_avfoundation 插件的详细说明及示例代码。希望这些信息对你有所帮助!如果有任何问题或需要进一步的帮助,请随时提问。


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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用video_player_avfoundation插件来播放视频的示例代码。video_player_avfoundationvideo_player插件在iOS平台上的具体实现,它依赖于AVFoundation框架。为了演示,我们将创建一个简单的Flutter应用,该应用包含一个视频播放页面。

首先,确保你的Flutter项目已经创建,并且位于项目根目录下。

  1. 添加依赖

    在你的pubspec.yaml文件中添加video_player依赖:

    dependencies:
      flutter:
        sdk: flutter
      video_player: ^2.2.10  # 请检查最新版本号
    

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

  2. 配置iOS平台

    对于iOS平台,video_player插件会自动使用video_player_avfoundation。你需要在ios/Runner/Info.plist中添加对HTTP请求的支持,如果你的视频URL是基于HTTP的(对于HTTPS,这是不必要的):

    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    
  3. 创建视频播放页面

    创建一个新的Flutter页面,比如video_player_screen.dart,并添加以下代码:

    import 'package:flutter/material.dart';
    import 'package:video_player/video_player.dart';
    import 'package:chewie/chewie.dart';
    
    class VideoPlayerScreen extends StatefulWidget {
      @override
      _VideoPlayerScreenState createState() => _VideoPlayerScreenState();
    }
    
    class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
      late VideoPlayerController _controller;
      ChewieController? _chewieController;
    
      @override
      void initState() {
        super.initState();
        // 初始化视频控制器
        _controller = VideoPlayerController.network(
          'https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4',
        )
          ..initialize().then((_) {
            // 确保视频初始化后设置Chewie控制器
            setState(() {});
          });
    
        // 创建Chewie控制器
        _chewieController = ChewieController(
          videoPlayerController: _controller,
          aspectRatio: _controller.value.aspectRatio,
          autoPlay: false,
          looping: false,
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Video Player Demo'),
          ),
          body: Center(
            child: _controller.value.isInitialized
                ? Chewie(_chewieController!)
                : Container(
                    child: CircularProgressIndicator(),
                  ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              setState(() {
                _controller.value.isPlaying
                  ? _controller.pause()
                  : _controller.play();
              });
            },
            child: Icon(
              _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
            ),
          ),
        );
      }
    
      @override
      void dispose() {
        _controller.dispose();
        _chewieController?.dispose();
        super.dispose();
      }
    }
    

    在这个例子中,我们使用了Chewie包,它是一个简单的Flutter视频播放器封装,基于video_player插件。你可以通过flutter pub add chewie来添加这个依赖。

  4. 更新主页面

    最后,在你的main.dart文件中,更新以包含新的视频播放页面:

    import 'package:flutter/material.dart';
    import 'video_player_screen.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(),
        );
      }
    }
    

现在,你应该能够在你的Flutter应用中播放视频了。运行flutter run来启动应用,并查看效果。这个示例演示了如何初始化视频播放器、播放和暂停视频,以及如何处理视频的初始化状态。

回到顶部