@codeages/live-stack
v0.1.9
Published
面向浏览器端直播能力的 TypeScript 工具库,封装了 WHIP/WebRTC 推流、本地媒体轨道采集、信令适配和 PeerConnection 网络状态监控等能力。
Downloads
250
Keywords
Readme
@codeages/live-stack
面向浏览器端直播能力的 TypeScript 工具库,封装了 WHIP/WebRTC 推流、本地媒体轨道采集、信令适配和 PeerConnection 网络状态监控等能力。
本项目使用 Vite library mode 构建,包入口为 src/main.ts,构建产物输出到 dist。
特性
- WHIP 推流客户端:创建
RTCPeerConnection、发布音视频轨道、停止推流、替换轨道。 - WHIP 推流监控:
WHIPClient内置采样网络质量、码率和采集异常,并通过同一事件总线派发。 - 信令适配:内置标准 WHIP 信令和腾讯云 WebRTC 推流信令。
- 自动重连:可配置最大重连次数,连接
disconnected或failed时自动重建推流连接。 - 本地媒体辅助:列出摄像头/麦克风,创建摄像头、麦克风、屏幕共享轨道。
- 编码 Transform 支持:可注入音视频
Worker,用于RTCRtpScriptTransform或createEncodedStreams()场景。 - 类型友好:使用 TypeScript 编写,并随构建产物生成类型声明。
安装
pnpm add @codeages/live-stack也可以使用 npm 或 yarn:
npm install @codeages/live-stack
yarn add @codeages/live-stack快速开始
import { LocalMedia, WHIPClient } from '@codeages/live-stack'
const [cameraTrack, microphoneTrack] = await LocalMedia.createCameraAndMicrophoneTracks({
video: {
width: { ideal: 1280 },
height: { ideal: 720 },
frameRate: { ideal: 30 },
},
audio: {
channelCount: 1,
sampleRate: 48000,
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true,
},
})
const client = new WHIPClient(
'https://example.com/whip/live/stream',
{
videoBitrate: 1_500_000,
audioBitrate: 64_000,
maxReconnectAttempts: 3,
monitor: {
sampleIntervalMs: 2000,
},
},
console,
)
client.on('metrics', ({ metrics }) => {
console.log(metrics.actualBitrate, metrics.networkQuality)
})
client.on('networkQuality', ({ current }) => {
console.log('network quality:', current)
})
client.on('issue', ({ type, severity, details }) => {
console.warn(type, severity, details)
})
await client.publish([cameraTrack, microphoneTrack])
// 需要切换屏幕共享或摄像头时,可以替换同类型轨道。
const [screenTrack] = await LocalMedia.createScreenTrack({
video: true,
audio: false,
})
await client.replaceTrack(screenTrack)
// 停止推流只关闭 WHIP/WebRTC 连接,不会主动停止调用方传入的媒体轨道。
await client.stop()
cameraTrack.stop()
microphoneTrack.stop()
screenTrack.stop()浏览器媒体采集需要在安全上下文中运行,通常是 https:// 或 http://localhost。
API
当前包入口导出以下模块:
export * from './whip/whip-client'
export * from './whip/whip-monitor'
export * from './media/black-frame-video-generator'
export * from './media/local-media'
export * from './utils/adjust-server-clock'
export * from './utils/format'SEI 插入 worker 会作为独立入口随包发布,不会并入包根入口。
WHIPClient
WHIPClient 用于将本地音视频轨道发布到 WHIP 或兼容的 WebRTC 推流服务。
const client = new WHIPClient(url, config, logger)
await client.publish(streamOrTracks)
await client.replaceTrack(newTrack)
await client.stop()
const pc = client.getConnection()
const metrics = client.getMonitorLatestMetrics()
const quality = client.getMonitorNetworkQuality()构造参数:
| 参数 | 类型 | 说明 |
| -------- | --------------------------- | -------------------------------------------------- |
| url | string | WHIP endpoint 或信令适配器需要的推流地址。 |
| config | Partial<WHIPClientConfig> | 可选推流配置。 |
| logger | Logger | 可选日志对象,默认使用 ts-log 的 dummyLogger。 |
WHIPClientConfig:
| 字段 | 类型 | 默认值 | 说明 |
| ---------------------- | ------------------------------------- | ------------ | ----------------------------------------------------------- |
| videoCodec | string \| null | null | 预留视频编码配置。 |
| audioCodec | string \| null | null | 预留音频编码配置。 |
| videoBitrate | number | 0 | 视频最高码率,单位 bps;0 表示不设置。 |
| audioBitrate | number | 0 | 音频最高码率,单位 bps;0 表示不设置。 |
| videoTransformWorker | Worker \| null | null | 视频编码 Transform Worker。 |
| audioTransformWorker | Worker \| null | null | 音频编码 Transform Worker。 |
| maxReconnectAttempts | number | 0 | 最大自动重连次数;0 表示不重连。 |
| signalingClient | string | 'Standard' | 信令实现名称,支持 'Standard'、'TencentCloud'。 |
| monitor | false \| Partial<WHIPMonitorConfig> | {} | 内置监控配置;默认启用,设为 false 时关闭监控采样和事件。 |
注意事项:
publish()接受MediaStream或MediaStreamTrack[]。replaceTrack()会查找同类型 sender 并调用RTCRtpSender.replaceTrack()。stop()会关闭RTCPeerConnection并调用信令 stop,但不会停止媒体轨道;轨道生命周期由调用方管理。- 启用自动重连时,客户端会复用仍处于
live状态的媒体轨道。 - 监控由
WHIPClient自动启动和停止,使用方直接通过client.on('metrics' | 'networkQuality' | 'issue', ...)订阅事件。
SEI 插入 Worker
包内置的 SEI 插入 worker 会在视频关键帧中插入带服务端时间戳的 SEI 数据。使用方可以从包子路径拿到 worker URL,并传给 WHIPClient:
import seiInsertWorkerUrl from '@codeages/live-stack/sei-insert-worker?worker&url'
import { adjustServerClock, WHIPClient } from '@codeages/live-stack'
const serverClock = await adjustServerClock('/apiapp/time')
const videoTransformWorker = new Worker(seiInsertWorkerUrl, {
type: 'module',
})
videoTransformWorker.postMessage({
operation: 'serverClock',
time: serverClock.now(),
})
const client = new WHIPClient(whipUrl, {
videoTransformWorker,
})构建后该 worker 对应 dist/sei-insert-worker.js,包通过 @codeages/live-stack/sei-insert-worker 子路径导出。上面的 ?worker&url 写法适用于 Vite;其他打包器可按自身的 worker/asset URL 规则引用该子路径。
LocalMedia
LocalMedia 提供常用的媒体设备和轨道创建方法。
const cameras = await LocalMedia.listCameras()
const microphones = await LocalMedia.listMicrophones()
const cameraTrack = await LocalMedia.createCameraTrack({ width: 1280, height: 720 })
const microphoneTrack = await LocalMedia.createMicrophoneTrack({ echoCancellation: true })
const [videoTrack, audioTrack] = await LocalMedia.createCameraAndMicrophoneTracks({
video: true,
audio: true,
})
const [screenVideoTrack, screenAudioTrack] = await LocalMedia.createScreenTrack({
video: true,
audio: true,
})说明:
listCameras()和listMicrophones()会临时请求设备权限,枚举完成后会停止临时轨道。createScreenTrack()返回[MediaStreamTrack, MediaStreamTrack | null],屏幕音频是否可用取决于浏览器和用户选择。- 调用方负责在不再需要时执行
track.stop()。
信令客户端
包内置 createSignalingClient(),用于按名称创建信令实现。
import { createSignalingClient } from '@codeages/live-stack'
const signaling = createSignalingClient('Standard')支持的实现:
| 名称 | 说明 |
| -------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Standard | 标准 WHIP:POST offer SDP 到 endpoint,并使用响应头 Location 作为 resource URL;停止时对 resource URL 发送 DELETE。 |
| TencentCloud | 腾讯云 WebRTC 推流信令:使用腾讯云 pushstream/stopstream 接口完成 offer/answer 和停止推流。 |
也可以直接实现 SignalingClient 接口,用于自定义信令流程。
WHIP 推流监控
WHIPClient 默认创建内置 WHIPMonitor,进入推流流程后自动启动,stop() 时自动停止。业务侧不需要单独创建或管理 Monitor 生命周期:
const client = new WHIPClient(whipUrl, {
monitor: {
sampleIntervalMs: 2000,
warmupMs: 3000,
},
})
client.on('metrics', ({ metrics }) => {
console.log(metrics.actualBitrate, metrics.lossRate, metrics.rtt)
})
client.on('networkQuality', ({ previous, current, driver }) => {
console.log(previous, current, driver)
})
client.on('issue', ({ type, severity, details }) => {
console.warn(type, severity, details)
})如果不需要监控,可在构造时关闭:
const client = new WHIPClient(whipUrl, {
monitor: false,
})本地开发
安装依赖:
pnpm install启动 Vite 开发服务器:
pnpm dev启动后可以打开 WHIP 示例:
http://localhost:5173/examples/whip/whip.html构建库产物:
pnpm build格式、lint 和构建检查:
pnpm fmt:check
pnpm lint
pnpm build示例
WHIP 推流示例
示例文件位于 examples/whip/:
examples/whip/whip.html:页面结构和输入控件。examples/whip/whip.ts:打开摄像头、创建WHIPClient、发布和停止推流。
示例中还演示了如何创建编码 Transform Worker:
import seiInsertWorkerUrl from '@codeages/live-stack/sei-insert-worker?worker&url'
const videoTransformWorker = new Worker(seiInsertWorkerUrl, {
type: 'module',
})该 worker 会在关键帧中插入带时间戳的 SEI 数据,适合本地调试编码 Transform 链路。
FLV 播放示例
examples/flv-player/ 提供了一个简单的 FLV 播放页面,用于调试播放链路。
项目结构
src/
main.ts # 包入口
media/
local-media.ts # 本地媒体设备和轨道辅助方法
black-frame-video-generator.ts # 黑帧视频轨道生成器
sei-insert-worker.ts # 编码 Transform Worker,单独打包发布
utils/
adjust-server-clock.ts # 服务端时间同步工具
format.ts # 格式化工具
whip/
whip-client.ts # WHIP/WebRTC 推流客户端
signaling.ts # 标准 WHIP 和腾讯云信令实现
examples/
whip/ # WHIP 推流调试页面
flv-player/ # FLV 播放调试页面公共 API 统一从 src/main.ts 导出;worker 这类运行时脚本作为独立入口从 package.json 的 exports 子路径暴露。
浏览器兼容性
本库面向浏览器运行时,依赖的能力包括:
navigator.mediaDevices.getUserMedia()navigator.mediaDevices.getDisplayMedia()RTCPeerConnectionRTCRtpScriptTransform或RTCRtpSender.createEncodedStreams()Workerfetch
部分内部工具还依赖:
OffscreenCanvasMediaStreamTrackGeneratorVideoFrame
这些能力在不同浏览器和版本中的支持情况不同。业务代码应在使用前做特性检测,并为不支持的浏览器提供降级路径。
发布说明
构建配置位于 vite.config.ts:
- library entries:
src/main.ts、src/media/sei-insert-worker.ts - format:ES module
- JS 输出:
dist/lib.js - Worker 输出:
dist/sei-insert-worker.js - 类型声明:
dist/lib.d.ts
package.json 发布 dist/lib.* 和 dist/sei-insert-worker.*,并通过 exports 暴露包根入口和 ./sei-insert-worker 子路径入口。
