npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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' |

功能特性

  1. 音视频通话:仅支持一对多音视频通话
  2. 网络质量监测:实时监测网络质量,动态调整视频质量
  3. 设备控制:支持开启/关闭麦克风、摄像头
  4. 扬声器控制:支持切换扬声器/听筒
  5. 动态视频质量调整:根据网络状况自动调整视频分辨率

注意事项

  1. 使用前需获取腾讯云 TRTC 服务的 SDK App ID 和 SDK 密钥
  2. 确保在 HTTPS 环境下使用,否则可能无法正常访问摄像头和麦克风
  3. 首次使用时需要用户授权摄像头和麦克风权限