实现视频通话
本文将介绍如何快速实现一个基本的实时音视频通话场景的应用。该应用会展示 SDK 基本的连麦功能,包括 加入房间,采集,发布,订阅 等过程。
主要流程
在开发之前,需要先了解下实时音视频通话的主要流程,流程图如下:

其中:
- 一路 Track 代表一路音频或者视频的轨道。
- 加入、离开房间代表一次音视频通话的开始和结束,无需反复调用。
- 加入房间后,可通过发布、订阅来实现音视频的推送和接收。离开房间后,将无法发布本地音视频,也无法订阅远端音视频。
SDK 初始化
首先,在调用 SDK 其他接口之前,需要在 Activity 生命周期中的 onCreate() 中进行 SDK 的初始化操作:
QNRTC.init(context, new QNRTCEventListener());
添加视频渲染控件
接下来我们需要在布局文件中期望的位置添加两个 QNSurfaceView 分别用来做本地视频画面和远端视频画面的渲染窗口。
示例代码如下:
<com.qiniu.droid.rtc.QNSurfaceView
android:id="@+id/local_surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.qiniu.droid.rtc.QNSurfaceView
android:id="@+id/remote_surface_view"
android:layout_width="150dp"
android:layout_height="150dp" />
mLocalWindow = findViewById(R.id.local_surface_view);
mRemoteWindow = findViewById(R.id.remote_surface_view);
创建 QNRTCClient
QNRTCClient 负责加入房间,离开房间,发布本地音视频轨道,订阅远端音视频轨道等一系列功能,是完成音视频通话的核心对象。创建 QNRTCClient 的操作我们建议在 Activity 生命周期中的 onCreate() 中完成。
QNRTCClient mClient = QNRTC.createClient(new QNClientEventListener());
其中,QNClientEventListener 为音视频通话过程中必须的事件监听回调,我们可以通过它来监听是否有人加入或者离开房间,是否有人发布音视频轨道等重要事件。
创建音视频采集 Track
Track 代表了音视频通话过程中的一路音频轨道或者一路视频轨道。七牛 SDK 提供多种形式的音视频轨道,例如,通过摄像头采集的视频创建一个视频轨道:
QNCameraVideoTrack mCameraVideoTrack = QNRTC.createCameraVideoTrack();
通过麦克风采集的音频创建一路音频轨道:
QNMicrophoneAudioTrack mMicrophoneAudioTrack = QNRTC.createMicrophoneAudioTrack();
其中视频轨道创建完成之后,我们即可为它设置渲染窗口从而预览到摄像头采集的画面,代码如下:
mCameraVideoTrack.play(mLocalWindow);
注意:创建 Track 需要 App 获取
CAMERA
、RECORD_AUDIO
等采集相关的权限,请确保您的应用已经获取该权限,否则数据采集将会失败。权限申请可参考 1v1 示例 demo
为了更好的控制摄像头采集的流程,可以在生命周期函数中添加如下调用:
@Override
protected void onResume() {
super.onResume();
// 开始视频采集
if (mCameraVideoTrack != null) {
mCameraVideoTrack.startCapture();
}
}
@Override
protected void onPause() {
super.onPause();
// 停止视频采集
if (mCameraTrack != null) {
mCameraTrack.stopCapture();
}
}
加入房间
完成本地音视频 Track 的创建后,我们就可以调用 QNRTCClient.join 接口加入房间了。
加入房间需要携带相应的 RoomToken:
- RoomToken 建议通过您的服务端生成,签算方式可参考 RoomToken 签发服务。
- 若您的服务端还没有实现相关代码,可参考房间的创建和管理文档在 portal 上生成临时的 token,需要注意 UserID 不可重复。
RoomToken 准备好后,即可通过如下代码加入房间:
mClient.join(token);
加入房间成功后会触发 QNClientEventListener.onConnectionStateChanged 回调 QNConnectionState.CONNECTED 状态。此时即可进行发布、订阅等操作。
在进入音视频通话房间之后,用户可以根据业务场景的需求在适当的时间调用离开房间的接口退出连麦,详情请见房间管理。
注意:加入、离开房间代表一次音视频通话的开始和结束,一次会话仅需调用一次加入、离开的操作即可,无需重复调用。
发布本地音视频 Track
成功加入房间后,我们可通过 QNClientEventListener.onConnectionStateChanged 回调方法中获取通知,然后通过以下代码的调用进行本地 Track 的发布:
@Override
public void onConnectionStateChanged(QNConnectionState state, @Nullable QNConnectionDisconnectedInfo info) {
if (state == QNConnectionState.CONNECTED) {
mClient.publish(new QNPublishResultCallback() {
@Override
public void onPublished() {
// Track 发布成功时回调
}
@Override
public void onError(int errorCode, String errorMessage) {
// Track 发布失败时回调
}
}, mCameraVideoTrack, mMicrophoneAudioTrack);
}
}
发布成功后,本地会收到 QNPublishResultCallback.onPublished 回调。远端用户会收到 QNClientEventListener.onUserPublished 回调。
取消发布可以通过调用 QNRTCClient.unpublish 方法实现。取消发布后,本地音视频数据将停止发送,但仍可以接收远端的音视频数据。更多内容可参考发布和订阅。
订阅远端音视频 Track
当远端成功发布音视频数据后,SDK 默认会进行自动订阅,订阅成功后将会收到 QNClientEventListener.onSubscribed 的回调,如果我们订阅到的是视频轨道,则可以为它设置渲染窗口,如果我们订阅到的是音频轨道,则可以为它设置音量:
@Override
public void onSubscribed(String remoteUserID, List<QNRemoteAudioTrack> remoteAudioTracks, List<QNRemoteVideoTrack> remoteVideoTracks) {
for(QNRemoteVideoTrack track : remoteVideoTracks) {
// 设置订阅到视频轨道的渲染窗口
track.play(remoteWindow);
}
for(QNRemoteAudioTrack track : remoteAudioTracks) {
// 设置订阅到音频轨道的音量大小
track.setVolume(volume);
}
}
在成功订阅之后,用户可以根据业务场景的需求在适当的时间调用取消订阅的接口取消订阅相应的 Track,详情请见发布与订阅
离开房间
当音视频通话结束,调用以下代码离开房间:
mClient.leave()
离开房间成功后会触发 QNClientEventListener.onConnectionStateChanged 回调 QNConnectionState.DISCONNECTED
状态,对应 QNConnectionDisconnectedInfo.Reason 为 LEAVE
。
SDK 销毁
在整个 Activity 销毁时,我们需要调用以下代码对资源进行释放,一般此操作建议在 Activity 生命周期的 onDestroy()
中进行,示例代码如下:
@Override
protected void onDestroy() {
super.onDestroy();
QNRTC.deinit();
}
示例代码
按照上述流程即可实现一个基本的实时音视频通话应用,完整的示例代码可参考 1v1 接口 demo。