Flutter视频投屏插件video_cast的使用

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

Flutter视频投屏插件video_cast的使用

简介

video_cast 是一个用于在Chromecast设备上播放视频的Flutter插件。这是对 flutter_video_cast_v2 插件的修改版本,增加了额外的功能。

安装

首先,在你的 pubspec.yaml 文件中添加 video_cast 作为依赖项。

Android 配置

在你的模块(应用级别)Gradle文件(通常是 android/app/build.gradle)中添加以下依赖:

implementation 'com.google.android.gms:play-services-cast-framework:21.2.0'
implementation 'com.google.android.exoplayer:extension-cast:2.17.1'

在应用程序清单 android/app/src/main/AndroidManifest.xml 中将 MainActivity 的主题设置为 @style/Theme.AppCompat.NoActionBar

<manifest ...
  <application ...
    <meta-data android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
               android:value="com.google.android.exoplayer2.ext.cast.DefaultCastOptionsProvider"/>
    ...
    <activity android:theme="@style/Theme.AppCompat.NoActionBar" ...

使 MainActivity 继承 FlutterFragmentActivity 并初始化 Cast 上下文:

CastContext.getSharedInstance(applicationContext)

使用 ChromeCastButton

你现在可以在小部件树中添加一个 ChromeCastButton 小部件。

按钮可以通过传递给 ChromeCastButtononButtonCreated 回调中的 ChromeCastController 进行控制。

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CastSample(),
    );
  }
}

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

class _CastSampleState extends State<CastSample> {
  ChromeCastController _controller;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Cast Sample'),
        actions: [
          ChromeCastButton(
            onButtonCreated: (controller) {
              setState(() => _controller = controller);
              _controller?.addSessionListener();
            },
            onSessionStarted: () {
                _controller?.loadMedia(
                url:
                    "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
                position: 30000, // 开始位置为30秒
                autoplay: true,
                title: "Spider-Man: No Way Home",
                description:
                    "Peter Parker is unmasked and no longer able to separate his normal life from the high-stakes of being a super-hero. When he asks for help from Doctor Strange the stakes become even more dangerous, forcing him to discover what it truly means to be Spider-Man.",
                image:
                    "https://terrigen-cdn-dev.marvel.com/content/prod/1x/marvsmposterbk_intdesign.jpg",
                type: ChromeCastMediaType.movie,
              );
            },
          ),
        ],
      ),
    );
  }
}

完整示例代码

import 'package:flutter/material.dart';
import 'package:video_cast/chrome_cast_media_type.dart';
import 'package:video_cast/chrome_cast_subtitle.dart';
import 'package:video_cast/video_cast.dart';

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

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

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

class _MyAppState extends State<MyApp> {
  ChromeCastController? castController;

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: Column(
            children: [
              const Text("ChromeCastButton"),
              const SizedBox(
                height: 5,
              ),
              ChromeCastButton(
                color: Colors.red, // 按钮颜色
                onButtonCreated: (controller) {
                  castController = controller;
                  castController?.addSessionListener(); // 添加会话监听器
                },
                onSessionEnding: (position) {
                  print("in app ending");
                  print("position is $position");
                },
                onSessionEnded: () {
                  print("in app ended");
                },
                onSessionStarted: () {
                  print("in app started");
                  castController?.onProgressEvent().listen((event) {
                    print("in app progress ${event.inMilliseconds}");
                  });
                  castController?.loadMedia(
                    url:
                        "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
                    position: 30000, // 开始位置为30秒
                    autoplay: true,
                    title: "Spider-Man: No Way Home",
                    description:
                        "Peter Parker is unmasked and no longer able to separate his normal life from the high-stakes of being a super-hero. When he asks for help from Doctor Strange the stakes become even more dangerous, forcing him to discover what it truly means to be Spider-Man.",
                    image:
                        "https://terrigen-cdn-dev.marvel.com/content/prod/1x/marvsmposterbk_intdesign.jpg",
                    type: ChromeCastMediaType.movie,
                    subtitles: [
                      ChromeCastSubtitle(
                        id: 1,
                        language: "en-US",
                        name: "English",
                        source:
                            "https://cc.2cdns.com/3e/62/3e62d0109500abf55acf229a0599a20d/3e62d0109500abf55acf229a0599a20d.vtt",
                      ),
                      ChromeCastSubtitle(
                        id: 2,
                        language: "ar",
                        name: "Arabic",
                        source:
                            "https://cc.2cdns.com/91/bd/91bdc91ffff0906bd54f0711eb3e786f/91bdc91ffff0906bd54f0711eb3e786f.vtt",
                      ),
                    ],
                  );
                },
              ),
              ElevatedButton(
                onPressed: () {
                  castController?.setTrack(subId: 1); // 设置字幕轨道1
                },
                child: const Text("Set Track 1"),
              ),
              ElevatedButton(
                onPressed: () {
                  castController?.setTrack(subId: 2); // 设置字幕轨道2
                },
                child: const Text("Set Track 2"),
              ),
              ElevatedButton(
                onPressed: () {
                  castController?.disableTrack(); // 禁用字幕轨道
                },
                child: const Text("Disable Track"),
              ),
            ],
          ),
        ),
      ),
    );
  }

  [@override](/user/override)
  void dispose() {
    castController?.cancelTimer(); // 取消计时器
    super.dispose();
  }
}

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

