@vostone/web-sdk
| Install | |
|---|---|
npm install @vostone/web-sdk |
|
| Latest Version: | 1.2.3 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Oct 22, 2026 |
| Links: | npm |
@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 不同:
- 语法:解析不了
?.、??。SDK 已在打包时降到chrome69。业务工程自己的源码也要同样降级,否则页面脚本仍会在 WebView 里直接语法报错。Vite 示例:
export default defineConfig({
build: { target: 'chrome69' },
esbuild: { target: 'chrome69' },
optimizeDeps: { esbuildOptions: { target: 'chrome69' } },
})
- WebRTC:该 WebView 默认 SDP 为 Plan B,JsSIP 需要 Unified Plan。SDK 创建
RTCPeerConnection时会带上sdpSemantics: 'unified-plan'。Chrome 72 及以后本来就是这个默认值,更新版本会忽略该字段。 - 静音 / 关视频:静音只把 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
TUIRoomKit Conference (TUIRoomKit) is a product suitable for multi-person audio...
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 | |
| 1.1.0 | ^3.4.0 | MIT | |
| 0.1.0 | ^3.4.0 | MIT |