@tencentcloud/roomkit-web-vue3
Version:
<h1 align="center"> TUIRoomKit</h1> Conference (TUIRoomKit) is a product suitable for multi-person audio and video conversation scenarios such as business meetings, webinars, and online education. By integrating this product, you can add room management,
290 lines (289 loc) • 11.3 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import TUIRoomEngine__default, { TUIVideoStreamType, TRTCVideoStreamType, TRTCVideoFillMode, TRTCVideoRotation, TRTCVideoMirrorType, TUIChangeReason, TUIRoomEvents } from "@tencentcloud/tuiroom-engine-js";
import { EventType } from "../types.mjs";
import { isMobile } from "../../utils/environment.mjs";
import { MESSAGE_DURATION } from "../../constants/message.mjs";
import logger from "../../utils/common/logger/index.mjs";
var StreamPlayMode = /* @__PURE__ */ ((StreamPlayMode2) => {
StreamPlayMode2["PLAY"] = "play";
StreamPlayMode2["STOP"] = "stop";
StreamPlayMode2["PLAY_IN_VISIBLE"] = "playInVisible";
return StreamPlayMode2;
})(StreamPlayMode || {});
var StreamPlayQuality = /* @__PURE__ */ ((StreamPlayQuality2) => {
StreamPlayQuality2["HIGH"] = "high";
StreamPlayQuality2["LOW"] = "low";
StreamPlayQuality2["Default"] = "default";
return StreamPlayQuality2;
})(StreamPlayQuality || {});
class MediaManager {
constructor(service) {
__publicField(this, "service");
__publicField(this, "intersectionObserver", null);
__publicField(this, "observerDataMap", /* @__PURE__ */ new Map());
__publicField(this, "observerRoot", null);
__publicField(this, "onUserVideoStateChanged", (eventInfo) => {
const { userId, streamType, hasVideo, reason } = eventInfo;
if (userId === this.service.basicStore.userId && !hasVideo && reason === TUIChangeReason.kChangedByAdmin) {
if (streamType === TUIVideoStreamType.kCameraStream) {
this.service.emit(EventType.ROOM_NOTICE_MESSAGE, {
type: "warning",
message: this.service.t("Your camera has been turned off"),
duration: MESSAGE_DURATION.NORMAL
});
}
if (streamType === TUIVideoStreamType.kScreenStream) {
this.service.emit(EventType.ROOM_NOTICE_MESSAGE_BOX, {
title: this.service.t("Your screen sharing has been stopped"),
message: this.service.t(
"Your screen sharing has been stopped, Now only the host/admin can share the screen"
),
confirmButtonText: this.service.t("I got it")
});
}
}
});
this.service = service;
this.bindRoomEngineEvents();
}
async startPlayVideo(options) {
var _a, _b, _c;
const { userId, streamType, view, observerViewInVisible } = options;
logger.info(
"MediaManager.startPlayVideo",
userId,
streamType,
view,
observerViewInVisible
);
const streamInfo = this.service.roomStore.getStreamInfo(userId, streamType);
if (!streamInfo) {
return;
}
(_a = streamInfo.playDomMap) == null ? void 0 : _a.set(view, streamType);
if (!observerViewInVisible) {
await this.doStartPlayVideo({ userId, streamType });
return;
}
this.initIntersectionObserver();
this.observerDataMap.set(
view,
Object.assign(this.observerDataMap.get(view) || {}, {
userId,
streamType
})
);
(_b = this.intersectionObserver) == null ? void 0 : _b.observe(view);
if ((_c = this.observerDataMap.get(view)) == null ? void 0 : _c.isIntersection) {
await this.doStartPlayVideo({ userId, streamType });
}
}
// If only one view wants to stop playing, update the viewList, but don't stop the stream.
// If no view is passed in, the stream is stopped.
async stopPlayVideo(options) {
var _a;
const { userId, streamType, view } = options;
logger.info("MediaManager.stopPlayVideo", userId, streamType, view);
const streamInfo = this.service.roomStore.getStreamInfo(userId, streamType);
if (!(streamInfo == null ? void 0 : streamInfo.playDomMap) || (streamInfo == null ? void 0 : streamInfo.playDomMap.size) === 0) {
return;
}
if (this.observerDataMap.get(view)) {
this.observerDataMap.delete(view);
(_a = this.intersectionObserver) == null ? void 0 : _a.unobserve(view);
}
streamInfo == null ? void 0 : streamInfo.playDomMap.delete(view);
if ((streamInfo == null ? void 0 : streamInfo.playDomMap.size) > 0) {
await this.doStartPlayVideo({
userId,
streamType
});
} else {
await this.doStopPlayVideo(options);
}
}
initIntersectionObserver() {
if (!this.intersectionObserver || document.getElementById("roomContainer") !== this.observerRoot) {
const observerRoot = document.getElementById("roomContainer");
this.intersectionObserver = new IntersectionObserver(
this.intersectionObserverCallback.bind(this),
{
root: observerRoot,
rootMargin: "0px"
}
);
this.observerDataMap = /* @__PURE__ */ new Map();
this.observerRoot = observerRoot;
}
}
intersectionObserverCallback(entries) {
entries.forEach((entry) => {
var _a;
const { isIntersecting, target } = entry;
const observerData = this.observerDataMap.get(target);
if (!observerData) {
return;
}
const { userId, streamType } = observerData;
const streamInfo = this.service.roomStore.getStreamInfo(
userId,
streamType
);
if (!streamInfo) {
return;
}
if (isIntersecting) {
observerData.isIntersection = true;
if ((streamInfo == null ? void 0 : streamInfo.playDomMap) && (streamInfo == null ? void 0 : streamInfo.playDomMap.size) > 0) {
this.doStartPlayVideo({ userId, streamType });
}
} else {
observerData.isIntersection = false;
const isContinuePlay = Array.from(
((_a = streamInfo == null ? void 0 : streamInfo.playDomMap) == null ? void 0 : _a.keys()) || []
).find(
(item) => {
var _a2;
return !this.observerDataMap.get(item) || ((_a2 = this.observerDataMap.get(item)) == null ? void 0 : _a2.isIntersection);
}
);
if (!isContinuePlay) {
this.doStopPlayVideo({ userId, streamType });
}
}
});
}
getPlayStreamType(userId, streamType) {
var _a;
if (streamType === TUIVideoStreamType.kScreenStream) {
return streamType;
}
const streamInfo = this.service.roomStore.getStreamInfo(userId, streamType);
if ((streamInfo == null ? void 0 : streamInfo.playDomMap) && (streamInfo == null ? void 0 : streamInfo.playDomMap.size) > 0) {
const playStreamTypeList = Array.from((_a = streamInfo == null ? void 0 : streamInfo.playDomMap) == null ? void 0 : _a.values());
if (playStreamTypeList.includes(TUIVideoStreamType.kCameraStream)) {
return TUIVideoStreamType.kCameraStream;
}
return TUIVideoStreamType.kCameraStreamLow;
}
return streamType;
}
async doStartPlayVideo(options) {
var _a, _b, _c;
const { userId, streamType } = options;
const streamInfo = this.service.roomStore.getStreamInfo(userId, streamType);
if (!streamInfo) {
return;
}
const playStreamType = this.getPlayStreamType(userId, streamType);
const viewIdList = Array.from(streamInfo.playDomMap.keys()).map((item) => {
if (item instanceof HTMLElement) {
return item == null ? void 0 : item.id;
}
return item;
});
this.service.roomStore.updateStreamInfo({
userId,
streamType,
isLoading: true
});
if (userId === this.service.basicStore.userId && streamType === TUIVideoStreamType.kCameraStream) {
(_a = this.service.roomEngine.instance) == null ? void 0 : _a.setLocalVideoView({ view: viewIdList });
} else {
(_b = this.service.roomEngine.instance) == null ? void 0 : _b.setRemoteVideoView({
userId,
streamType: playStreamType,
view: viewIdList
});
await this.setVideoRenderParams({ userId, streamType });
await ((_c = this.service.roomEngine.instance) == null ? void 0 : _c.startPlayRemoteVideo({
userId,
streamType: playStreamType
}));
}
this.service.roomStore.updateStreamInfo({
userId,
streamType,
isLoading: false
});
}
async setVideoRenderParams(options) {
var _a;
const { userId, streamType } = options;
if (userId !== this.service.basicStore.userId) {
const trtcCloud = (_a = this.service.roomEngine.instance) == null ? void 0 : _a.getTRTCCloud();
const trtcStreamType = streamType === TUIVideoStreamType.kScreenStream ? TRTCVideoStreamType.TRTCVideoStreamTypeSub : TRTCVideoStreamType.TRTCVideoStreamTypeBig;
let trtcFillMode = TRTCVideoFillMode.TRTCVideoFillMode_Fit;
if (isMobile && streamType !== TUIVideoStreamType.kScreenStream) {
trtcFillMode = TRTCVideoFillMode.TRTCVideoFillMode_Fill;
}
await (trtcCloud == null ? void 0 : trtcCloud.setRemoteRenderParams(userId, trtcStreamType, {
mirrorType: TRTCVideoMirrorType.TRTCVideoMirrorType_Disable,
rotation: TRTCVideoRotation.TRTCVideoRotation0,
fillMode: trtcFillMode
}));
}
}
async doStopPlayVideo(options) {
var _a, _b;
const { userId, streamType } = options;
this.service.roomStore.updateStreamInfo({
userId,
streamType,
isLoading: false
});
if (userId === this.service.basicStore.userId && streamType === TUIVideoStreamType.kCameraStream) {
(_a = this.service.roomEngine.instance) == null ? void 0 : _a.setLocalVideoView({ view: null });
} else {
await ((_b = this.service.roomEngine.instance) == null ? void 0 : _b.stopPlayRemoteVideo({
userId,
streamType
}));
}
}
onUserAudioStateChanged(eventInfo) {
const { userId, hasAudio, reason } = eventInfo;
if (userId === this.service.basicStore.userId && !hasAudio && reason === TUIChangeReason.kChangedByAdmin) {
this.service.emit(EventType.ROOM_NOTICE_MESSAGE, {
type: "warning",
message: this.service.t("Your microphone has been turned off"),
duration: MESSAGE_DURATION.NORMAL
});
}
}
dispose() {
this.intersectionObserver = null;
this.observerDataMap = /* @__PURE__ */ new Map();
}
bindRoomEngineEvents() {
TUIRoomEngine__default.once("ready", () => {
var _a, _b;
(_a = this.service.roomEngine.instance) == null ? void 0 : _a.on(
TUIRoomEvents.onUserVideoStateChanged,
this.onUserVideoStateChanged.bind(this)
);
(_b = this.service.roomEngine.instance) == null ? void 0 : _b.on(
TUIRoomEvents.onUserAudioStateChanged,
this.onUserAudioStateChanged.bind(this)
);
});
}
unbindRoomEngineEvents() {
var _a, _b;
(_a = this.service.roomEngine.instance) == null ? void 0 : _a.off(
TUIRoomEvents.onUserVideoStateChanged,
this.onUserVideoStateChanged
);
(_b = this.service.roomEngine.instance) == null ? void 0 : _b.off(
TUIRoomEvents.onUserAudioStateChanged,
this.onUserAudioStateChanged
);
}
}
export {
MediaManager,
StreamPlayMode,
StreamPlayQuality
};