Pano开发者中心
  • 开发者中心
  • 下载中心

›音视频

新手入门

  • 简介
  • 名词解释
  • 创建第一个应用

规则说明

  • Channel ID命名规则
  • 权限控制
  • 计费说明
  • 频道最大时长说明
  • 每月一万分钟免费说明
  • 布局参数说明
  • 水印

场景方案

    教育行业

    • 1vN互动小班课
    • 互动直播大班课

快速接入

  • 简介
  • 音视频

    • Windows (C++)
    • iOS (Objective-C)
    • Android (Java)
    • Web
    • Electron
    • Flutter
    • React Native
    • Unity

    白板

    • Windows (C++)
    • iOS (Objective-C)
    • Android (Java)
    • Web
    • Electron
    • Flutter
    • React Native

高级功能(RTC)

  • 简介
  • 屏幕共享
  • 分组讨论
  • 状态回调
  • 设备诊断
  • 音量指示
  • 控制声音
  • 声卡操作
  • 混音/伴音
  • 混响
  • 耳返
  • 变声
  • 美颜
  • 音视频数据回调
  • 音视频外部采集
  • 收发多路视频
  • 多窗口渲染
  • 性能检测
  • 截图
  • 反馈

高级功能(RTS)

  • 简介
  • 白板

    • Windows (C++)
    • iOS (Objective-C)
    • Android (Java)
    • Web
    • Flutter

    标注

    • 视频标注
    • 共享标注
    • 外部标注

    消息

    • 消息服务

    远程控制

    • 远程控制

操作实践

  • 切换大小屏

RESTful API

  • 基本格式
  • 生成Token
  • 频道管理
  • 云端录制
  • CDN推流
  • 文档转码
  • 消息服务
  • 服务端消息通知

SDK API

  • SDK接口说明
  • Windows (C++)
  • macOS/iOS (Objective-C)
  • Android (Java)
  • Web SDK (IE专用版)
  • Web SDK

    • 浏览器兼容性
    • RtcEngine
    • GroupManager
    • RtcWhiteboard
    • RtsService
    • RtcMessage
    • Annotation
    • Constants

更新记录

  • 简介
  • Windows
  • macOS
  • iOS
  • Android
  • Electron
  • Flutter
  • React Native
  • Unity
  • Web(全功能SDK)
  • Web(RTS SDK)
  • Web(IE专用音视频SDK)

帮助

  • FAQ
  • 更多帮助

Flutter

本文以实现音视频通话为例,结合 SDK API 和示例代码,介绍如何快速接入。

  • 如需查看完整 SDK API 列表,请访问:pano_rtc library。
  • 请注意,Android 不支持模拟器调试,请使用真机。

导入SDK

在项目的 pubspec.yaml 文件的 dependencies 部分,配置:

dependencies:
  flutter:
    sdk: flutter
  ...
  # 请到 https://pub.dev 网站通过包名 Search packages 查看最新版本号,以下为示例。
  pano_rtc: ^1.0.4 # Pano SDK
  permission_handler: ^6.1.1 # 用于申请权限(麦克风、摄像头、存储等)
  wakelock: ^0.5.0+2 # 用于处理通话过程中屏幕常亮

  # 在需要使用 Pano SDK 进行音视频通话的地方配置:
  # import 'package:pano_rtc/pano_rtc.dart';
  # import 'package:permission_handler/permission_handler.dart';
  # import 'package:wakelock/wakelock.dart';

防止混淆

如果你的项目需要混淆,请在 android/app/proguard-rules.pro 文件中配置以下内容防止混淆 Pano SDK。

-keep class com.pano.**{*;}
-keep class video.pano.**{*;}

配置权限

配置 Android 权限

在 android/app/src/main/AndroidManifest.xml 文件的 manifest 根元素内添加:

<uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- 音频需要此权限 -->
<uses-permission android:name="android.permission.CAMERA" /> <!-- 视频需要此权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <!-- 音频需要此权限 -->
<uses-feature android:name="android.hardware.camera" /> <!-- 视频需要此配置 -->
<uses-feature android:name="android.hardware.camera.autofocus" /> <!-- 视频需要此配置 -->

配置 iOS 权限

在 ios/Runner/Info.plist 的 dict 标签内添加:

<key>NSMicrophoneUsageDescription</key>
<string>请修改为 App 需要使用麦克风的提示</string>

<key>NSCameraUsageDescription</key>
<string>请修改为 App 需要使用摄像头的提示</string>

申请权限

在需要使用 Pano SDK 进行音视频通话的地方配置:

