本文结合融云官方文档,以Vue的方式实现Web端融云视频通话功能,希望能对需要此功能的小伙伴有所帮助。
融云官方文档:实现音视频通话 | 融云开发者文档
目录
一、开通音视频服务
1、获取App Key 与 App Secret(详细开通步骤略)
二、导入SDK(NPM安装方法,本文用的5.x版本)
1、安装 5.X 版本 IMLib
2、安装 RTCLib 5.X
3、安装 CallLib 5.X
三、初始化(本文在Vue页面中进行)
1、Import引入
2、初始化
① IM客户端初始化,异步方式
② RTC 客户端与 CallLib 客户端初始化
四、建立 IM 连接(实现用户之间实时通信的基础步骤)
1、与 IM 服务建立连接(IMLib 5.X)
五、发起呼叫
1、编写视频容器、呼叫按钮、接听按钮(具体可结合自己的业务实现)
2、发起呼叫方法
3、挂断方法
融云视频通话Vue实现
一、开通音视频服务
1、获取App Key 与 App Secret(详细开通步骤略)
二、导入SDK(NPM安装方法,本文用的5.x版本)
1、安装 5.X 版本 IMLib
# 安装 IMLib v5
npm install @rongcloud/engine@latest @rongcloud/imlib-next --save
2、安装 RTCLib 5.X
# 安装 RTCLib
npm install @rongcloud/plugin-rtc --save
3、安装 CallLib 5.X
# 安装 CallLib
npm install @rongcloud/plugin-call --save
三、初始化(本文在Vue页面中进行)
1、Import引入
import * as RongIMLib from "@rongcloud/imlib-next";// 融云提供的即时通讯库 - 构建即时通讯功能的核心组件
import * as RCCall from '@rongcloud/plugin-call';// 通话插件 - 主要用于实现实时音视频通话功能
import * as RCRTC from '@rongcloud/plugin-rtc';// 实时通信插件 - 专注于实现实时音视频流的传输
2、初始化
① IM客户端初始化,异步方式
② RTC 客户端与 CallLib 客户端初始化
mounted() {
// 初始化 IM Client
this.init();
// 建立 IM 连接(第四步中描述)
this.connect();
},
methods: {
async init() {
try {
// ①调用 IMLib 的 init 方法,初始化 IM 客户端(IMLib 5.X)
await RongIMLib.init({
appkey: this.appkey,//appkey为开通服务所获取的APP Key,可定义在data中
});
console.log("IM Client 初始化成功")
// ②RTC 客户端初始化(其中,rtcClient定义在data中)
this.rtcClient = RongIMLib.installPlugin(RCRTC.installer, { /* 配置项参数 */});//调用IMLib的installPlugin方法,安装RCRTC 实时通信插件,返回的 RTC 客户端实例
console.log("RTC 客户端初始化成功", this.rtcClient)
// ③CallLib 客户端初始化(其中,caller定在data中)
this.caller = RongIMLib.installPlugin(RCCall.installer, {//安装融云通话插件 (RCCall) 并配置其行为,返回的通话客户端实例
rtcClient: this.rtcClient,
onSession: this.onSession,//当一个新的通话会话创建时触发。你可以在这个回调中处理会话相关的逻辑,比如更新 UI 或者准备媒体流。
onSessionClose: this.onSessionClose,//当一个通话会话关闭时触发。你可以在这里清理资源、更新状态等。
onOfflineRecord: this.onOfflineRecord,//当有离线录音可用时触发
});
console.log("CallLib 客户端初始化成功", this.caller)
} catch (error) {
console.error("IM Client 初始化过程中发生错误", error);
}
},
// CallLib 客户端初始化(接上)
onSession(session) {//监听和处理通话会话中的各种事件,若有接听业务可注重处理
session.registerSessionListener({
onRinging: this.onRinging,
onAccept: this.onAccept,
onHungup: this.onHungup,
onTrackReady: this.onTrackReady,
});
},
onRinging(sender, session) {//当有来电响铃时(即对方正在呼叫),这个回调函数会被触发。
console.log('User ringing:', sender.userId);
},
onAccept(sender, session) {//当来电被接受时,这个回调函数会被触发。
console.log('Call accepted by:', sender.userId);
},
onHungup(sender, reason, session) {//当通话被挂断时,这个回调函数会被触发。
console.log('Call hung up by:', sender.userId, ', Reason:', reason);
},
onTrackReady(track, session) {//当媒体轨道(如音频或视频流)准备就绪时,这个回调函数会被触发。
if (track.isAudioTrack() && !track.isLocalTrack()) {
track.play();
}
if (track.isVideoTrack()) {
const videoElement = document.getElementById("video" + track.getUserId());
if (videoElement) {
track.play(videoElement);
}
}
},
onSessionClose(session, summaryInfo) {//当会话关闭时(例如通话结束),这个回调函数会被触发。
console.log('Session closed:', session, summaryInfo);
},
onOfflineRecord(record) {//当有离线录音可用时,这个回调函数会被触发。
console.log('Offline call record:', record);
},
四、建立 IM 连接(实现用户之间实时通信的基础步骤)
1、与 IM 服务建立连接(IMLib 5.X)
// 建立 IM 连接(在methdos中定义,此处略过,因上述代码已定义)
async connect() {
try {
// 连接IM服务
const connection = await RongIMLib.connect(this.token);//调用IMLib中connect方法,参数为token(在data中定义,获取token的方式融云官方文档中,《获取用户信息》有详细的示例,此文中略过)
if (!connection) {
console.warn("IM 连接失败")
}
// 连接成功后,会返回对应的用户id,也就是你当前的用户id
console.log("IM 连接成功,链接用户 id 为", connection.data.userId)
} catch (error) {
console.warn("IM 连接失败", error)
}
},
五、发起呼叫
1、编写视频容器、呼叫按钮、接听按钮(具体可结合自己的业务实现)
<template>
<div>
<!-- 本地视频播放容器 -->
<video id="local-video" autoplay muted playsinline></video>
<!-- 远端视频播放容器 remoteUsers为远端用户id数组 data中定义-->
<div v-for="user in remoteUsers" :key="user.userId">
<video :id="'remote-video-' + user.userId" autoplay playsinline></video>
</div>
<!-- 发起呼叫按钮 -->
<button @click="handleCallClick">发起呼叫</button>
<!-- 挂断按钮,仅当有活跃会话时显示 -->
<button v-if="session" @click="handleHangupClick">挂断</button>
</div>
</template>
2、发起呼叫方法
// 发起单人呼叫
async handleCallClick() {
if (!this.caller) {// 判断CallLib 客户端是否初始化成功
console.error('CallClient is not initialized.');
return;
}
const callOptions = {// 设置发起呼叫参数
targetId: this.targetId,// 目标用户 ID
mediaType: this.mediaType,// 通话媒体类型 1音频 2视频
listener: {// 通话监听器
onRinging(sender, session) {// 当有来电响铃时(即对方正在呼叫),这个回调函数会被触发。
console.log(`User ${sender.userId} is ringing.`);
},
onAccept: (sender, session) => {// 当来电被接受时,这个回调函数会被触发。
console.log('onAccept called with sender:', sender, 'session:', session);
if (!sender || !sender.userId) {
console.error('Invalid sender or userId in onAccept');
return;
}
this.remoteUsers.push({userId: sender.userId});// 将远端用户添加到用户列表中,远端用户也就是当前对方用户
},
onHungup: (sender, reason, session) => {// 当通话被挂断时,这个回调函数会被触发。
console.log('onHungup called with sender:', sender, 'reason:', reason, 'session:', session);
if (sender && sender.userId && this.remoteUsers) {//
// 移除远端用户列表中的用户
this.remoteUsers = this.remoteUsers.filter(user => user.userId !== sender.userId);// 移除远端用户列表中的用户
// 清理与该用户的会话状态(如果需要)
if (session && session === this.session) {
this.session = null;
}
} else {
console.error('Unexpected context or parameters for onHungup');
}
},
onTrackReady(track, session) {// 当媒体轨道(如音频或视频流)准备就绪时,这个回调函数会被触发。
console.log('Track ready:', track);
if (track.isAudioTrack() && !track.isLocalTrack()) {// 检查并播放音频轨道 只播放远端音频轨道
track.play();
}
if (track.isVideoTrack()) {// 检查并播放视频轨道
const userId = track.getUserId();// 获取轨道的关联用户 ID
const isLocal = track.isLocalTrack();// 检查轨道是否为本地轨道
const videoElementId = isLocal ? 'local-video' : `remote-video-${userId}`;// 根据是否为本地轨道,生成对应的视频元素 ID
const videoElement = document.getElementById(videoElementId);// 获取视频元素
if (videoElement) {// 如果找到视频元素,则播放轨道
console.log(`Playing ${isLocal ? 'local' : 'remote'} video for user ${userId}`);
track.play(videoElement);
} else {
console.error(`${isLocal ? 'Local' : 'Remote'} video element for user ${userId} not found!`);
}
}
},
},
}
// 下面为发起呼叫方法
try {
const session = await this.caller.call(callOptions);// 发起呼叫
this.session = session.session// 将会话对象存储在组件的 data 中
} catch (error) {
console.error("呼叫失败", error);
}
},
3、挂断方法
// 挂断方法
async handleHangupClick() {
if (!this.session) {// 判断是否有活跃的会话
console.error('No active session to hang up.');
return;
}
try {
// 调用 session 的 挂断 方法
const {code} = await this.session.hungup();
console.log('Hangup result:', code)
if (code === 10000) {// 如果挂断成功,则清除会话状态和远端用户列表(其中,状态值为10000为成功,这里没做处理)
// 清理会话状态
this.session = null;
// 移除所有远端用户
this.remoteUsers = [];
console.log('Call ended successfully.');
} else {
console.error('Failed to hang up the call:', code);
}
} catch (error) {
console.error('Error during hangup:', error);
}
},
最后送大家一句话:
遇事不决,可问春风 。春风不语,既随本心。