@vostone/web-sdk

Vue 3 composables for WebRTC SIP calling and local media
1,267
Install
npm install @vostone/web-sdk
Latest Version:1.2.3
Vue:3
License:MIT
Last Updated:Oct 22, 2026
Links: npm
Maintainer: vostone2026

@vostone/web-sdk

面向 Vue 3 的浏览器端 SIP/WebRTC 能力封装:基于 JsSIP 完成注册、呼出、来电接听与挂断;配套 本地音视频/屏幕共享 组合式函数,便于嵌入任意 Vue 项目。

特性

  • useSipCall:从业务 HTTP 接口拉取注册账号、按顺序尝试注册、音视频/单向视频呼出、来电振铃与接听、远端流绑定到传入的 video/audio 元素。
  • useLocalMedia:枚举摄像头/麦克风、预览、静音/关视频、屏幕共享及与 SIP 轨道替换联动。

环境要求

  • Vue ^3.4
  • 支持 WebRTC 与 getUserMedia 的浏览器;SDK 产物语法目标为 Chrome 69(Android 9 系统 WebView)。新版 Chrome 执行同一份降级后的代码,行为不变
  • 需自行提供可访问的 WSS SIP 中继与平台下发的注册信息接口(见下文)

Android 9 WebView

系统 WebView 约等于 Chrome 69,有两处和桌面 Chrome 不同:

  1. 语法:解析不了 ?.、??。SDK 已在打包时降到 chrome69。业务工程自己的源码也要同样降级,否则页面脚本仍会在 WebView 里直接语法报错。Vite 示例:
export default defineConfig({
  build: { target: 'chrome69' },
  esbuild: { target: 'chrome69' },
  optimizeDeps: { esbuildOptions: { target: 'chrome69' } },
})
  1. WebRTC:该 WebView 默认 SDP 为 Plan B,JsSIP 需要 Unified Plan。SDK 创建 RTCPeerConnection 时会带上 sdpSemantics: 'unified-plan'。Chrome 72 及以后本来就是这个默认值,更新版本会忽略该字段。
  2. 静音 / 关视频:静音只把 Web Audio 增益设为 0,音频发送轨保持 enabled,继续发送语音静音 RTP,避免对端媒体超时挂断。不发送视频黑帧。关视频时 replaceTrack(null),视频 RTP 停止;重新打开时再挂上视频轨。Chrome 69 上拆掉的摄像头轨可能变成 ended,Android 会重新采集后再 replaceTrack。AudioContext.resume() 在呼叫、接听、静音的点击里同步调用,并且发生在 getUserMedia 之前。

原生壳还需自行处理,SDK 做不到:

  • 页面必须是 HTTPS(或 localhost)
  • WebChromeClient.onPermissionRequest 里放行摄像头、麦克风
  • WebSettings.setMediaPlaybackRequiresUserGesture(false),<video> 加 playsinline
  • 屏幕共享依赖 getDisplayMedia(Chrome 72+),Android 9 系统 WebView 没有该 API

安装

在目标项目中安装依赖(示例使用 npm):

npm install @vostone/web-sdk vue

依赖说明:JsSIP 已打入 SDK 产物;crypto-js、events 列为本包 dependencies,一般会随 SDK 自动安装。Vue 3 仍为 peerDependency,需一并安装。

使用 Vite 时(重要)

SDK依赖 Node 风格的 events。构建后会在产物中 静态 import npm 的 events。Vite 默认会把模块名 events 当成 Node 内置并打成空桩,运行时会报错(例如 Dynamic require of "events" is not supported 或 EventEmitter is not exported by __vite-browser-external)。

请在 vite.config.ts 中为 events 配置 alias,指向本机安装的 npm 包(建议在应用里显式依赖 "events": "^3.3.0",保证路径稳定):

import { fileURLToPath } from 'url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  resolve: {
    alias: {
      events: fileURLToPath(new URL('./node_modules/events/events.js', import.meta.url)),
    },
  },
  plugins: [vue()],
})

vite.config.ts 若使用 import.meta.url,可为 tsconfig.node.json 增加 "types": ["node"] 并安装 @types/node(开发依赖)。

若通过 monorepo / file: 引用本地包,构建 SDK 后由应用安装即可:

cd packages/sip-web-sdk && npm install && npm run build

在应用中:

{
  "dependencies": {
    "@vostone/web-sdk": "file:../packages/sip-web-sdk"
  }
}

快速开始

1. 本地媒体

import { useLocalMedia } from '@vostone/web-sdk'

const localMedia = useLocalMedia({
  onOutgoingVideoTrackChanged: (track) => sipCall.replaceOutgoingVideoTrack(track),
  onOutgoingAudioTrackChanged: (track) => sipCall.replaceOutgoingAudioTrack(track),
})

在模板中挂载本地预览 video,并在 onMounted / nextTick 后调用:

localMedia.setLocalVideoElement(videoEl)
await localMedia.refreshDevices()

2. SIP 会话

将本地媒体适配器与远端 DOM 访问器传入 useSipCall:

