Agora SDK 常见问题Q&A —— 集成与使用篇

该部分包含集成和使用 Agora SDK 过程中常见的问题。

音频相关

iOS 端集成 H5 游戏音量低

背景信息: iOS SDK 2.2.0 集成 H5 游戏。

问题现象: 用 layabox 自带的引擎播放 WkWebview,主播加入声网的频道,游戏里面的声音很低。该问题仅在 iOS 端发现,Android 端表现正常。

问题原因: WKWebView 加载的 H5 是另外一个进程通过 AVAudioSession 播放声音,不是通过 SDK 播放的。

解决方案:
self.agoraEngine setAudioProfile:(AgoraRtc_AudioProfile_Default) scenario:(AgoraRtc_AudioScenario_GameStreaming);//选择 GameStreaming 模式。

方案缺点:

  • 采用 GameStreaming 模式可能会出现一点回声,理论不影响使用,如有必现或大概率复现的情况可联系技术支持。
  • H5 的声音不是通过 SDK 播放的,无法消除回声。

Android 9 设备上应用退到后台或锁屏后,采集不到声音或视频

背景信息: Android 9 系统行为变更。

问题现象: Android 9 设备锁屏 1 分钟内,音频无声或看不到视频。

问题原因: 从 Android 官网来看,这是系统强制限制。原文如下:

**Limited access to sensors in background**
Android 9 limits the ability for background apps to access user input and sensor data. If your app is running in the background on a device running Android 9, the system applies the following restrictions to your app:

* Your app cannot access the microphone or camera.
* Sensors that use the continuous reporting mode, such as accelerometers and gyroscopes, don't receive events.
* Sensors that use the on-change or one-shot reporting modes don't receive events.
If your app needs to detect sensor events on devices running Android 9, use a foreground service.

详见 Android 行为变更

解决方案: 目前 Android 官网没有明确说明后台采集声音或视频应如何处理,但使用 前台服务 可以让应用正常工作。

如果 Android 9 设备用户有锁屏后采集音频或视频的需求,可以在锁屏或退至后台前起一个 Service,并在退出锁屏或返回前台前终止 Service。
关于如何起 Service,请参考 https://developer.android.com/reference/android/app/Service

Android 设备进入频道后,耳机无声/语音路由不正常

背景信息 :采用 Agora Android Demo 的模式,使用 WorkerThread 来维护 Agora RtcEngine 的实例。

问题现象 :进频道后安卓设备上耳机无声,路由功能不正常等。

问题原因

有些 Agora 的 Android 示例程序通过创建 WorkerThread 线程来维护一个全局的 RtcEngine 实例。WorkerThread 的生命周期与示例程序的生命周期是一致的。当应用程序进程销毁(调用 destroy 方法),WorkerThread 也随之消亡。

如果开发者没能正确退出 WorkerThread,就有可能会导致耳机无声,或语音路由不正常等问题。

在实际的应用开发中,开发者会通过操控 WorkerThread 来管理 RtcEngine 实例的生命周期。在创建引擎和加入频道时这么做是可以的。但是开发者在离开 WorkerThread 时,没有销毁 RtcEngine 实例。如果 WorkerThreader 和应用程序的生命周期不一致,这就很容易产生问题。

RtcEngine 调用 destroy 方法会移除所有注册过的系统 Listener (对于音频来说是 PhoneStateListener),这些监听可能会引用线程的 Looper。如果在退出 WorkerThread 时不移除系统 Listener,注册过的 Listener 会持续监听,但其引用的 Looper 已经随着 WorkerThread 线程的停止而被置为无效或清空。最终会以 Dead Binder 的形式出错。

解决方案

Agora 建议你选择如下一种方法解决该问题:

  • 全局只维护一个 WorkerThread 线程
  • 退出频道时,还需要调用 destroy 方法销毁 RtcEngine
视频相关

我该如何选择视频分辨率、帧率、码率?

通常来讲,视频参数的选择要根据产品实际情况来确定,比如,如果是 1 对 1,用户的窗口比较大,要求分辨率会高一点,随之帧率和码率也要高一点;如果是 1 对 4,用户的窗口比较小,分辨率可以低一点,对应的码率帧率也会低一点,以减少编解码的资源消耗和缓解下行带宽压力。一般可按下列场景中的推荐值进行设置。

  • 2 人视频通话场景:
    • 分辨率 320 * 240、帧率 15 fps、码率 200 Kbps
    • 分辨率 640 * 360、帧率 15 fps、码率 400 Kbps
  • 多人视频通话场景:
    • 分辨率 160 * 120、帧率 15 fps、码率 65 Kbps
    • 分辨率 320 * 180、帧率 15 fps、码率 140 Kbps
    • 分辨率 320 * 240、帧率 15 fps、码率 200 Kbps