// 关于 permission_handler 的用法,可以参考:https://pub.dev/packages/permission_handler
await [Permission.camera, Permission.microphone, Permission.storage].request();

屏幕常亮

通话过程中,通常需要屏幕常亮以防止系统锁屏。开发者如需实现屏幕常亮,可以参考「导入SDK」部分的介绍导入 Wakelock。

  • 在适当的时机(例如下文将提到的"自己加入频道成功"后)调用:Wakelock.enable(); 启用屏幕常亮;
  • 在离开频道时,调用 Wakelock.disable(); 取消屏幕常亮;
  • 关于 Wakelock 的更多介绍,请查看 pub.dev 网站。

初始化

通过 RtcEngineKit 的 engine(RtcEngineConfig config) 方法初始化实例。

static String appId = '...'; // 替换为你的应用ID
static RtcEngineConfig rtcEngineConfig = RtcEngineConfig(appId);
...
rtcEngineKit = await RtcEngineKit.engine(rtcEngineConfig);
  • 请登录 Pano控制台,点击左侧导航 应用管理 ,查看应用ID(即 appId)。

注册通知

通过 RtcEngineKit 实例的 setEventHandler(RtcEngineEventHandler handler) 方法来处理 Pano SDK 返回的通知。

注意:必须尽早注册通知,以免错过某些通知。

rtcEngineKit.setEventHandler(RtcEngineEventHandler(
    onChannelJoinConfirm: (ResultCode result) async {
        // 自己加入频道的通知
    },
    onChannelLeaveIndication: (result) async {
        // 自己被动离开频道的通知
    },
    onChannelCountDown: (remain) async {
        // 频道倒计时通知
    },
    ...
));

完整的回调方法列表,请查看 RtcEngineEventHandler。

加入频道

加入频道

通过 RtcEngineKit 实例的 joinChannel 方法加入频道。

static String token = '请替换为实际的token';
static String channelId = '请替换为实际的channelId';
static String userId = '请替换为实际的userId';
...
RtcChannelConfig rtcChannelConfig = RtcChannelConfig(
    // mode: ChannelMode 频道模式,OneOnOne 一对一模式 / Meeting 会议模式
    // 如果有 Web 端参与,或者需要进行直播/录制,请设置为 ChannelMode.Meeting
    mode: ChannelMode.Meeting,
    /* serviceFlags 频道标志:
       ChannelService.Media 音视频
       ChannelService.Whiteboard 白板
       ChannelService.Message 消息
    */
    serviceFlags: {ChannelService.Media, ChannelService.Whiteboard, ChannelService.Message},
    subscribeAudioAll: true, // 自动订阅音频,可以配置为 false 来主动订阅音频(关闭自动订阅)
    userName: '请替换为实际的userName'  // 用户名,可选参数,可为空,建议配置以区分不同用户
);
var result = await rtcEngineKit.joinChannel(token, channelId, userId, config: rtcChannelConfig);
if (result != ResultCode.OK) {
    // 调用失败,请根据 ResultCode 进行处理
}
  • 另请参考 名词解释 了解 channelId、token、userId、userName 的作用。
  • userId 号段 [0xFFFEFF0000000000, 0xFFFEFFFFFFFFFFFF] (18446461499221213184 - 18446462598732840959) 保留给 PANO 内部使用,开发者请勿使用 ,否则会返回错误。
  • 可以使用 临时token 来进行临时测试。

自己加入频道的通知

调用 joinChannel 方法后,将触发 onChannelJoinConfirm 通知。

onChannelJoinConfirm: (result) {
    // result 表示自己加入频道的结果
}

joinChannel (加入频道) 接口返回的 ResultCode 仅表示调用该接口的结果,而 onChannelJoinConfirm (自己加入频道的通知) 返回的 result 表示和服务器交互后的结果。
也就是说当 onChannelJoinConfirm 返回 ResultCode.OK 才表示加入频道成功。

其他用户加入频道的通知

其他用户加入频道后,将触发 onUserJoinIndication 通知。

onUserJoinIndication: (userId, userName) {
    // 其他用户加入频道的通知。userId 和 userName 都是该用户在 joinChannel 时传入的
    // 此时可以将其加入到与会者列表中
}

倒计时通知

加入频道后,如果存在倒计时限制,将触发 onChannelCountDown 通知。

onChannelCountDown: (remain) {
    // 频道倒计时通知,单位:秒;请保存用于展示倒计时,此回调仅在加入频道后回调一次
}
  • 已实名认证,并且使用正式token,Pano不限制频道时长
  • 未实名认证,或者使用临时token,最大频道时长为 30 分钟

