一对一通话
本页介绍了一对一呼叫的主要功能,包括如何从您的应用程序拨打、接听、处理和结束呼叫。
关键类介绍
RCCallPlusClient
RCCallPlusClient: CallPlus for Web 的核心类,用于管理客户端呼叫行为,例如发起、接听、挂断通话,操作音视频设备,管理通话记录等。
方法 | 说明 |
---|---|
setCallPlusEventListener | 注册应用层事件,包含“收到呼叫、通话结束、通话人员状态变更、通话类型变更”等事件 |
setStatusReportListener | 注册音视频上下行丢包数据监听 |
setVideoView | 设置要观看人员(包括自己和对方)的媒体播放器 |
removeVideoView | 删除指定单个用户的媒体播放器,不观看指定单个用户的视频时,业务层可以直接移除其媒体播放器 |
playMedia | 播放指定人员的音视频媒体,播放指定单个用户的视频前,请确保已经调用 setVideoView 方法为其设置视频视图 |
createVideoConfigBuilder | 创建视频配置构建器 |
setVideoConfig | 设置视频配置 |
createAudioConfigBuilder | 创建音频配置构建器 |
setAudioConfig | 设置音频配置 |
startCall | 发起呼叫 |
joinMultiCall | 直接加入进行中的群组通话 |
invite | 通话中邀请他人 |
accept | 接听通话 |
hangup | 挂断通话 |
requestChangeMediaType | 通话中发起媒体类型变更请求 |
cancelChangeMediaType | 取消切换媒体类型变更请求 |
replyChangeMediaType | 媒体类型变更应答 |
getCurrentCallSession | 获取当前进行中的通话 |
getAvailableCallRecordsFromServer | 从服务器获取未结束的通话记录 |
getRemoteTracks | 获取远端资源列表 |
getCallRecords | 分页查找当前用户的全部通话记录 |
deleteCallRecordsFromServer | 根据 callId 集合批量删除通话记录 |
deleteAllCallRecordsFromServer | 清空所有通话记录 |
startCamera | 开启摄像头 |
stopCamera | 关闭摄像头 |
switchCamera | 切换摄像头 |
startMicrophone | 开启麦克风 |
stopMicrophone | 关闭麦克风 |
isMicrophoneEnable | 麦克风是否开启 |
muteAllRemoteAudio | 静音所有远端音频流 |
getVersion | 获取 SDK 版本信息 |
RCCallPlusSession
RCCallPlusSession 对象代表一则通话的所有信息,包含获取通话实体信息的方法集合。
方法 | 说明 |
---|---|
getCallId() | 获取通话 ID。 |
getState() | 获取通话实体的状态 RCCallPlusCallState。 |
getCallType() | 获取通话类型 RCCallPlusType。 |
getMediaType() | 获取通话媒体类型 RCCallPlusMediaType。 |
getUserList() | 获取一组用户信息对象,每个对象中包含通话人员用户 ID 与用户状态 RCCallPlusSessionUserState。 |
getCreatorUserId() | 获取通话发起者 userId |
getInviterUserId() | 获取通话邀请者 userId |
getCreateTimestamp() | 获取通话起始时间 |
getDuration() | 获取通话时长 |
ICallPlusEventListener
ICallPlusEventListener 监听器提供来电事件、通话状态、通话记录等事件相关回调。
方法 | 说明 |
---|---|
onReceivedCall | 本地用户收到来电通知。 |
onRemoteUserInvited | 本地用户收到收到远端人员被邀请加入通话通知,如 A 与 B 通话中,A 邀请 C,则 B 会收到此回调。inviteeUserList 表示受邀人用户 ID 列表。inviterUserId 表示邀请者用户 ID。callId 表示所属通话;群聊中,己方已不在通话中的情况下,也会收到服务侧的事件通知 |
onCallConnected | 通话已建立,sdk 内部会发布音视频资源 |
onCallTypeChanged | 本地用户收到通话类型变更通知。 |
onRemoteUserStateChanged | 本地用户收到人员状态变更通知。 |
onCallEnded | 本地用户收到通话结束(群组通话时,客户端挂断不代表通话结束) |
onRemoteCameraStateChanged | 本地用户收到远端摄像头开、关通知 |
onRemoteMicrophoneStateChanged | 本地用户收到远端麦克风开、关通知 |
onReceivedCallLog | 本地用户单呼或群呼结束后,收到服务器下发的通话日志 |
onReceivedChangeMediaTypeRequest | 本地用户收到媒体类型变更请求(仅单聊) |
onReceivedChangeMediaTypeResult | 本地用户收到媒体类型变更结果 (仅单聊) |
onReceivedCallStartTime | 本地用户收到收到通话开始计时通知 |
onReceivedCallFirstFrameTime | 本地用户收到收到通话首帧到达通知 |
onUserMediaAvailable | 本地用户收到指定单个用户的音频或视频可播放 |
onFetchRemoteMediaError | 收到获取本人或远端媒体资源失败 |
onUserAudioLevelChanged | 本地用户收到人员音量变化 |
呼叫流程
CallPlus SDK 中的一对一通话是指两人之间通话。一对一呼叫通过以下步骤建立:
- 主叫方发起呼叫,SDK 内部为主叫用户创建在音视频资源,以在通话中使用。被叫方会收到 onReceivedCall 通知。
- 当被叫方选择接听通话后,SDK 内部会为被叫用户创建音视频资源,以在通话中使用。
- 接听成功后,主叫方和被叫方的音视频资源将会被推送至融云媒体服务器。
- 融云信令服务器通知主叫方和被叫方可查看对方的音视频媒体资源。
- 主叫方和被叫方可以调 setVideoView 指定要观看的用户视频画面,SDK 内部会自动获取音频资源。
- 主叫方和被叫方可在 ICallPlusEventListener 监听器的 onUserMediaAvailable 事件中调 playMedia(useId,mediaType) 播放指定用户的音视频资源。注意:请务必根据用户 ID 和媒体类型进行判断,如果是本地用户采集的音频流,请不要在本端播放,避免造成回声或啸叫问题。
对于主叫用户来说, 调用 startCall 方法后,将返回一个解析为 { code: RCCallPlusCode, callId?: string }
的 promise。对于被叫用户来说,将通过 ICallPlusEventListener
监听器的 onReceivedCall
方法收到 RCCallPlusSession 通话对象。对于主叫用户和被叫用户来说,都可以调用通话客户端 RCallPlusClient
对象的 getCurrentCallSession 方法获取当前进行中的通话对象。
前提条件
- App Key 已开通音视频通话服务。
- 已初始化 CallPlus SDK,并获取
RCCallPlusClient
对象。本文中的callPlusClient
即为初始化时 获取的RCCallPlusClient
实例对象。
注册监听器
CallPlus for Web SDK 提供了 ICallPlusEventListener 事件处理程序,用于接收来自远端用户或服务端的事件,方便应用程序处理并做出反应。例如收到通话呼入时可选择接听或挂断、收到通话媒体类型升级请求时可选择同意或拒绝、收到通话开始计时可在页面显示通话时长。
获取 RCCallPlusClient 对象后,使用 setCallPlusEventListener()
注册监听器。
// 注册 callPlus 业务层监听事件
callPlusClient.setCallPlusEventListener({
/**
* 呼入通知
* 收到呼入时,可选择接听或挂断通话
* @param session 通话实例
* @param extra 透传呼叫方发起呼叫时携带的附加信息
*/
async onReceivedCall(session: RCCallPlusSession, extra?: string) {
const callId = session.getCallId();
console.log(`呼入通知, callId: ${callId}`);
/**
* 接听电话
*/
const { code } = await callPlusClient.accept(callId);
console.log(`接听通话结果, code: ${code}`);
},
/**
* 群组通话收到远端人员被邀请加入通话通知,如 A 与 B 通话中,A 邀请 C,则 B 会收到此回调
* @param inviteeUserList - 受邀人用户 ID 列表
* @param inviterUserId - 邀请者用户 ID
* @param callId - 所属通话;群聊中,己方已不在通话中的情况下,也会收到服务侧的事件通知
*/
onRemoteUserInvited(inviteeUserList: string[], inviterUserId: string, callId: string) {
console.log(`收到远端人员被邀请加入通话通知, callId: ${callId}, inviteeUserList: ${inviteeUserList}, inviterUserId: ${inviterUserId}`);
},
/**
* 通话已建立,sdk 内部会发布音视频资源
*/
onCallConnected(session: RCCallPlusSession) {
console.log(`通话已建立, callId: ${session.getCallId()}`);
},
/**
* 通话类型变更
* @param type 单呼或群呼
* @param callId 通话 id
*/
onCallTypeChanged(type: RCCallPlusType, callId: string) {
console.log(`通话类型变更, callId: ${callId}, type: ${type}`);
},
/**
* 人员状态变更
* @param callId 通话 id
* @param userId 状态变更人员 id
* @param state 人员变更后状态
* @param reason 变 更原因
*/
onRemoteUserStateChanged(
// 增量
callId: string,
userId: string,
state: RCCallPlusSessionUserState,
reason?: RCCallPlusReason,
) {
console.log(`人员状态变更, callId: ${callId}, ${userId}状态: ${RCCallPlusSessionUserState[state]}, reason: ${reason}`);
},
/**
* 通话结束(群组通话时,客户端挂断不代表通话结束)
* @param session 通话实例
* @param reason 通话结束原因
*/
onCallEnded(session: RCCallPlusSession, reason: RCCallPlusReason) {
console.log(`通话结束, callId: ${session.getCallId()}, reason: ${reason}`);
},
/**
* 远端摄像头开、关通知
* @param callId 通话 id
* @param userId 用户 id
* @param disabled 是否关闭
*/
onRemoteCameraStateChanged(callId: string, userId: string, disabled: boolean) {
console.log(`远端摄像头开、关通知, callId: ${callId}, userId: ${userId}, disabled: ${disabled}`);
},
/**
* 远端麦克风开、关通知
* @param callId 通话 id
* @param userId 用户 id
* @param disabled 是否关闭
*/
onRemoteMicrophoneStateChanged(callId: string, userId: string, disabled: boolean) {
console.log(`远端m麦克风开、关通知, callId: ${callId}, userId: ${userId}, disabled: ${disabled}`);
},
/**
* 单呼或群呼结束后,服务器下发的通话日志
* @param record 数据接口定义为:IRCCallPlusCallRecord,可通过 apiDoc 查看具体包含字段
*/
onReceivedCallRecord(record: IRCCallPlusCallRecord) {
console.log(`通话日志下 发, record: ${JSON.stringify(record)}`);
},
/**
* 收到媒体类型变更请求(仅单聊)
* @param userId 请求发起人
* @param transactionId 事物 id,本次请求和应答的唯一标识
* @param mediaType 请求变更的媒体类型
*/
onReceivedChangeMediaTypeRequest(
userId: string, transactionId: string, mediaType: RCCallPlusMediaType,
) {
console.log(`收到媒体类型变更请求, userId: ${userId}, transactionId: ${transactionId}, mediaType: ${mediaType}`);
/**
* 应答是否同意变更媒体请求
*/
const isAgree = true;
callPlusClient.replyChangeMediaType(transactionId, isAgree);
},
/**
* 媒体类型变更结果(仅单聊)
* @param info.userId
* @param info.transactionId 事物 id,本次请求和应答的唯一标识
* @param info.mediaType
* @param info.code - 升级结果
* - 升级成功
* - 发起升级请求方取消
* - 收到升级请求方拒绝
* - 响应超时
*/
onReceivedChangeMediaTypeResult(info: {
userId: string,
transactionId: string,
mediaType: RCCallPlusMediaType,
code: RCCallPlusMediaTypeChangeResult
}) {
const { userId, transactionId, mediaType, code } = info;
console.log(`媒体类型变更结果, userId: ${userId}, transactionId: ${transactionId}, mediaType: ${mediaType}, code: ${code}`);
},
/**
* 收到通话开始计时
* @param info.callId 通话 id
* @param info.callType 单聊或群聊
* @param info.callStartTime 通话开始时间
*/
onReceivedCallStartTime(info: { callId: string, callType: RCCallPlusType, callStartTime: number }) {
console.log(`通话计时开始, startTime: ${info.callStartTime}`);
/**
* 起通话计时定时器
*/
let callDuration = Math.floor((+new Date() - info.callStartTime) / 1000);
setInterval(() => { callDuration++; }, 1000);
},
/**
* 收到首帧时间(仅单聊存在)
* 收到首帧开始计费
* @param callId 通话 id
* @param callFirstFrameTime 通话首帧到达时间
*/
onReceivedCallFirstFrameTime(callId: string, callFirstFrameTime: number) {
console.log(`收到首帧时间, callFirstFrameTime: ${callFirstFrameTime}`);
},
/**
* 收到指定单个用户的音频或视频可播放
* 业务层可调 playMedia(userId, mediaType) 播放
* @param userId 用户 id
* @param mediaType 媒体类型
*/
onUserMediaAvailable(userId: string, mediaType: RCCallPlusMediaType) {
/**
* 请务必根据用户 ID 和媒体类型对 流进行判断,如果是本地采集的音频流,请不要在本端播放,避免造成回声或啸叫问题。
*/
callPlusClient.playMedia(userId, mediaType);
},
/**
* 获取远端媒体资源失败
* @param userId 远端人员 id
* @param code 失败原因
*/
onFetchRemoteMediaError(userId: string, code: RCCallPlusCode) {
console.log(`获取远端 媒体资源失败, userId: ${userId}, code: ${code}`);
},
/**
* 人员音量变化
* @param userId 本端或远端人员 id
* @param audioLevel 音量值(0-100)
*/
onUserAudioLevelChanged(userId: string, audioLevel: number) {
console.log(`人员音量变化, userId: ${userId}, audioLevel: ${audioLevel}`);
},
})
注意
如果未注册
ICallPlusEventListener
事件处理程序,则用户无法接收onReceivedCall
通话呼入事件。建议在初始化 CallPlus SDK 后添加此处理程序。
添加媒体播放元素
视频媒体播放元素是一个 HTMLVideoElement <video>
,用于显示视频流。要显示本端和远程视频媒体流,以下两个元素是必需添加在页面中的。id 为 local_video_element_id
的 video
标签用于播放本端视频,id 为 remote_video_element_id
的 video
标签用于播放远端视频。音频播放依赖 SDK 内部创建的 Audio 对象,业务层无需关注。
<video id="local_video_element_id"></video>
<video id="remote_video_element_id"></video>
在页面准备好以上两个标签后,调 callPlusClient.setVideoView
可以设置要观看某些人的画面。如设置了要观看人员 A 的视频视图后,SDK 在获取到 A 的视频后,会在 ICallPlusEventListener
的 onUserMediaAvailable 事件通知业务层,此时业务层可调 callPlusClient.playMedia()
播放媒体资源(请勿在本端播放本地用户采集的音频流,避免造成回声或啸叫问题)。
/**
* 设置要观看人员(包括自己和对方)的媒体播放器
* @param list 为一个列表,可传入多人的媒体播放器
* @param item.userId 用户 id
* @param item.videoElement 一个 video 元素,用于播放视频,需要挂载在业务层页面上
* @param item.isTiny 是否观看别人的小流,小窗口时可以配置为 true,可节省带宽,userId 为远端用户时有效
* @returns code 返回是否设置成功
*/
setVideoView(list: {userId: string, videoElement: HTMLVideoElement, isTiny: boolean}[]): { code: RCCallPlusCode }
呼叫和接听前设置本端和远端的视频播放器。
callPlusClient.setVideoView([
{
userId: '<local-userId>',
videoElement: document.getElementById('local_video_element_id')
},
{
userId: '<remote-userId>',
videoElement: document.getElementById('remote_video_element_id')
},
]);
本端的视频播放器需在呼叫和接听前设置。远端人员的视频播放器可以按需设置,既可以在通话前提前设置好,也可以在
ICallPlusEventListener
的 onRemoteUserStateChanged 事件中,收到远端人员状态为RCCallPlusSessionUserState.ONCALL
确认远端接通时设置,如果需要看远端人员的小流,可以指定isTiny
为 true。
发起呼叫
注意
从 CallPlus 2.0 开始,startCall 方法新增可选参数
pushConfig
和extra
。pushConfig
支持携带移动端推送配置 IRCCallPlusPushConfig,可用于自定义推送通知标题等属性extra
支持携带透传的自定义数据。
通过在 startCall
方法中提供被叫方的用户 ID、通话类型、通话媒体类型来发起呼叫。通话发起成功时,会返回成一个 callId
。
/**
* 发起呼叫
* @param userIds 被叫方人员 userId 列表,单人呼叫仅需在数组中放置对方一人的 userId
* @param type 单人呼叫 or 多人呼叫
* @param mediaType 通话媒体类型: 音频 or 音视频
* @returns callId 呼叫成功后,产生的会话 id
*/
callPlusClient.startCall(['<userId>'], RCCallPlusType.SINGLE, RCCallPlusMediaType.AUDIO_VIDEO);