实现音视频互动

  • Flutter

更新时间不可用

了解如何快速接入实时互动 RTC,完成环境准备、参数配置、示例运行和核心流程验证。

本文介绍如何集成声网实时互动 SDK,通过少量代码从 0 开始实现一个简单的实时互动 App,适用于互动直播和视频通话场景。 首先,你需要了解以下有关音视频实时互动的基础概念:

  • 声网实时互动 SDK:由声网开发的、帮助开发者在 App 中实现实时音视频互动的 SDK。
  • 频道:用于传输数据的通道,在同一个频道内的用户可以进行实时互动。
  • 主播:可以在频道内发布音视频,同时也可以订阅其他主播发布的音视频。
  • 观众:可以在频道内订阅音视频,不具备发布音视频权限。

更多概念详见关键概念。

下图展示在 App 中实现音视频互动的基本工作流程:

  1. 所有用户调用 joinChannel 方法加入频道,并根据需要设置用户角色:

    • 互动直播:如果用户需要在频道中发流,则设为主播;如果用户只需要收流,则设为观众。
    • 视频通话:将所有用户的角色都设为主播。
  2. 加入频道后,不同角色的用户具备不同的行为:

    • 所有用户默认都可以接收频道中的音视频流。
    • 主播可以在频道内发布音视频流。
    • 观众如果需要发流,可在频道内调用 setClientRole 方法修改用户角色,使其具备发流权限。

前提条件

  • Flutter 2.10.5 或更高版本。
  • Dart 2.14.0 或更高版本。
  • 根据你的目标平台,准备对应的开发和运行环境:
目标平台环境要求
iOS
  • macOS 10.15 或更高版本
  • 最新版本的 Xcode
  • 两台 iOS 设备
Android
  • macOS 10.15 或更高版本
  • Windows 10 或更高版本
  • 最新版本的 Android Studio
  • 两台 Android 设备
macOS
  • macOS 10.15 或更高版本
  • 最新版本的 Xcode
  • 两台 macOS 设备
Windows
  • Windows 10 或更高版本
  • 最新版本的 Visual Studio
  • 两台 Windows 设备
表格内容超出当前宽度,可横向滚动查看更多列。

信息

  • 更多环境要求细节,详见 Install Flutter。
  • 你可以运行 flutter doctor 命令检查开发和运行环境是否达到要求。
  • 可以访问互联网的计算机。如果你的网络环境部署了防火墙,参考应对防火墙限制以正常使用声网服务。
  • 一个有效的声网账号以及声网项目。请参考开通 RTC 服务从声网控制台获得以下信息:
    • App ID:声网随机生成的字符串,用于识别你的项目。
    • 临时 Token:Token 也称为动态密钥,在客户端加入频道时对用户鉴权。临时 Token 的有效期为 24 小时。

创建项目

根据你选用的 IDE 不同,创建 Flutter 项目有多种方式,详见 Create the app。在本文中,以在终端中运行 flutter create 命令创建 Flutter 项目为例。

Shell
# 将 <Project Name> 替换为项目名
flutter create <Project Name>

集成 SDK

  1. 打开 pubspec.yaml 文件,添加以下依赖:

    • 添加 agora_rtc_engine 依赖项,集成声网 Flutter SDK。关于 agora_rtc_engine 的最新版本可以查询 https://pub.dev/packages/agora_rtc_engine
    • 添加 permission_handler 依赖项,安装权限处理插件。
    YAML
    environment:
      sdk: ">=2.12.0 <3.0.0"
    # 依赖项
    dependencies:
      flutter:
        sdk: flutter
      # The following adds the Cupertino Icons font to your application.
      # Use with the CupertinoIcons class for iOS style icons.
      cupertino_icons: ^0.1.3
      # 声网 Flutter SDK 依赖项,请使用最新版本的 agora_rtc_engine
      agora_rtc_engine: ^6.0.0
      #  权限处理插件依赖项
      permission_handler: ^8.3.0
  2. 添加依赖并保存文件后,打开终端,在项目路径下执行以下命令获取并安装依赖:

    Shell
    flutter pub get

