bl-trtc-callkit-vue
v1.2.2
Published
基于腾讯云 TRTC SDK 开发的 Vue 3 通话组件,支持一对多音视频通话、网络质量监测、动态视频质量调整等功能。 1.2.0以后新增了对多用户通话的支持。 (内部使用、userSig不安全) ## 安装
Readme
bl-trtc-callkit-vue
基于腾讯云 TRTC SDK 开发的 Vue 3 通话组件,支持一对多音视频通话、网络质量监测、动态视频质量调整等功能。 1.2.0以后新增了对多用户通话的支持。 (内部使用、userSig不安全)
安装
npm install bl-trtc-callkit-vue使用示例
基本用法
<script setup>
import { ref, onMounted } from 'vue'
import CallKit from 'bl-trtc-callkit-vue';
const callKitRef = ref(null)
const localUserId = ref(String(Math.floor(Math.random() * 900 + 100)))
const remoteUsers = ref([])
const selectedUsers = ref([])
function onNotify({ type, text }) {
console[type]('🚀 ~ CallKit notify', text)
showToast(text, type)
}
// 处理远端用户状态变化
function onRemoteUserStatusChange({ userId, action, userList }) {
console.log('远端用户状态变化:', { userId, action, userList })
if (action === 'enter') {
// 检查用户是否已在列表中
const existingIndex = remoteUsers.value.findIndex(u => u.userId === userId)
if (existingIndex === -1) {
remoteUsers.value.push({
userId
})
}
} else if (action === 'exit') {
// 直接从列表中移除
const existingIndex = remoteUsers.value.findIndex(u => u.userId === userId)
if (existingIndex !== -1) {
remoteUsers.value.splice(existingIndex, 1)
// 同时从选中列表中移除
const selectedIndex = selectedUsers.value.indexOf(userId)
if (selectedIndex !== -1) {
selectedUsers.value.splice(selectedIndex, 1)
}
}
}
}
// 切换用户选择状态
function toggleUserSelection(userId) {
const index = selectedUsers.value.indexOf(userId)
if (index === -1) {
selectedUsers.value.push(userId)
} else {
selectedUsers.value.splice(index, 1)
}
}
// 呼叫选中的用户
function callSelectedUsers() {
if (selectedUsers.value.length === 0) {
alert('请先选择要呼叫的用户')
return
}
callKitRef.value.handleCall(selectedUsers.value)
}
onMounted(() => {
// 初始化:传入 userId、sdkAppId、sdkSecretKey
callKitRef.value.init({
userId: localUserId.value,
sdkAppId: "YOUR_SDK_APP_ID",
sdkSecretKey: "YOUR_SDK_SECRET_KEY",
profile: "1080p"
})
})
const toastList = ref([]);
// 生成唯一ID
function generateId() {
return Date.now() + Math.random()
}
// 显示 Toast
function showToast(text, type = 'info') {
const id = generateId()
const toast = {
id,
text,
type
}
toastList.value.push(toast)
// 3秒后自动移除
setTimeout(() => {
const index = toastList.value.findIndex(item => item.id === id)
if (index !== -1) {
toastList.value.splice(index, 1)
}
}, 3000)
}
// 获取图标
function getIcon(type) {
switch (type) {
case 'error':
return '❌'
case 'info':
default:
return 'ℹ️'
}
}
</script>
<template>
<div class="wrapper">
<div style="font-size: 1rem;">当前 userId:<strong>{{ localUserId }}</strong></div>
<div style="margin-top:12px; border:1px solid #ccc; padding:10px; border-radius:4px;">
<h4>远端用户列表</h4>
<ul>
<li v-for="user in remoteUsers" :key="user.userId"
:class="{ selected: selectedUsers.includes(user.userId) }"
@click="toggleUserSelection(user.userId)">
{{ user.userId }}
</li>
</ul>
<button @click="callSelectedUsers" style="height: 36px;padding: 0 8px; margin-top: 12px;">呼叫选中用户</button>
</div>
<CallKit ref="callKitRef" @notify="onNotify" @remote-user-status-change="onRemoteUserStatusChange" />
<!-- Toast 通知组件 -->
<div class="toast-container">
<transition-group name="toast">
<div v-for="toast in toastList" :key="toast.id" :class="['toast-item', `toast-${toast.type}`]">
<span class="toast-icon">{{ getIcon(toast.type) }}</span>
<span class="toast-text">{{ toast.text }}</span>
</div>
</transition-group>
</div>
</div>
</template>
<style lang="scss" scoped>
.wrapper {
max-width: 1200px;
margin: 0 auto;
padding: 12px;
display: flex;
flex-direction: column;
gap: 8px;
box-sizing: border-box;
.remote-user-call {
margin-top: 12px;
display: flex;
gap: 8px;
align-items: center
}
ul {
margin-top: 12px;
}
li {
height: 32px;
display: flex;
align-items: center;
background: #eee;
border-radius: 4px;
padding: 6px 8px;
margin-bottom: 12px;
cursor: pointer;
transition: background-color 0.2s;
&.selected {
background: #e3f2fd;
border-left: 4px solid #2196f3;
}
}
}
.toast-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
display: flex;
flex-direction: column;
gap: 10px;
max-width: 300px;
}
.toast-item {
display: flex;
align-items: center;
padding: 12px 16px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
animation: slideInRight 0.3s ease;
min-width: 250px;
max-width: 100%;
}
.toast-info {
background-color: #e3f2fd;
color: #1976d2;
border-left: 4px solid #2196f3;
}
.toast-error {
background-color: #ffebee;
color: #d32f2f;
border-left: 4px solid #f44336;
}
.toast-icon {
margin-right: 10px;
font-size: 18px;
}
.toast-text {
flex: 1;
word-break: break-word;
}
/* 动画效果 */
.toast-enter-active,
.toast-leave-active {
transition: all 0.3s ease;
}
.toast-enter-from {
opacity: 0;
transform: translateX(100%);
}
.toast-leave-to {
opacity: 0;
transform: translateX(100%);
position: absolute;
}
@keyframes slideInRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
</style>API 说明
组件方法
| 方法名 | 参数 | 说明 |
|-------|------|------|
| init | { userId: string, sdkAppId: number, sdkSecretKey: string, profile?: string } | 初始化组件,传入用户 ID、SDK App ID、SDK 密钥和可选的视频分辨率(默认1440p,支持360p、720p、1080p、1440p) |
| handleCall | targetIds: string[] | 发起呼叫,传入目标用户 ID 数组或者单个用户 ID 字符串 |
| show | 无 | 显示通话组件 |
| hide | 无 | 隐藏通话组件 |
| hangup | 无 | 挂断通话 |
| setVideoProfile | profile: string | 设置视频分辨率 |
| handleEnter | 无 | 进入通话房间 |
| handleExit | 无 | 退出通话房间 |
组件事件
| 事件名 | 回调参数 | 说明 |
|-------|----------|------|
| notify | { type: string, text: string } | 通知事件,包含通知类型和内容 |
| remote-user-status-change | { userId: string, action: string, userList: string[] } | 远程用户状态变化事件,action 为 'enter' 或 'exit' |
功能特性
- 音视频通话:仅支持一对多音视频通话
- 网络质量监测:实时监测网络质量,动态调整视频质量
- 设备控制:支持开启/关闭麦克风、摄像头
- 扬声器控制:支持切换扬声器/听筒
- 动态视频质量调整:根据网络状况自动调整视频分辨率
注意事项
- 使用前需获取腾讯云 TRTC 服务的 SDK App ID 和 SDK 密钥
- 确保在 HTTPS 环境下使用,否则可能无法正常访问摄像头和麦克风
- 首次使用时需要用户授权摄像头和麦克风权限