如果你希望自定义视频参数,比如调高码率以保证视频质量,也可以使用 setVideoEncoderConfiguration 对各参数进行自定义设置。高分辨率、帧率、码率会提高视频的清晰度,但同时也可能导致卡顿,并引起计费增加。

直播场景中通常需要较大码率来提升视频质量。因此 Agora 建议将直播码率值设为通信值的 2 倍。详见设置码率

直播相关

直播中如何踢人?

目前 App 可以支持服务端踢人功能。具体用法可参考 Dashboard RESTful API

如何调整旁路直播的布局?

请参考各平台 API 文档中 setLiveTranscoding 接口的描述。

为什么推流录制的最后出现 30 秒的卡顿?

为了防止主播断线或临时退出加入等情况造成 RTMP 断流,录制服务默认会预留 30 秒用于缓冲静态数据,在主播退出 30 秒后才完全退出推流录制。

使用 CDN 测试地址时,为什么会有跨域问题?

测试地址使用的域名主要应用在测试环境,由于 CDN 上没有配置 cross.xml,因此会有跨域问题出现。

是否支持主播多路视频同时直播显示?

是的,实现方法如下:

  • APP 负责采集屏幕和主播摄像,把屏幕和主播摄像混合成一路输入 Agora SDK。Agora 不建议使用 SDK 自带的截屏输出流、合图后再输入的方式实现,因为会有额外的效率损失。关于 PC 端屏幕采集的原理 Agora 会提供技术支持。
  • 主播在 PC 端进行直播的同时,在手机 APP 端主播以嘉宾的身份登录,把手机视频以嘉宾连线方式进入小窗口。
  • PC 端应用程序用嘉宾连线的方式,把主播的一路视频连入直播室。
游戏相关

我在使用 Unity3D 5.4 编译代码示例时,为什么报错?

由于 Agora 提供的代码示例使用的是 Unity3D 5.5,所以当你使用 Unity3D 5.4 时,可能会出现以下问题:

  • CheckConsistency: GameObject does not reference component MonoBehaviour. Fixing. 当报这个错误时,删除掉项目当中的 HelloUnity3D 这个场景 (scene),新建一个同名的场景,然后把 HelloUnity3D.cs 添加到该场景上
  • 导出 Google Android Project (ADT) 编译通过,但是运行的时候崩溃。当出现这个问题时, 请确保权限是否都正常,将子模块 AgoraAudioKit.pluginAndroidManifest.xml 拷贝到自己的项目当中

AMG SDK 使用的是 Unity Plugins 机制集成,更多问题,建议认真阅读 相关文档

在 iOS 平台上编译代码示例时,为什么会出现签名出错?

如果报下图左边的错误时,请按照下图右边的方式解决该问题:

在 iOS 平台上编译代码示例时,为什么会出现 bitcode 出错?

如果在编译过程出现以下 bitcode 报错信息,请关闭 bitcode:

关闭方式如下:

  1. 选中当前 Target
  2. 选择 Build Settings
  3. 选择 Enable Bitcode ,并将其设置为 No。

在 iOS 平台上编译代码示例时,为什么会出现 core-telephony 出错?

当出现下图左边的错误时,请添加下图右边的 framework:

在 iOS 平台上编译代码示例时,为什么会出现 libresolv 出错?

当出现下图左边的错误时,请添加下图右边的所需库:

在编译 Unity 代码示例时,我该如何导出 gradle 项目?

完成 实现游戏语音功能 的编译步骤后,请根据实际需要使用如下命令进行编译(须根据自己环境修改命令):

/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/bin/java -classpath 
"/Applications/Unity/PlaybackEngines/AndroidPlayer/Tools/gradle/lib/gradle-launcher-2.14.jar" 
org.gradle.launcher.GradleMain "clean" "assembleDebug"

如何让通话音量、控制也都走媒体音量系统?

优点

进出频道,不改变游戏原来的设置。

使用方法

setParameters 是 SDK 句柄的方法。 在 joinChannel 之前,在不同平台上,调用一下相应的设置。

iOS