操作视频

发送本地视频

通过 RtcEngineKit 实例的 startVideo 方法发送本地视频。

RtcRenderConfig localRenderConfig = RtcRenderConfig(
    profileType: VideoProfileType.HD720P, // 分辨率:1280 x 720,实际使用请按需配置
    sourceMirror: false, // 采集是否镜像
    scalingMode: VideoScalingMode.Fit,
    mirror: true // 渲染是否镜像
);
/* profileType 和 sourceMirror 会同时影响发送和渲染,scalingMode 和 mirror 只影响渲染不影响发送
   sourceMirror 和 mirror 只要其中一个为 true,本地渲染即为镜像模式
*/
/* 调用 startVideo 方法后,其他用户才能看到你的画面;请在 onChannelJoinConfirm 回调加入频道成功后再调用
   config 参数是可选的,不配置将使用默认值
*/
await rtcEngineKit.startVideo(localView, config: localRenderConfig);

startVideo 设置的分辨率(VideoProfileType)表示期望的发送分辨率,实际过程中可能会因硬件支持情况、网络情况和订阅情况触发 SDK 自动调整而降低(后文会介绍订阅)。

切换摄像头

通过 RtcEngineKit 实例的 isFrontCamera 方法判断是否是前置摄像头,switchCamera 方法切换摄像头。

await rtcEngineKit.switchCamera(); // 此方法将切换发送出去的摄像头画面

停止发送本地视频

通过 RtcEngineKit 实例的 stopVideo 方法停止发送本地视频。

await rtcEngineKit.stopVideo(); // 调用此方法后,其他用户将看不到你的画面

其他用户开启视频的通知

当其他用户发送视频时,将触发 onUserVideoStart 通知。

onUserVideoStart: (userId, maxProfile) {
    // maxProfile 表示该用户的最大可发送分辨率
    // 取决于 摄像头支持的最大分辨率 和 设置的发送分辨率 这两个值中的较小值
}

订阅其他用户的视频

通过 RtcEngineKit 实例的 subscribeVideo 方法订阅其他用户的视频。

// 请在收到其他用户的 onUserVideoStart 通知后,再调用订阅
// 返回 ResultCode.OK 表示接口调用成功,否则表示失败
RtcSurfaceViewModel remoteView;
RtcRenderConfig remoteRenderConfig = RtcRenderConfig(
    // 可以根据显示窗口的大小来决定订阅分辨率,比如大窗口订阅高分辨率,小窗口订阅低分辨率
    profileType: profileType,
    sourceMirror: false,
    mirror: false,
    scalingMode: VideoScalingMode.Fit
);
...
onUserVideoStart: (userId, maxProfile) async {
    remoteRenderConfig.profileType = maxProfile;
    var result = await rtcEngineKit.subscribeVideo(userId, remoteView, config: remoteRenderConfig);
}
  • Pano采用订阅模式来接收视频,参与者之间需要相互订阅,才可以看到彼此的视频画面。
  • 默认 正式token 最多可以订阅 10 路视频,临时token 最多可以订阅 3 路视频。
  • 如果订阅失败,会触发 onUserVideoSubscribe 通知。

视频首帧的通知

当自己发送或收到其他用户第一个视频帧时,将触发 onFirstVideoFrameRendered 通知。

onFirstVideoFrameRendered: (userId) {
    // 第一个视频帧通知,可以开始显示视频画面
}

取消订阅其他用户的视频

通过 RtcEngineKit 实例的 unsubscribeVideo 方法取消订阅其他用户的视频。

await rtcEngineKit.unsubscribeVideo(userId); // 调用此方法后,你将看不到该用户的画面

当其他用户停止视频或者离开频道的时候,将被自动取消订阅。

操作声音

发送本地声音

通过 RtcEngineKit 实例的 startAudio 方法发送本地声音。

await rtcEngineKit.startAudio(); // 调用此方法后,其他用户才能听到你的声音;请在加入频道成功后再调用

停止发送本地声音

通过 RtcEngineKit 实例的 stopAudio 方法停止发送本地声音。

// 调用此方法后,其他用户将听不到你的声音
// 不影响你接收其他用户的声音
// 可以调用 startAudio 重新发送
await rtcEngineKit.stopAudio();

静音麦克风

通过 RtcEngineKit 实例的 muteAudio 方法静音本地麦克风。

await rtcEngineKit.muteAudio(); // 调用此方法后,其他用户将听不到你的麦克风的声音