创建用户界面

根据实时音视频互动的场景需要,为你的项目创建两个视图框,分别用于展示本地视频和远端视频。复制以下代码即可快速创建场景所需的用户界面。

实现步骤

本小节介绍如何实现一个实时音视频互动 App。你可以先复制完整的示例代码到你的项目中,快速体验实时音视频互动的基础功能,再按照实现步骤了解其中的核心 API 调用。

下图展示了使用声网 RTC SDK 实现音视频互动的基本流程:

下面列出了一段实现实时音视频互动基本流程的完整代码以供参考。复制以下代码替换 /lib/main.dart 文件的全部内容,即可快速体验实时音视频互动基础功能。

信息

将 <-- Insert App Id -->、<-- Insert Token --> 和 <-- Insert Channel Name --> 分别替换为你在控制台获取到的 App ID、临时 Token,以及生成临时 Token 时填入的频道名。

导入 package

导入构建 App 所需的 package。

Dart
import 'dart:async';

import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

定义 App ID 和 Token

传入从声网控制台获取的 App ID、临时 Token,以及生成临时 Token 时填入的频道名,用于后续初始化引擎和加入频道。

Dart
// 填写声网控制台中获取的 App ID
const appId = "<-- Insert App Id -->";
// 填写声网控制台中生成的临时 Token
const token = "<-- Insert Token -->";
// 填写频道名
const channel = "<-- Insert Channel Name -->";

处理权限请求

获取体验实时音视频所需的麦克风和摄像头权限。

Dart
await [Permission.microphone, Permission.camera].request();

信息

如果你的目标平台是 iOS 或 macOS,需要在 Info.plist 中添加实时互动所需的权限声明如下:

  • 麦克风:key 为 Privacy - Microphone Usage Description,value 填写使用目的,如:for a video call。
  • 摄像头:key 为 Privacy - Camera Usage Description,value 填写使用目的,如:for a video call。

初始化引擎

调用 createAgoraRtcEngine 方法创建一个 RtcEngine 对象,然后调用 initialize 初始化引擎并设置频道场景为 channelProfileLiveBroadcasting(直播场景)。

注意

在初始化 SDK 前,需确保终端用户已经充分了解并同意相关的隐私政策。

Dart
// 创建 RtcEngine 对象
_engine = await createAgoraRtcEngine();

// 初始化 RtcEngine,设置频道场景为 channelProfileLiveBroadcasting(直播场景)
await _engine.initialize(const RtcEngineContext(
  appId: appId,
  channelProfile: ChannelProfileType.channelProfileLiveBroadcasting,
));

启用视频模块

按照以下步骤启用视频模块:

  1. 调用 enableVideo 方法,启用视频模块。
  2. 调用 startPreview 方法,开启本地视频预览。
Dart
// 启用视频模块
await _engine.enableVideo();
// 开启本地预览
await _engine.startPreview();

加入频道并发布音视频流

调用 joinChannel 加入频道。在 ChannelMediaOptions 中进行如下配置:

  • 设置用户角色为 clientRoleBroadcaster(主播)或 clientRoleAudience(观众)。
  • 将 publishMicrophoneTrack 和 publishCameraTrack 设置为 true,发布麦克风采集的音频和摄像头采集的视频。
  • 将 autoSubscribeAudio 和 autoSubscribeVideo 设置为 true,自动订阅所有音视频流。
Dart
await _engine.joinChannel(
  // 使用临时 Token 和频道名加入频道
  token: token,
  channelId: channel,
  options: const ChannelMediaOptions(
    // 自动订阅所有视频流
    autoSubscribeVideo: true,
    // 自动订阅所有音频流
    autoSubscribeAudio: true,
    // 发布摄像头采集的视频
    publishCameraTrack: true,
    // 发布麦克风采集的音频
    publishMicrophoneTrack: true,
    // 设置用户角色为 clientRoleBroadcaster(主播)或 clientRoleAudience(观众)
    clientRoleType: ClientRoleType.clientRoleBroadcaster),
  // uid 为 0 表示由引擎内部随机生成用户 ID
  uid: 0,
);