1 回复

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


当然,以下是一个关于如何在Flutter应用中使用video_cast插件来实现视频投屏的示例代码。video_cast插件允许你将Flutter应用中的视频内容投屏到支持DLNA或Chromecast的设备上。

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

dependencies:
  flutter:
    sdk: flutter
  video_cast: ^0.4.0  # 请检查最新版本号

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

接下来,在你的Flutter应用中,你可以按照以下步骤来使用video_cast插件:

  1. 初始化Cast上下文
import 'package:flutter/material.dart';
import 'package:video_cast/video_cast.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late CastContext castContext;

  @override
  void initState() {
    super.initState();
    // 初始化Cast上下文
    castContext = CastContext(
      onDevicesUpdated: _devicesUpdated,
      onSessionUpdated: _sessionUpdated,
    );
    castContext.initialize();
  }

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

  void _devicesUpdated(List<CastDevice> devices) {
    // 处理设备更新事件
    print("Devices updated: $devices");
  }

  void _sessionUpdated(CastSession? session) {
    // 处理会话更新事件
    print("Session updated: $session");
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Video Cast Example'),
        ),
        body: Center(
          child: CastButton(
            castContext: castContext,
            videoUrl: 'https://www.example.com/video.mp4', // 你的视频URL
            text: 'Cast Video',
          ),
        ),
      ),
    );
  }
}
  1. 创建CastButton组件

由于video_cast插件没有自带的按钮组件,你可以自定义一个按钮来触发投屏操作。以下是一个简单的CastButton组件示例:

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

class CastButton extends StatelessWidget {
  final CastContext castContext;
  final String videoUrl;
  final String text;

  const CastButton({
    Key? key,
    required this.castContext,
    required this.videoUrl,
    required this.text,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () async {
        List<CastDevice> devices = castContext.devices;
        if (devices.isEmpty) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('No cast devices found')),
          );
          return;
        }

        CastDevice device = devices.first; // 选择第一个设备,实际应用中你可能需要让用户选择
        CastSession session = await castContext.startSession(device, videoUrl);
        if (session != null) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Casting to ${device.friendlyName}')),
          );
        } else {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Failed to start casting')),
          );
        }
      },
      child: Text(text),
    );
  }
}

以上代码展示了一个基本的Flutter应用,它使用video_cast插件来检测可用的投屏设备,并允许用户点击按钮将视频投屏到第一个检测到的设备上。

请注意,实际应用中你可能需要处理更多的边缘情况和用户交互,比如让用户选择特定的投屏设备,处理投屏过程中的错误,以及在投屏结束时进行适当的清理工作。此外,务必确保你的视频URL是有效的,并且目标设备支持DLNA或Chromecast协议。

回到顶部