停止发送本地声音(stopAudio) 和 静音本地麦克风(muteAudio) 这两个接口都可以将自己静音(不让其他用户听到你的声音)。它们的区别在于:
1 "停止发送本地声音"会断开音频通道连接(同时停止发送麦克风和伴音的声音,会取消其他用户订阅你的声音,如需重建连接需要消耗时间)
2 "静音本地麦克风"会发送静音包(不影响伴音发送,不影响订阅关系,静音包数据量很小,临时静音建议使用此方式,取消静音能够迅速恢复发送声音)

取消静音麦克风

通过 RtcEngineKit 实例的 unmuteAudio 方法取消静音本地麦克风。

await rtcEngineKit.unmuteAudio(); // 静音麦克风后,需要取消静音,其他用户才能听到你的麦克风的声音

其他用户开启声音的通知

当其他用户发送声音时,将触发 onUserAudioStart 通知。

onUserAudioStart: (userId) {
    // 其他用户开启声音的通知
}

订阅其他用户的声音

如果在 joinChannel (加入频道)时,配置了自动订阅音频(config 中 subscribeAudioAll: true),则开发者无需再主动订阅其他用户的声音。否则,需要通过 RtcEngineKit 实例的 subscribeAudio 方法订阅其他用户的声音。

// 如果 加入频道 时配置了自动订阅音频,则无需调用此接口
// 请在收到其他用户的 onUserAudioStart 通知后,再调用订阅
await rtcEngineKit.subscribeAudio(userId);
  • 如果希望在通话过程中,不收听某位与会者,或者不收听所有其他与会者,请在加入频道时,设置不自动订阅音频;随后按需订阅或取消订阅某位或所有其他与会者。
  • 如果订阅失败,会触发 onUserAudioSubscribe 通知。

收到其他用户声音的通知

当收到其他用户的声音时,将触发 onFirstAudioDataReceived 通知。

onFirstAudioDataReceived: (userId) {
    // 收到其他用户的首个声音数据包
}

取消订阅其他用户的声音

通过 RtcEngineKit 实例的 unsubscribeAudio 方法取消订阅其他用户的声音。

await rtcEngineKit.unsubscribeAudio(userId); // 调用此方法后,你将听不到该用户的声音

当其他用户停止声音或者离开频道的时候,将被自动取消订阅。

离开频道

离开频道

通过 RtcEngineKit 实例的 leaveChannel 方法离开频道。

await rtcEngineKit.leaveChannel();

注意:调用此接口主动离开频道,自己不会收到 onChannelLeaveIndication 回调。

其他用户离开频道的通知

其他用户离开频道后,将触发 onUserLeaveIndication 通知。

onUserLeaveIndication: (userId, reason) {
    // 可将其从与会者列表中移除
}

释放资源

通过 destroy 方法销毁 RtcEngineKit 实例。

await rtcEngineKit.destroy();

反馈问题

我们强烈建议您集成反馈功能,以便用户遇到问题时,可以提交信息给我们分析排查,具体请 点此查看。

SDK API 指南

本文仅介绍接入Pano Flutter SDK实现视频通话的基本流程和接口。
实际场景可能需要结合使用更多接口,请 点此查看 API 列表。

示例代码

为方便开发者了解丰富的接口使用方式,我们还提供示例代码,请体验参考:

  • GitHub
  • Gitee
Last updated on 2022/3/23
← ElectronReact Native →
  • 导入SDK
  • 防止混淆
  • 配置权限
    • 配置 Android 权限
    • 配置 iOS 权限
    • 申请权限
  • 屏幕常亮
  • 初始化
  • 注册通知
  • 加入频道
    • 加入频道
    • 自己加入频道的通知
    • 其他用户加入频道的通知
    • 倒计时通知
  • 操作视频
    • 发送本地视频
    • 停止发送本地视频
    • 其他用户开启视频的通知
    • 订阅其他用户的视频
    • 视频首帧的通知
    • 取消订阅其他用户的视频
  • 操作声音
    • 发送本地声音
    • 停止发送本地声音
    • 静音麦克风
    • 取消静音麦克风
    • 其他用户开启声音的通知
    • 订阅其他用户的声音
    • 收到其他用户声音的通知
    • 取消订阅其他用户的声音
  • 离开频道
    • 离开频道
    • 其他用户离开频道的通知
  • 释放资源
  • 反馈问题
  • SDK API 指南
  • 示例代码
浙ICP备20002645号 ©2019-2022 Pano拍乐云