实现常用回调

根据使用场景,定义必要的回调。以下示例代码展示如何调用 registerEventHandler 添加并实现 onJoinChannelSuccess、 onUserJoined 和 onUserOffline 回调。

Dart
// 添加回调事件
_engine.registerEventHandler(
  RtcEngineEventHandler(
    // 成功加入频道回调
    onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
      debugPrint("local user ${connection.localUid} joined");
      setState(() {
        _localUserJoined = true;
      });
    },
    // 远端用户或主播加入当前频道回调
    onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {
      debugPrint("remote user $remoteUid joined");
      setState(() {
        _remoteUid = remoteUid;
      });
    },
    // 远端用户或主播离开当前频道回调
    onUserOffline: (RtcConnection connection, int remoteUid,
        UserOfflineReasonType reason) {
      debugPrint("remote user $remoteUid left channel");
      setState(() {
        _remoteUid = null;
      });
    },
  ),
);

设置远端视图

当远端用户加入频道时,触发 onUserJoined 回调。通过该回调获取远端用户的 uid 后,创建一个 AgoraVideoView 控件,用于显示对应远端用户的视频流。

Dart
// 生成远端视频
Widget _remoteVideo() {
  if (_remoteUid != null) {
    return AgoraVideoView(
      controller: VideoViewController.remote(
        rtcEngine: _engine,
        canvas: VideoCanvas(uid: _remoteUid),
        connection: const RtcConnection(channelId: channel),
      ),
    );
  } else {
    return const Text(
      'Please wait for remote user to join',
      textAlign: TextAlign.center,
    );
  }
}

开始音视频互动

在 initState() 方法中初始化声网音视频功能并开始实时音视频互动。

Dart
@override
void initState() {
  super.initState();
  initAgora();
}

结束音视频互动

按照以下步骤结束音视频互动:

  1. 调用 leaveChannel 离开当前频道,释放所有会话相关的资源。
  2. 调用 release 销毁引擎,并释放声网 SDK 中使用的所有资源。

    注意

    • 调用 release 后,你将无法再使用 SDK 的所有方法和回调。如需再次使用实时音视频互动功能,你必须重新创建一个新的引擎。详见初始化引擎。
      • 该方法为同步调用。需要等待引擎资源释放后才能执行其他操作,因此建议在子线程中调用该方法,避免主线程阻塞。
Dart
Future<void> _dispose() async {
  await _engine.leaveChannel(); // 离开频道
  await _engine.release(); // 释放资源
}

调试 App

按照以下步骤测试直播 App:

  1. 将目标设备连接到电脑。

  2. 打开终端,在项目路径下执行以下命令在目标设备上运行示例项目:

    Shell
    flutter run
  3. 启动 App,授予麦克风和摄像头权限,如果你将用户角色设置为主播,便会在本地视图中看到自己。

  4. 使用第二台设备,重复以上步骤,在该设备上安装 App、打开 App 加入频道,观察测试结果:

    • 如果两台设备均作为主播加入频道,则可以看到对方并且听到对方的声音。
    • 如果两台设备分别作为主播和观众加入,则主播可以在本地视频窗口看到自己;观众可以在远端视频窗口看到主播、并听到主播的声音。

以 Android 设备为例,编译成功后的 App 如下图所示:

后续步骤

  • 本文的示例使用了临时 Token 加入频道。在测试或生产环境中,为确保通信安全,声网推荐使用 Token 服务器来生成 Token,详见使用 Token 鉴权。
  • 如果你想要实现极速直播场景,可以在互动直播的基础上,通过修改观众端的延时级别为低延时 (audienceLatencyLevelLowLatency)实现。详见实现极速直播。

参考信息

示例项目

声网提供了开源的实时音视频互动示例项目供你参考,你可以前往下载或查看其中的源代码。

常见问题

相关文档