import { useSipCall } from '@vostone/web-sdk'

const sipCall = useSipCall(
  {
    ensureLocalStreamReady: localMedia.ensureLocalStreamReady,
    ensureMicOnlyStreamReady: localMedia.ensureMicOnlyStreamReady,
    // 可选。不传时,ensure* 内部仍会在点击同步阶段恢复 AudioContext
    primeOutgoingAudio: localMedia.primeOutgoingAudio,
    stopLocalMedia: localMedia.stopLocalMedia,
    getOutgoingStream: localMedia.getOutgoingStream,
    getMediaStreamForIncomingAnswer: localMedia.getMediaStreamForIncomingAnswer,
    getOutgoingAudioTrack: localMedia.getOutgoingAudioTrack,
  },
  {
    remoteVideoEl: () => remoteVideoRef.value,
    remoteAudioEl: () => remoteAudioRef.value,
  },
  {
    // 必填:拉取注册账号的 GET 地址
    registerInfoUrl: 'https://your-api/caller/getRegisterInfo',
    // 必填,拉取注册账号的密钥
    auth: {
      appId: '...',
      accessKey: '...',
      accessSecret: '...',
    },
    debugJsSip: false,
  },
)

初始化拉取账号并注册:

await sipCall.loadSipConfig()
await sipCall.goOnline()

发起呼叫(target 为被叫号码或 SIP user 部分,具体与平台域名配置一致):

sipCall.makeCall(target, 'video') // 或 'audio' | 'oneWayVideo'

来电时由 sipCall.isIncomingCall / sipCall.incomingFrom 展示 UI,并调用:

sipCall.answerIncomingCall()
sipCall.rejectIncomingCall()

结束:

sipCall.hangup()
sipCall.goOffline()

API 说明

useLocalMedia(options?)

返回/方法 说明
cameraDevices / microphoneDevices 设备列表
selectedCameraId / selectedMicrophoneId 当前选中设备
refreshDevices() 刷新设备枚举
ensureLocalStreamReady() 保证本地音视频流(含屏幕共享时的组合逻辑)
ensureMicOnlyStreamReady() 仅麦克风,用于单向视频呼出等场景
switchToCamera() 切换摄像头后重新采集
startScreenShare() / stopScreenShare() 屏幕共享
toggleLocalMute() / toggleLocalVideo() 本地静音、关画面
stopLocalMedia() 停止本地轨道
setLocalVideoElement(el) 绑定本地预览 video

useSipCall(media, elements, options)

media(SipMediaAdapter):与 useLocalMedia 提供的方法一致,用于在呼叫/接听时获取 MediaStream 或替换发送端轨道。

elements(SipRemoteElements):

  • remoteVideoEl() / remoteAudioEl():返回远端渲染用的 HTMLVideoElement / HTMLAudioElement(可为 null)。

options(SipSdkOptions):

字段 说明
registerInfoUrl 必填。拉取 SIP 账号列表的 GET 完整 URL;SDK 不包含任何默认接口地址。为空或非法 URL 时,loadSipConfig() 会写入 registerError
auth 必填。HMAC 鉴权字段 appId、accessKey、accessSecret 须由业务注入,SDK 不包含任何默认密钥。任一项为空时,loadSipConfig() 会写入 registerError;服务端返回 401/403 时提示校验密钥是否正确
debugJsSip 为 true 时打开 JsSIP 调试输出

主要状态(ref):

status、currentUsername、registerError、callError、callNotice、isConfigLoading、isRegistering、isRegistered、isCalling、isIncomingCall、incomingFrom、sipConfig。

主要方法:

方法 说明
loadSipConfig() 请求注册信息并填充内部候选账号
goOnline() / goOffline() 注册上线 / 下线并清理会话
makeCall(target, mode?) mode: 'video' | 'audio' | 'oneWayVideo'
hangup() 挂断当前通话
answerIncomingCall() / rejectIncomingCall() 接听 / 拒接
replaceOutgoingVideoTrack / replaceOutgoingAudioTrack 通话中替换发送轨道(与 useLocalMedia 回调配合)

TypeScript

包内导出全部类型定义;应用侧需保证 Vue 单文件组件模块声明(如 declare module '*.vue')由本工程维护。

许可

MIT

Related Packages

@voicenter-team/vsip

A vue based jssip wrapper.

2,510 6
@tmsoft/webphone

WebPhone - SIP softphone component for Vue 3 and Web Components

11,607
@tencentcloud/roomkit-web-vue3

腾讯云 TUIRoomKit 音视频房间 UI 组件库(Vue3 版本)。提供会前预检与会中两套完整...

189,303 161
@tencentcloud/roomkit-electron-vue3

TUIRoomKit Conference (TUIRoomKit) is a product suitable for multi-person audio...

55,049 161

Version History

Version Released Vue License
1.2.3 ^3.4.0 MIT
1.2.2 ^3.4.0 MIT
1.2.0 ^3.4.0 MIT
1.1.2 ^3.4.0 MIT
1.1.1 ^3.4.0 MIT