setParameters("
 {\\"che.audio.use.remoteio\\":true}
 ");

Android

mRtcEngine.setParameters("
{\\"che.audio.audioMode\\":0}
");
mRtcEngine.setParameters("
{\\"che.audio.recordingDevice\\":1}
 ");
mRtcEngine.setParameters("
{\\"che.audio.stream_type\\":3}
 ");

副作用

通话音量不起作用,回声消除算法没法使用(如果场景中不涉及连麦,则不会有影响)。 通话音量、控制也都走媒体音量系统。
在连麦中,出现回声、噪音等问题,由于没有使用声网音频相关算法,没法解决。

Unity 发生 DllNotFoundException?

通常是以下几点可能的原因:

  • 使用编辑器调试,或者 Windows 调试的 , 我们 默认不提供 Windows SDK ,所以不支持 mac 或者 Windows 直接调试。
  • SDK 不完整,通常直接建议客户把官网下载的 Demo 的 Plugin 直接添加到工程中。

iPhone 手机上的静音物理按键能否静音游戏中的语音?

不能,iOS 系统设计行为。
iOS上语音通话,Category 一定是 AVAudioSessionCategoryPlayAndRecord。此 Category,静音物理按键不能静音。请参照:Audio Session Categories and Modes
iOS 7 以后的系统已经去掉了静音物理按键的回调,App 也没法监听到该事件。

录制相关

怎么检测录音权限?

  • iOS/macOS 平台上:首次运行系统会提示打开录音权限。如被手工关闭后开发者可以查询系统接口 AVAudioSession.sharedInstance().recordPermission()[iOS8.0+] 来检测录音权限。
  • Android 平台上:比较复杂,因为各个厂家的实现不一,并没有统一的手段可以检测到所有手机的录音权限。Agora Native SDK 会尝试检测录音失败并且上报 ERR_ADM_RECORD_AUDIO_FAILED (1018) 错误码,但未必能覆盖所有机型。

你的 App 可以通过此上报错误码来提示用户检测录音权限。

音视频通话时我可以录音吗?

我们提供录音功能,可以通过 API 将录音文件直接存储到开发者指定的服务器上。

我到底该用一种录制方案, 录制 SDK, 录制服务,还是 CDN 直播录制?

推荐所有的新用户使用录制 SDK 版,其他方案均已被弃用。

录制的触发是由 Linux 服务器控制的吗?

是的。

由于服务器自己触发录制,那它怎么知道什么时候加入频道,频道号等?

通过你自己的信令。

当录制 SDK 加入频道时,API 的行为与客户端使用 Agora Native SDK 调用 API 的行为类似。

录制完成动作如何捕获

自动模式录制:如果频道内没有人,当idle时间到,则停止录制,然后 leaveChannel 离开频道。应用侧监控 leaveChannel 则表示录制完成,可以转入下一步处理逻辑:例如录制完成后把录制文件上传到其他服务器上等。

录制文件保存目录及文件如何自定义

可以自定义,需要单独配置 cfg 文件。SDK 包中 Agora_Recording_SDK_for_Linux_FULL/samples/cpp 下面有一个隐藏文件.cfg.json,可以参考设置输出文件路径,文件名的方法。

具体链接:https://docs.agora.io/cn/Recording/recording_cpp?platform=C++

例如:目录文件名需要按照“根目录/年月日/channelId/uid.aac”方式保存: 按照如下方式配置/home/Agora_Recording_SDK_for_Linux_FULL/samples/recording_output。

是否可以针对频道内的某个用户进行录制

不行。会录下所有有音频或者视频的用户。

录制的频道模式必须和 Native SDK 或 Web SDK 设置的频道模式保持一致吗?

对,如果不一致,可能会引发问题。

当使用命令行进行录制时,如何停止录制?

当使用命令行进行录制时,会在以下情况下停止录制:

  • 在命令行运行时,在键盘上同时按下 Ctrl 和 C 键结束进程。
  • 当你设置参数 idle (设置空闲频道超时退出时间) 的值后,如果频道内无用户的状态超过设定的时间,录制程序自动退出。默认值为 300 秒。

在使用命令行工具集成录制 SDK 时,报错 java.land.UnsatisfiedLinkError: no recording in java.library.path,如何解决?

报错原因:系统环境找不到 librecording.so 库文件。

解决方法:确认 Java demo 是否成功编译并生成了库文件,查看并配置库文件的位置。

例如,若库文件位置为 /home/user/Desktop/tool/Agora_Recording/samples/java/bin/io/agora/recording/librecording.so,则在 Linux 系统下,在 /etc/profile 或者 ~/.bash_profile、~/.bashrc 下配置 LD_LIBRARY_PATH

LD_LIBRARY_PATH=/home/user/Desktop/tool/Agora_Recording/samples/java/bin/io/agora/recording/librecording.so

不同系统与程序配置 java.library.path 的方法请参考修改java.library.path的位置

Web SDK相关

视频过程中,如何更换音视频输入设备?

通过枚举系统设备接口 getDevices 可以获取用户的音视频输入输出设备。很多用户想要不选择设备,直接用默认识别到的第一个,可以直接在 createstream 接口中把 cameraIdmicrophoneId 填为""。用户也可以自己创建对象数组来管理本地设备(通过 kind 中的类型分类)。请注意 cameraIdmicrophoneId 不是唯一确定的而是随机生成的,部分情况下这个 ID 可能改变。所以目前音视频中途更换设备,需要关掉流之后,重新 getDevice ,来建立新流。

如何开启双流模式?

开启双流模式 接口 enableDualStream ,发送端调用这个接口开启双流,接收端订阅了流之后用 setRemoteVideoStreamType() 随时切换大小流。小流参数可用 setLowStreamParameter() 来设置。

Native SDK相关

踢人API

功能介绍

Restful 踢人 API: https://api.agora.io/dev/v1/kicking-rule ,具体使用方法请参见 Dashboard RESTful API

适用场景

遇到炸房等紧急场景,可以使用Restful踢人API将捣乱者踢出,维持频道内正常秩序。

不适用场景

由于 Restful 踢人 API 使用媒体后台信令,因此不建议用户大批量频繁调用,如果用户期望通过踢人 API 实现结束录制,建议客户在应用层实现。

两人语音聊天室集成 FAQ

客户场景

社交行业 LB 客户:1 v 1 音频聊天室,通信模式,客户集成代码简单,对错误回调或者质量参数缺少监控,问题发生时无法快速定位。

集成问题及解决方案

频道内用户听对方声音小

问题原因:用户使用通信模式,通信模式默认走听筒,公放场景客户不点公放,通话音量路由不会切换到扬声器,容易造成用户听声音特别小。

解决方案:建议用户设置 setEnableSpeakerphone :YES,将默认路由设置为扬声器。

业务部门反馈声音效果差,技术部门缺少录音验证

问题原因:客户对质量参数没有进行监控

解决方案:

  • 监控 onFirstLocalAudioFrame 验证本地推流是否成功;
  • 监控 onFirstRemoteAudioFram 验证远端拉留是否成功;
  • 监控 onRtcStats 收集上行发送码率,下行接收码率,流量,客户端 CPU 使用率;
  • 监控 onAudioVolumeIndication 收集频道内用户音量值,判断客户端采集音量是否正常;
  • 监控 onRecordFrame 验证音频前处理阶段麦克风采集的声音是否有问题。

onError 中重复调用 leaveChannel 导致报错 ERR_LEAVE_CHANNEL_REJECTED = 18?

问题原因:声网一个 joinChannel 对应一个 leaveChannel ,如果调用多次 leaveChannel 会导致 ERR_LEAVE_CHANNEL_REJECTED = 18 错误。

解决方案:检查应用逻辑,同时增加 onError 错误判断,如果有 ERR_LEAVE_CHANNEL_REJECTED = 18 则不再执行 leaveChannel 避免死循环。

小程序SDK相关

推流/拉流处理

推流/拉流处理可以参考或直接使用 Github 上开源代码

退后台处理

可以通过设置小程序的 live-pusher 组件中的 waiting-image 属性来处理。设置后,推流端退到后台时,可以推送静态图片来维持推流,其他端会收到本端预设的 waiting-image 图片来代替视频流。 除非通过一些方式 (例如后台播放背景音乐),小程序会在某些场景下断开 websocket 或者 rtmp 连接,例如点击右上角按钮将程序退到后台。这种情况下,若回到前台后收到 error code 904 或 501,则应使用 SDK 进行重连,具体方法请参考 重新加入频道 rejoin 中的描述。

只启用小程序的音频功能,不需要发送视频,应该如何设置?

直接使用微信小程序的接口处理即可。在小程序的 live-pusher 组件中,通过设置 enable-camera 来实现开启/关闭摄像头。详见 小程序 live-pusher 组件文档

小程序和 Native 互通有问题?

在使用小程序 SDK 过程中,请确保已在 Native 端调用如下接口完成设置,否则可能会出现无法互动,Native 端听不到小程序声音等问题:
请调用设置用户角色 setClientRole,并将 Role 设置为 AgoraClientRoleBroadcaster = 1:主播;

小程序和 Web 互通时,Web 端可以看到小程序的视频,但小程序看不到 Web 端的视频?

Web 与小程序互通时,Web 端只支持 H264 模式的编码,不支持 VP8。将 Web SDK 的 index.html 文件修改为如下设置即可:
client = AgoraRtc.createClient({mode: 'h264_interop'});

小程序的 live-pusher 组件里的 src 应该写什么?

客户端调用 client.publish 方法后,会回调一个以 rtmp 开头的临时地址,这个地址就分别是 live-player 和 live-pusher 组件中的 rtmp 播放地址 和 rtmp 推流地址。

集成小程序 SDK 时,如何打开和保存日志?

调用如下 API 实现保存和打开日志:

  • 保存日志:
AgoraMiniappSDK.LOG.onlog = (text) => {
Utils.log(text);
};
  • 打开日志:
    AgoraMiniappSDK.LOG.setLogLevel(-1);

出现客户端初始化失败之后,该如何做?

  1. 退出后重新加入频道;
  2. 如果步骤 1 无法生效,请换台设备试试;
  3. 如果步骤 2 仍旧无效,请联系客户支持。

出现错误码

Agora Miniapp SDK for WeChat 在调用 API 或运行时,可能会返回一个错误码对象,也可能会返回一个错误码。详细可以参考 错误代码和警告代码 进行排查。

SDK对断网、杀进程的处理

声网 SDK 有断线重连机制吗?

断线一般分两种情况:断网、进程被杀。

断网

假设有 A, B 两个用户处于同一个频道内进行音视频直播 / 通话,通话过程中 A 用户失去了网络连接。

  1. A 失去网络连接(A 用户在 4 秒内没有收到服务器数据):
  • 如果 A 是 Android, Windows,或 Linux 平台,A 有回调: onConnectionInterrupted
  • 如果 A 是 iOS 或 mac 平台: rtcEngineConnectionDidInterrupted
  • 如果 A 是 Web 平台,A 没有回调。
  1. 失去连接后, A 尝试重连其他服务器,直到重连成功:
  • 如果 A 在 10 秒内未连接成功,会有回调:
    • 如果 A 是 Android, Windows,或 Linux 平台: onConnectionLost
    • 如果 A 是 iOS 或 mac 平台: rtcEngineConnectionDidLost
    • 如果 A 是 Web 平台,A 没有回调。
  • 如果 B 在一定时间内没有收到 A 的包,B 有回调:
    • 如果 B 是 Android, Windows,或 Linux 平台,20 秒内没有收到 A 的包: onUserOffline
    • 如果 B 是 iOS 或 mac 平台,20 秒内没有收到 A 的包: didOfflineOfUid
    • 如果 B 是 Web 平台,10 秒内没有收到 A 的包: client.on('stream-removed')
  • 如果 A 重连成功:
    • 如果 A 是 Android, Windows,或 Linux 平台,A 有回调: didRejoinChannel
    • 如果 A 是 iOS 或 mac 平台,A 有回调: didRejoinChannel
    • 如果 A 是 Web 平台,A 没有回调。如果此前 B 未收到 A 重连失败的回调,B 不会因为 A 重连成功而收到回调;如果此前 B 已经收到 A 重连失败的回调,则此时 B 有回调:
    • 如果 B 是 Android, Windows,或 Linux 平台: onUserJoined
    • 如果 B 是 iOS 或 mac 平台: didJoinedOfUid
    • 如果 B 是 Web 平台: client.on('stream-added')

进程被杀

进程被杀包括以下各种情况:

  • 通信模式/直播模式
  • 打开/关闭 voip 模式
  • 前台/后台运行时进程被杀
  • 网页关闭(Web 端)

假设有 A, B 两个用户处于同一个频道内进行音视频直播/通话。
当 A 进程被杀:

  • 如果 A 是 iOS 或 mac 平台:A 自动触发 leaveChannel ,B 有回调:
    • 如果 B 是 Android, Windows,或 Linux 平台: onUserOffline
    • 如果 B 是 iOS 或 mac 平台: didOfflineOfUid
    • 如果 B 是 Web 平台: client.on('peer-leave')
  • 如果 A 是 Android, Windows,或 Linux 平台,且 B 使用的是 Native SDK:
    • 如果 20 秒内, A 没有重启 app 并加入原频道,B 有回调:
      • 如果 B 是 Android, Windows,或 Linux 平台: onUserOffline
      • 如果 B 是 iOS 或 mac 平台: didOfflineOfUid
    • 如果 20 秒内, A 重启 app 并加入原频道,B 不会收到回调。
  • 如果 A 是 Android, Windows,或 Linux 平台,且 B 使用的是 Web SDK:
    • 如果 10 秒内, A 没有重启 app 并加入原频道,B 有回调: client.on('stream-removed')
    • 如果 10 秒内, A 重启 app 并加入原频道,B 不会收到回调。
  • 如果 A 使用的是 Web SDK,进程被杀与掉线的行为是一样的。
  • 如果 A 是频道内最后一个用户,服务端会在 10s 后销毁频道
其它常见问题

Android 平台常见问题

集成 SDK 后,点击 App 中视频小窗口没有反应,也无法拖动,我该怎么办?

检查系统上有没有开启悬浮窗权限。如果没有开启该权限,App 是无法启动小窗口的。

可以在 Android 设备上做 64 位兼容吗?

取决于你使用的 Agora Native SDK 版本:

  • 如果你使用的是 1.7.4 版 (或更高版本) Agora Native SDK:
    Agora Native SDK 目前支持 64 位的 ARM 架构,只需将 arm64-v8a 里面的文件(位于 SDK 包内)拷贝至项目对应的 arm64-v8a 路径下。目前不支持 x86_64 架构直接运行,不过可以以 x86 方式兼容运行。具体做法就是在 64 位的 x86 设备上保证 App 里面没有 x86_64 目录。
  • 如果你使用的是 1.7.4 版之前的 Agora Native SDK:
    Agora Native SDK 目前只提供 32 位 native 库(armeabi-v7a),在 64 位设备上,Android 支持以 32 位进程模式启动 App,因此 Agora Native SDK 也可以在 64 位 Android 设备上使用,但必须保证 App 的 arm64 目录为空。否则 Android 系统将以 64 位进程模式加载 App,由于 Agora Native SDK 没有提供 64 位库,App 启动会失败。

由于目前 Android 的主流还是 32 位设备,一般各厂商都会提供 32 位库,因此一般来说,在 64 位 Android 设备以 32 位进程模式启动一般不会有问题。但是如果在某些 64 位平台上出现了这样的错误: java.lang.UnsatisfiedLinkError: dlopen failed: ”libHDACEngine.so”

但是如果 64 位平台上出现以下报错: java.lang.UnsatisfiedLinkError: dlopen failed: “libHDACEngine.so”

可能的原因:

在安装 App 的时候,系统会按照 Build.SUPPORTED_ABIS 去查找 App 的 lib 目录下的 native 库的目录(现有的 ABI: armeabi, armeabi-v7a,arm64-v8a, x86, x86_64, mips64, mips)。如果在 App 中有兼容 64-bit 的目录但是又缺少库文件的话,并不会使用其他 ABI 目录下的库文件替换所缺少的库文件进行安装,这些库不混合使用,也就是说需要为每个架构提供对应的库文件。Android 在加载 native 库的时候有回退(fallback)机制,在 64 位系统上如果 App 并不存在 arm64-v8a 的目录,则会尝试寻找 armeabi-v7a 下面的库进行加载,一般来说是向下兼容的。

解决方案:

  • 方法 1: 在构建应用程序的时候,在工程 (project) 里删除所有 arm64-v8a 下面的库以及该目录;在生成 App 后,确认 App 的包内 lib 下没有 arm64-v8a 的目录。
  • 方法 2: 在 gradle 构建文件中设置 abiFilters,只打包 32 位架构的库:
android {
        ...
        defaultConfig {
        ...
        ndk {
        abiFilters "armeabi-v7a","x86"
        }
        }
        }

为什么我会收到到错误消息: Failed to crunch file?

当您在使用 Android Open Video Call demo 时,如果遇到以下错误消息,例如:
Error: Failed to crunch file E:\Rock\videoIM\Agora_Native_SDK_for_Android_v1_7_4_FULL\Agora_Native_SDK_for_Android_FULL\samples\OpenVideoCall_Android\app\build\intermediates\exploded-aar\com.android.support\appcompat-v7\25.0.0\res\drawable-xhdpi-v4\abc_ab_share_pack_mtrl_alpha.9.png
into
E:\Rock\videoIM\Agora_Native_SDK_for_Android_v1_7_4_FULL\Agora_Native_SDK_for_Android_FULL\samples\OpenVideoCall_Android\app\build\intermediates\res\merged\debug\drawable-xhdpi-v4\abc_ab_share_pack_mtrl_alpha.9.png

该问题是由于示例代码引用的文件名过长造成的。

登录类常见问题

为什么提示我被踢出了设备?

如果一个已经登录的用户,在另一个设备登录,则当前用户会被踢。

频道类常见问题

网络环境差时,SDK 会强行让用户自动退出频道么?

SDK 不会让用户自动退出频道,除非用户自己主动退出,例如,应用程序调用 leaveChannel

在每个房间,每个频道内,通话中是否有管理员?

没有管理员的概念,管理员是属于业务管理层的范围。可以由信令层实现,由信令服务器主动下发命令,调用SDK的接口来实现通话管理。

客户端是否需要维护频道?

频道是自动创建和删除的,客户端无需处理和维护。当所有客户端都离开一个频道时,频道自动被删除。

什么是 App ID 和 Token? 我如何使用?

更多详细介绍, 以及关于如何获取和使用 App ID 和 Token 的步骤,请参考 校验用户权限

用户直播时,如何保持房间名/频道名的唯一性?

由 App 端自行区分,例如加上前后缀。如果指定相同的频道名,则进入同一频道。

如何监听频道内谁在说话?

以下各平台回调方法提示了频道内谁在说话,以及说话者的音量:

  • Android/Windows: onAudioVolumeIndication
  • iOS/macOS: reportAudioVolumeIndicationOfSpeakers

该提醒默认为关闭状态。如需启用,请调用 enableAudioVolumeIndication 方法进行配置。

Windows 上关于几个初始化参数的初始化时间点有哪些注意事项?

  • 在加入频道之前,必须保证调用过一次: virtual int IRtcEngine::initialize(const RtcEngineContext& context)
  • 如果需要开启视频功能,则必须在加入频道前调用: virtual int IRtcEngine::enableVideo()
  • 如果要使用同频道消息透传,必须在加入频道前调用: virtual int IRtcEngine::enableVendorMessage()

其他问题

为什么 Open Live 编译无法通过?

Open Live 编译无法通过通常是由错误填写 App ID 或没有填写 App ID 引起的,用户需要自己申请 App ID 并填写才能通过。请在提示出错的地方,补上自己申请的 App ID。

从哪里可以获取 App ID?

dashboard.agora.io 注册后,即可在 Dashboard 默认或新建的项目下获取 App ID。 详见 校验用户权限

为什么在 Open Live 代码里填好 App ID 后,进不去频道,也看不到本地视频?

请检查一下:在 dashboard 中,是否启用了 App Certificate, 一旦启用 App Certificate, 则必须使用 Token 加入频道。

关于 App ID 与 Token 的区别,详见 校验用户权限

Token 的时效多长?过期时是否对正在直播或看播产生影响,比如中断?

Token 有两个跟时间相关的字段:

  • 授权时间戳 :Token 本身的有效期,有效期为 24 个小时,如果超过 24 小时用户没有进入频道,则该 Token 将无法再加入频道。
  • 服务过期时间戳:允许用户在频道内的最大时长。在到时间时用户将被踢出频道。默认该事件为无穷大,但用户可以自定义。

Agora SDK 支持 ReplayKit 吗?

ReplayKit 是 iOS 10 内置录屏功能,目前 Agora SDK 不内置 ReplayKit,但可以与 ReplayKit 协同工作,将 ReplayKit 采集到的数据传给 SDK 实现。

当 PC 端有多个摄像头用于多角度拍摄时,是否可以通过切换不同的视频原始码流并送到 SDK 里来进行主播大窗口的切换?

对于单台 PC 外接多 USB 摄像头,可以通过自行采集不同摄像头原始视频流再输入 SDK 的方案进行切换;也可以直接在APP端通过热切换摄像头的方式进行主播画面切换,SDK 本身是支持 PC 端多个摄像头热切换的。

哪些回调函数建议做 App 业务逻辑?哪些不建议做?

App 经常关心的是用户状态相关的回调,如 onUserJoinedonUserOffline 等,这一类建议可以做成 App 业务逻辑。

Error Code 里哪些可以做 APP 的业务逻辑,哪些不可以?

Error 类的可以做 APP 的业务逻辑,但是 Warning 类的无需处理。

哪些回调可以用于提示用户断开服务器,或者重连?

rtcEngineConnectionDidLostconnectionLostBlock 可用户提示用户断开服务器, 断开事件后,SDK会主动重连服务器。

多次调用 initWithAppId 会有什么不良后果吗?

有,可能会闪退或者导致摄像头方向不正常等。

加解密接口(算法)对系统影响有多大?

不同复杂程度的加解密算法对 CPU 的影响不一样。对于过于复杂的加解密线程,CPU 负载很大,可能会出现延迟。

通话时,为什么旋转手机,图像有时跟着旋转,有时不?

手机支持转屏和不转屏两种。这个在系统里可以设置。如果设置了允许转屏,应用可以重新布局,窗口会变宽或者窄。如果系统不允许转屏,应用就无法重新布局。这就是为什么旋转手机,图像有时候会跟着旋转,有时候不会。

网络重新连接后,为什么对方视频图像仍然为静止状态,没有恢复?

网络连接后,视频通讯需要一点延时才能才能恢复。这是所有视频通讯都有的现象。网络比较差的情况下,延时的恢复时间更长。

SDK 的用户 id 是 32 位无符号整型,而我们现有用户的 id 是 String 值, 我该怎么办?

这个是信令层的逻辑和协议,建议客户服务器在 string 和 int 间映射。

怎么让音量显示的回调生效?

由于远端音频流音量回调默认关闭,所以必须在加入频道前后立刻调用相关 API 开启该回调: RtcEngineParameters:: enableAudioVolumeIndication(int interval, int smooth)。

什么是回调?

编程分别两类:

  • 系统编程 (System Programing):编写库。
  • 应用编程 (Application Programing):利用已写好的库来编写具有某种功用的程序,也就是应用。

系统开发程序员留下一些接口给应用开发程序员使用,这些接口即为 API (Application Programming API)。
当程序运行时, 应用程序(Application program)会时常通过API调用库里所预先备好的函数。但有些库函数要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数成为回调函数 (Callback Function)。

例如: 你走进一家商店,想买某一款香水,但是店员告诉你现在缺货。店员说他们会在有货的时候联系你,但你必须自己提供联系方式。例如: 你提供了电话号码或邮箱地址。联系你的行为是商店提供的,这就类似于库函数;你决定是否提供联系方式,以及提供什么方式,这就类似于回调函数。你让商店给你打电话,或发邮件,或添加微信好友联系你的动作,就类似于登记回调函数。

以下为基本逻辑:

当我在 Windows 上进行调试时,提示我需要一个 agorartc.pdb 文件,这个文件在哪里可以拿到?

请忽视该提示,不影响使用。

为什么在 Windows 平台上显示视频的窗口不是平铺的,且这些视频窗口不是同一个父窗口?

如果显示视频的窗口不是平铺开的,并且这些视频窗口不是同一个父窗口,那么这些视频窗口绘制时可能会出现互相被刷掉的情况。因此,如果出现这种情况,你需要调用 Win32 API ::SetWindowLong 给父窗口设置如下的 style:

LONG styleValue = ::GetWindowLong(parentWindow.GetSafeWnd(), GWL_STYLE);
::SetWindowLong(parentWindow.GetSafeHwnd(), styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);

为什么 SEI 中设置的布局,跟实际得到的布局,有 1 个像素上的偏移?

视频底层解码为 YUV420 格式时,YUV 的采样在宽和高两个方向上的比例为 2:1:1,所以宽跟高必须是偶数,移动的距离上也必须是偶数。
但是由于我们自定义布局采用相对值,所以在计算变换时,会将各个主播的宽高和位置,计算成偶数,导致与用户期望的数据,有 1 个像素的偏差。

为什么 HLS 延时比 RTMP 要高很多?

HLS 分为 m3u8 索引文件和 ts 媒体切片文件,Apple 的文档中,ts 最短是 2s 一个切片,m3u8 至少 3 个切片文件的索引,所以最短需要 6s 的延时。

而 RTMP 一般都是直接透传,只需要短暂的缓冲即可,所以延时相对而言要比 HLS 低很多。

无法加入频道

查看是否有错误码,以及查看是哪种错误码引起的加入频道失败。
如果错误码提示是因为没有退出上次通话引起的,先调用 leaveChannel ,然后再次加入频道。

无法通过 Dynamic Key/Token 验证

检查:

  • Dynamic Key/Token 生成的算法是否正确。
  • App ID 和 App Certificate 是否填写正确,注意区分大小写。
  • expireTime 是否晚于当前时间。

当用户加入频道后切换到后台模式一段时间后(例如 30 分钟),发现 iOS App 崩溃了

该问题出现的原因是当集成 Agora SDK 时,没有在 Background Modes 里选择 Audio, AirPlay, and Picture in Picture 。

你仅需要在 Xcode 勾选该选项即可。

当 App 在 iOS 上进入后台模式后,通话中断。

在 Xcode 中开启后台模式即可。在您的App上:

  • 选择 Project > Capabilities
  • 打开 Background Modes, 选择 Audio, AirPlay and Picture in Picture 和 Voice over ip 选项。

日志打印中出现 Failed to decode frame xxx, return error code is -1

这个是解码失败,最常见的情形是网络不好时丢包导致收不到完整帧,引起解码出错,如果日志打印中出现这段信息,检查一下当前的网络环境。

XP 系统初始化失败

Agora 的 SDK 从 1.1 版本开始,编译器默认采用 VC2013,依旧会支持 XP 系统,但由于操作系统未部署相关运行时库,需从微软下载,地址如下(该地址可能由于微软官方变更而失效):https://www.microsoft.com/en-us/download/details.aspx?id=40784

请勿从其他第三方转载地址下载,很多下载站所提供版本并非最新版,即使安装也无法正常运行。

启动 app 时出现 Exception 信息

当集成 Agora SDK 以后,启动 app 出现下面的 Exception 信息:

dalvik.system.PathClassLoader[DexPathList[[zip file xxxxx.apk],nativeLibraryDirectories=[/data/app/xxxxx/lib/arm,/vendor/lib/,system/lib]]]
couldn’t find "agoraxxx.so" java.lang.Runtime.loadLibrary(Runtime.java:366)…

这种情况是由于集成时没有将 .so 文件放置在正确的平台路径下, 导致 App 启动后找不到 .so 文件导致的。打包 APK 时请注意平台和路径。

产品、服务、参数篇

故障排除篇