TrackModeSession
TrackModeSession
是房间管理模块,所有和房间有关系的操作都通过这个模块来实现。
构造函数
import * as QNRTC from "pili-rtc-web";
const myRoom = new TrackModeSession();
无论重复几次加入离开房间,确保一个页面只能有一个房间模块的实例
构造函数中可以传入一个配置对象 QNRTCConfig
,结构如下:
export interface QNRTCConfig {
// 传输协议
transportPolicy?: "forceUdp" | "forceTcp" | "preferUdp";
// 开启大小流
simulcast?: boolean;
// 网络重连次数
reconnectTimes?: number;
// 网络请求超时时间(ms)
requestTimeout?: number;
}
该对象在 SDK 中的默认值为:
const DEFAULT_CONFIG: Required<QNRTCConfig> = {
transportPolicy: "forceUdp",
simulcast: false,
reconnectTimes: 3,
requestTimeout: 5000
};
transportPolicy
如果您所在的网络环境不支持 UDP
通信,可以在实例化时修改底层的媒体传输方式。
const myRoom = new TrackModeSession({
transportPolicy: "preferUdp",
});
一共支持 3 个值,forceUdp
表示强制使用 UDP
传输, forceTcp
表示强制使用 TCP
传输, preferUdp
表示默认使用 UDP
, 当检测到 UDP
不通时回落到 TCP
,默认值为 preferUdp
。
simulcast
如果想要开启 视频大小流 功能,可以在配置对象设置 simulcast
。
const myRoom = new TrackModeSession({
simulcast: true,
});
reconnectTimes
如果想要自定义网络异常时 WebSocket 连接的自动重连次数,可以在配置对象设置 reconnectTimes
。当发生网络异常时,会触发重连逻辑,SDK 内部会每隔 1s 尝试重连一次。当 reconnectTimes
用完时,SDK 会触发 disconnect
(10007) 回调,表示断线重连失败。
requestTimeout
如果想要定义网络请求超时时间,可以定义参数 requestTimeout
。该参数的默认值为 5000ms,表示如果在 5000ms 内没有请求成功,则触发超时,抛出错误码(11016)。
userId
string
| undefined
类型 表示自己在房间中的 userId
,只有成功加入房间后才有值
roomName
string
| undefined
类型 表示当前房间的名称,只有成功加入房间后才有值
users
User>
类型 Array<表示房间当前的用户列表,具体每个 User
的详细信息可以参考 User 模块。如果没有加入房间,将会返回空列表。
trackInfoList
TrackInfo>
类型 Array<表示房间中当前所有其他人的 TrackInfo
,每次房间中有人发布或者取消发布,这个值都会自动更新。
roomState
number
类型 表示当前房间的连接状态,如果房间不是已连接的状态,除了离开房间/加入房间以外的方法都不能调用。如果想感知房间的 roomState
变化,可以通过监听 room-state-change
事件来实现,具体参见页面下方的 事件列表
enum RoomState {
Idle = 0, // 未连接
Connecting = 1, // 正在连接
Connected = 2, // 已连接
Reconnecting = 3, // 正在重新连接
}
publishedTracks
Track>
类型 Array<房间中自己所有已经发布的 Track
对象列表
subscribedTracks
Track>
类型 Array<房间中自己所有已经订阅的 Track
对象列表
mergeStreamTracks
Array<string>
类型 房间中已经添加到合流画面中的 trackId
列表, 关于合流的详细细节可以参考 合流转推
recorder
QNMediaRecorder
类型音视频录制对象。
checkSystemRequirements()
静态方法,用于检测浏览器的实际支持情况。
interface SystemRequirementsTestResult {
// 测试的房间名
roomName: string;
// 测试结果,是否通过
ok: boolean;
// 错误原因
reason: string;
// 平均 rtt 值
avgRTT: number;
// 平均丢包率
avgPacketLossRate: number;
// 平均音频码率
avgAudioBitrate: number;
// 平均视频码率
avgVideoBitrate: number;
// 平均音量
avgVolumnLevel: number;
}
注意,该方法会实际运行一遍一对一通话的基本流程,大概需要耗时 30s 左右。如果想要直接通过浏览器版本号和接口来判断是否支持 RTC 通话,可以使用 browserReport 接口。
joinRoomWithToken(roomToken, userData)
加入房间
string
roomToken: 加入房间的凭证 token,详细可以参考 加入房间
string
| undefined
userData: 用户的额外数据
User>>
返回: Promise<Array<异步操作完成后,会返回当前加入房间的用户列表
publish(tracks)
发布媒体对象
Track>
tracks: Array<传入 Track
对象,将这些媒体数据发布到房间中。
可以通过 getLocalTracks 采集本地的
Track
对象。
Promise<void>
返回: 异步操作完成后,认为发布成功
unpublish(trackIds)
取消发布
Array<string>
trackIds: 想要取消发布的 trackId
列表,trackId
可以通过 TrackInfo 来获取
取消发布后,SDK 不会自动释放对应的
Track
对象,还可以正常播放,如果想手动释放,参考释放媒体对象
Promise<void>
返回: 异步操作完成后,认为取消发布成功
subscribe(trackIds: string[], strictMode: boolean = false, trackProfiles?: TrackProfiles)
订阅远端的 Track
Array<string>
trackIds: 想要订阅的 trackId
列表,trackId
可以通过 TrackInfo 来获取
boolean
可选
strictMode: 是否使用严格模式订阅,默认为 false
trackProfiles 可选
TrackProfiles
的格式如下。
export type TrackProfiles = {
[key: string]: Profile;
}
export type Profile = 'high' | 'medium' | 'low'
通过指定一个 trackId 为 key,同时指定大小流 Profile,可以指定订阅该 track 大小流中的视频质量。
订阅过程中会有一种小概率的极端情况——订阅目标在我们订阅操作的中途取消了发布。无疑,这将会导致我们无法订阅到这个目标,这里 SDK 会根据严格模式的不同采取不同的逻辑。比如我们同时订阅了 6 路 Track,其中 1 路出现了这个情况,如果开启严格模式,SDK 会停止全部 6 路 Track 的订阅直接返回一个
10041
错误,如果不开启严格模式,SDK 会跳过订阅这路 Track,将剩下的 5 路 Track 返回。
Track>
返回: Promise<异步操作完成后,会返回和提供 trackId
对应的 Track
对象
unsubscribe(trackIds)
取消订阅
Array<string>
trackIds: 想要取消订阅的 trackId
列表,trackId
可以通过 TrackInfo 来获取
Promise<void>
返回: 异步操作完成后,认为取消订阅成功
取消订阅后,SDK 会自动释放对应的
Track
对象
muteTracks(tracks)
将自己本地已经发布的 Track
对象静音或者取消静音,这个静音动作会被广播给全房间,其他用户可以通过 mute-tracks
事件来感知。
Array<{trackId: string, muted: boolean}>
tracks: 一个列表,每个列表项有一个 trackId
和 muted
项,表示这个 Track
的静音状态。
视频 Track 和音频 Track 都可以设置静音,静音操作的本质就是保留数据通道但是不发送数据,视频 Track 静音后会黑屏。
muteRemoteAudio(boolean)
mute 远端音频,设置 mute 为 true 后将无法听到远端的声音。
kickoutUser(userId)
将指定的目标用户踢出房间,只有拥有管理员权限的用户才能调用此方法,用户的权限是在加入房间时提供的 roomToken
中指定的。
string
userId: 目标用户的用户名
Promise<void>
返回 异步操作完成后,认为踢出房间成功
createMergeJob(id, option)
创建一个默认合流以外的合流 Job。默认情况下,一个房间只能合成一路 RTMP 流,这一路 RTMP 的设定是通过 七牛控制台 或者通过 服务端 API 来配置。在部分特殊场景下,可能需要一个房间合成多路 RTMP 流,此时就可以使用这个 API 创建一个新的合流 Job。
string
id: 指定这个合流 Job 的 ID,不同的合流 Job 通过这个 id 来区分,在合流 API 中,如果没有传入 JobID,就认为使用默认的合流。
MergeJobOption
option: 配置这个合流 Job,具体配置可以见下:
Promise<void>
返回 异步操作完成后,认为创建合流 Job 成功
MergeJobOption {
publishUrl: string; // 这个 JOB 最终输出的 RTMP 地址
height?: number; // 输出画面的宽度
width?: number; // 输出画面的高度
fps?: number; // 输出流的帧率
kbps?: number; // 输出流的码率
audioOnly?: boolean; // 是否只合流音频,默认 false
// 合流画面伸缩模式,分别是充满容器、适应于容器、拉伸以充满容器
stretchMode?: "aspectFill" | "aspectFit" | "scaleToFit";
watermarks?: WaterMark[]; // 指定水印图片
background?: Background; // 指定背景图片
maxRate?: number; // 最高码率(kbps)
minRate?: number; // 最低码率(kbps)
// 是否保留 track 断开连接前最后一帧,默认为 false
holdLastFrame?: boolean;
}
WaterMark
对象和 Background
对象的格式相同,具体如下:
{
w: number; // 指定图片在合流画面中的宽度
h: number; // 指定图片在合流画面中的高度
x: number; // 指定图片位于合流画面 x 轴的位置
y: number; // 指定图片位于合流画面 y 轴的位置
url: string; // 图片链接
}
注意,url
传入背景或者水印的图片链接。图片格式要求如下:
- 必须是 PNG 格式
- 必须要有 alpha 通道
- 图片链接必须使用 HTTP 协议
setDefaultMergeStream(width, height, jobId?)
开启默认合流,默认合流布局的逻辑是 覆盖画面 和 尽量等分,具体的合流使用可以参考 合流转推
number
width: 默认合流输出的画面宽度,一般和控制台或者服务端设置的对应
number
height: 默认合流输出的画面高度,一般和控制台或者服务端设置的对应
string
可选
jobId: 指定这个默认合流的合流 Job,关于 Job 的介绍查看 createMergeJob,大部分情况不需要设置这个值
请确保一个房间在同一时刻只有一个用户调用此方法
addMergeStreamTracks(mergeOpts, jobId?)
通过指定 trackId
的方式将将指定的 Track
加入到合流画面之中
Array<TrackMergeOptions>
mergeOpts: TrackMergeOptions
的形式如下:
TrackMergeOptions {
trackId: string, // 指定要加入合流画面的 trackId
x: number, // 指定这个 Track 位于合流画面 x 轴的位置
y: number, // 指定这个 Track 位于合流画面 y 轴的位置
w: number, // 指定这个 Track 在合流画面上的宽度
h: number, // 指定这个 Track 在合流画面上的高度
z: number, // 指定这个 Track 在合流画面的覆盖等级(zIndex)
// 指定这个 track 画面伸缩模式,分别是充满容器、适应于容器、拉伸以充满容器
stretchMode: "aspectFill" | "aspectFit" | "scaleToFit",
}
如果指定的 Track
是音频 Track,则 x
,y
,w
,h
,z
,stretchMode
可以不填。
当未指定 stretchMode
值时,stretchMode
默认继承 mergeJob 中配置的拉伸模式。
string
可选
jobId: Promise<void>
返回:指定需要添加 Track 的合流 Job,关于 Job 的介绍查看 createMergeJob,大部分情况不需要设置这个值
当第一次调用这个方法成功的时候,就认为合流开始
removeMergeStreamTracks(trackIds)
通过 trackId
将之前指定的 Track
从合流画面中删除
Array<string>
trackIds: 指定的 trackId
列表
string
可选
jobId: Promise<void>
返回:指定需要删除 Track 的合流 Job,关于 Job 的介绍查看 createMergeJob,大部分情况不需要设置这个值
stopMergeStream(jobId?)
string
可选
jobId: 指定一个合流 Job 停止合流,关于 Job 的介绍查看 createMergeJob,大部分情况不需要设置这个值
停止合流
leaveRoom()
离开房间,切断和房间以及流媒体服务的连接,释放所有订阅媒体的资源,roomState
会被重新置为 未连接
。如果需要重新加入房间,再次调用 joinRoomWithToken 即可
sendCustomMessage(message, userIds?, messageId?)
发送文本消息。
string
message: 要发送的文本消息。
string[]
可选
userIds: 接收文本消息的对象,格式为由 userId
字符串组成的数组。
如果不指定 userIds
参数,则表示在全房间内广播。
string
可选
messageId: 消息唯一 ID,如果不指定,则会默认生成。
pushCameraTrackWithImage
使用图片替换视频 track。方法签名如下。
public async pushCameraTrackWithImage(trackId: string, source?: string | ArrayBuffer | File): Promise<void>
注意,当参数 source
为 undefined
时,表示取消替换,恢复原本传输的视频 track。
setReconnectTimes(reconnectTimes: number)
设置自定义网络异常时 WebSocket 连接的自动重连次数。
getReconnectTimes()
获取网络异常时 WebSocket 连接的自动重连次数的当前配置。
事件列表
room-state-change
房间状态改变
事件参数
- roomState: RoomState 当前的房间状态
myRoom.on("room-state-change", roomState => {
console.log("current roomState is", roomState);
})
user-join
房间有除自己以外的新用户加入
事件参数
- user: User 新加入的用户对象
myRoom.on("user-join", user => {
console.log("new user!", user);
})
user-leave
房间有除自己以外的用户离开
事件参数
- user: User 离开的用户对象
myRoom.on("user-leave", user => {
console.log("user leave!", user);
})
track-add
房间中有其他用户发布了 Track
事件参数
- tracks: Array<TrackInfo> 新发布 Track 的 TrackInfo
myRoom.on("track-add", tracks => {
console.log("new tracks", tracks);
})
track-remove
房间中有其他用户取消发布了 Track
事件参数
- tracks: Array<TrackInfo> 取消发布 Track 的 TrackInfo
myRoom.on("track-remove", tracks => {
console.log("track removed", tracks);
})
mute-tracks
房间中其他用户的 Track 修改了静音状态
事件参数
- tracks:
Array<{trackId: string, muted: boolean}>
关于设置静音可以参考 muteTracks
myRoom.on("mute-tracks", tracks => {
for (const track of tracks) {
console.log("track", track.trackId, "muted", track.muted);
}
})
remote-track-stats
获取已订阅远端用户的传输状态数据
事件参数
- remoteTrackStats:
RemoteTrackStat[]
myRoom.on("remote-track-stats", remoteTrackStats => {
remoteTrackStats.forEach(stat => {
console.log("Remote track stat: ", stat);
});
});
RemoteTrackStat
接口格式如下:
export interface RemoteTrackStat {
userId: string, // 发布该路流的用户的 id
networkGrade: NetworkGrade,
kind: string, // 该路流的类型 audio | video
trackId: string, // 该路流的 id
packetLossRate: number, // 丢包率
rtt: number // 网络往返延时
}
NetworkGrade
表示网络质量等级枚举,含义如下:
export enum NetworkGrade {
/**
* 网络等级还未获取
*/
INVALID = -1,
/**
* 网络优
*/
EXCELLENT = 1,
/**
* 网络良
*/
GOOD = 2,
/**
* 网络一般
*/
FAIR = 3,
/**
* 网络较差
*/
POOR = 4
}
messages-received
接收文本消息
事件参数
- msgData: 接收到的文本消息。格式为数组,每个数组元素为一个消息对象,格式如下:
参数名 | 类型 | 含义 |
---|---|---|
timestamp | number | 消息时间戳 |
data | string | 消息内容 |
userId | string | 消息发送人ID |
type | string | 消息类型 |
注意,type
为消息类型,当前支持 normal
和 notify
类型(notify
类型为服务端通知消息,此时 playerid
为空)。
disconnect
其他原因导致和房间连接断开且不可恢复
事件参数
- code:
number
断开连接的原因 - data:
any
不同断开连接的原因的data
字段不同,具体见下面的表格
原因 | code | data |
---|---|---|
token 错误 | 10001 | 无 |
token 过期 | 10002 | 无 |
reconnect token 过期 | 10004 | 无 |
被管理员踢出房间 | 10006 | { userId: string } userId 是操作踢人的用户 |
断线重连失败 | 10007 | 无 |
该用户在其他页面或终端登录 | 10022 | 无 |
房间人数已满 | 10011 | 无 |
myRoom.on("disconnect", ({ code, data }) => {
if (code === 10006) {
console.log("被", data.userId, "踢出房间");
}
})
disconnect 触发后,SDK 会自动清空重置房间,如果有需要可以重新调用加入房间
remote-user-reconnecting
房间中远端用户正在重连
事件参数
- user: User 正在重连的远端用户对象
myRoom.on("remote-user-reconnecting", (user) => {
console.log("remote-user-reconnecting", user)
})
remote-user-reconnected
房间中远端用户重连成功
事件参数
- user: User 重连成功的远端用户对象
myRoom.on("remote-user-reconnected", (user) => {
console.log("remote-user-reconnected", user)
})
merge-job-connected
合流 Job 连接成功
事件参数
{ jobId: string }
合流 Job ID
myRoom.on("merge-job-connected", ({ jobId }) => {
console.log(jobId);
});
当通过 createMergeJob 接口创建自定义合流 Job,Job 连接成功后触发。
merge-job-disconnected
事件参数
{ jobId: string }
合流 Job ID
myRoom.on("merge-job-disconnected", ({ jobId }) => {
console.log(jobId);
});
当通过 stopMergeStream 接口关闭自定义合流 Job,Job 断开成功后触发。