Flutter视频播放插件video_player_android的使用

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

Flutter视频播放插件video_player_android的使用

video_player_androidvideo_player 插件在 Android 平台上的实现。当你在项目中使用 video_player 时,它会自动包含这个平台特定的实现包,因此你不需要在 pubspec.yaml 中显式添加它,除非你需要直接使用它的 API。

使用方法

基本使用

  1. 添加依赖:如果你需要直接使用 video_player_android 的 API,确保在 pubspec.yaml 文件中添加了 video_player 依赖。

    dependencies:
      video_player: ^2.6.1 # 确保版本兼容
    
  2. 初始化控制器:根据你的需求选择不同的视频源(本地资源、网络视频或 RTSP 流)来初始化 VideoPlayerController 或者在这个例子中的自定义 MiniController

  3. 设置状态监听和初始化:为控制器添加监听器并在初始化完成后执行相应操作,如开始播放视频。

  4. 创建用户界面:构建一个包含 VideoPlayer 小部件和其他控制元素(例如播放/暂停按钮、进度条等)的 UI。

  5. 清理资源:当页面不再可见或组件被销毁时,记得释放控制器占用的资源以避免内存泄漏。

示例代码

以下是一个完整的示例应用,展示了如何使用 video_player 播放不同类型的视频内容(本地资源、远程 MP4 和 RTSP 流)。请注意,在实际开发中应该替换示例 URL 和路径以适应自己的项目需求。

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'),
              Tab(icon: Icon(Icons.videocam), text: 'RTSP'),
              Tab(icon: Icon(Icons.insert_drive_file), text: 'Asset'),
            ],
          ),
        ),
        body: TabBarView(
          children: <Widget>[
            _BumbleBeeRemoteVideo(),
            _RtspRemoteVideo(),
            _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((_) => _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),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// 播放远程MP4视频
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),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// 播放RTSP流媒体
class _RtspRemoteVideo extends StatefulWidget {
  @override
  _RtspRemoteVideoState createState() => _RtspRemoteVideoState();
}

class _RtspRemoteVideoState extends State<_RtspRemoteVideo> {
  MiniController? _controller;

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

  Future<void> changeUrl(String url) async {
    if (_controller != null) {
      await _controller!.dispose();
    }

    setState(() {
      _controller = MiniController.network(url);
    });

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

    return _controller!.initialize();
  }

  String? _validateRtspUrl(String? value) {
    if (value == null || !value.startsWith('rtsp://')) {
      return 'Enter a valid RTSP URL';
    }
    return null;
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(padding: const EdgeInsets.only(top: 20.0)),
          const Text('With RTSP streaming'),
          Padding(
            padding: const EdgeInsets.all(20.0),
            child: TextFormField(
              autovalidateMode: AutovalidateMode.onUserInteraction,
              decoration: const InputDecoration(label: Text('RTSP URL')),
              validator: _validateRtspUrl,
              textInputAction: TextInputAction.done,
              onFieldSubmitted: (String value) {
                if (_validateRtspUrl(value) == null) {
                  changeUrl(value);
                } else {
                  setState(() {
                    _controller?.dispose();
                    _controller = null;
                  });
                }
              },
            ),
          ),
          if (_controller != null)
            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 _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'),
            ),
          ),
        ),
      ],
    );
  }
}

以上代码片段提供了一个多标签页的应用程序界面,每个标签页对应一种视频播放方式。你可以根据自己的需求调整这些代码片段,并且可以根据实际情况进一步扩展功能,比如增加更多的播放控件或者优化UI布局。


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

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用video_player_android插件来播放视频的示例代码。不过需要注意的是,video_player_android这个插件名可能有些误导,因为Flutter社区更常用的视频播放插件是video_player,它同时支持Android和iOS。如果你确实是在寻找一个特定名为video_player_android的插件,请确保它存在于pub.dev上,并且以下代码可能需要稍作调整。但一般来说,video_player插件已经足够满足大多数需求。

以下是如何使用video_player插件的示例:

  1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  video_player: ^2.2.17  # 请检查pub.dev以获取最新版本
  1. 导入包

在你的Dart文件中导入video_player包:

import 'package:video_player/video_player.dart';
import 'package:chewie_flutter/chewie_flutter.dart';  // 可选的,用于提供UI控件

注意:chewie_flutter是一个基于video_player的封装,提供了更丰富的播放控制UI。

  1. 初始化视频播放器

在你的State类中初始化VideoPlayerController

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

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

  @override
  void initState() {
    super.initState();
    // 初始化视频播放器控制器
    _controller = VideoPlayerController.network(
      'https://www.example.com/path/to/your/video.mp4',
    )
      ..initialize()  // 初始化视频
      .then((_) {
        // 确保界面在视频加载完成后更新
        setState(() {});
      });
  }

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

  @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),
              )
            : Container(),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 使用Chewie作为播放控件
          setState(() {
            _showChewiePlayer();
          });
        },
        tooltip: 'Play with controls',
        child: Icon(Icons.play_arrow),
      ),
    );
  }

  void _showChewiePlayer() {
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => ChewieDemo(
          _controller: _controller,
        ),
      ),
    );
  }
}

class ChewieDemo extends StatelessWidget {
  final VideoPlayerController _controller;

  ChewieDemo({required this._controller});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Chewie Demo"),
      ),
      body: Center(
        child: Chewie(
          _controller: _controller,
          aspectRatio: _controller.value.aspectRatio,
          autoPlay: false,
          looping: false,
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,它使用video_player插件来播放网络视频。我们还展示了如何使用chewie_flutter来提供一个带有播放控件的UI。

请确保在实际项目中替换视频URL,并根据需要调整UI和逻辑。如果你确实在寻找一个名为video_player_android的特定插件,请查阅其官方文档以获取正确的使用方法和示例代码。

回到顶部