2021-07-20 04:19:06 +08:00
|
|
|
import {
|
|
|
|
EFFECT_TYPES,
|
|
|
|
BLUR_FILENAME,
|
|
|
|
createVirtualBackgroundStream,
|
2022-07-13 01:50:16 +08:00
|
|
|
} from '/imports/ui/services/virtual-background/service';
|
2021-07-20 04:19:06 +08:00
|
|
|
import MediaStreamUtils from '/imports/utils/media-stream-utils';
|
|
|
|
import { EventEmitter2 } from 'eventemitter2';
|
|
|
|
|
2022-07-13 01:50:16 +08:00
|
|
|
export default class BBBVideoStream extends EventEmitter2 {
|
|
|
|
static isVirtualBackground(type) {
|
|
|
|
return type === EFFECT_TYPES.IMAGE_TYPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static trackStreamTermination(stream, handler) {
|
2022-09-06 03:06:22 +08:00
|
|
|
const _handler = () => {
|
|
|
|
handler({ id: stream?.id });
|
|
|
|
};
|
|
|
|
|
2021-07-20 04:19:06 +08:00
|
|
|
// Dirty, but effective way of checking whether the browser supports the 'inactive'
|
|
|
|
// event. If the oninactive interface is null, it can be overridden === supported.
|
|
|
|
// If undefined, it's not; so we fallback to the track 'ended' event.
|
|
|
|
// The track ended listener should probably be reviewed once we create
|
|
|
|
// thin wrapper classes for MediaStreamTracks as well, because we'll want a single
|
|
|
|
// media stream holding multiple tracks in the future
|
|
|
|
if (stream.oninactive === null) {
|
2022-09-06 03:06:22 +08:00
|
|
|
stream.addEventListener('inactive', _handler, { once: true });
|
2021-07-20 04:19:06 +08:00
|
|
|
} else {
|
|
|
|
const track = MediaStreamUtils.getVideoTracks(stream)[0];
|
|
|
|
if (track) {
|
2022-09-06 03:06:22 +08:00
|
|
|
track.addEventListener('ended', _handler, { once: true });
|
2021-07-20 04:19:06 +08:00
|
|
|
// Extra safeguard: Firefox doesn't fire the 'ended' when it should
|
|
|
|
// but it invokes the callback (?), so hook up to both
|
2022-09-06 03:06:22 +08:00
|
|
|
track.onended = _handler;
|
2021-07-20 04:19:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor(mediaStream) {
|
|
|
|
super();
|
|
|
|
this.mediaStream = mediaStream;
|
|
|
|
this.originalStream = mediaStream;
|
|
|
|
this.effect = null;
|
|
|
|
this.virtualBgEnabled = false;
|
|
|
|
this.virtualBgService = null;
|
|
|
|
this.virtualBgType = EFFECT_TYPES.NONE_TYPE;
|
|
|
|
this.virtualBgName = BLUR_FILENAME;
|
|
|
|
this._trackOriginalStreamTermination();
|
|
|
|
}
|
|
|
|
|
2022-07-13 01:50:16 +08:00
|
|
|
set mediaStream(mediaStream) {
|
2021-07-20 04:19:06 +08:00
|
|
|
if (!this.mediaStream
|
|
|
|
|| mediaStream == null
|
|
|
|
|| mediaStream.id !== this.mediaStream.id) {
|
|
|
|
const oldStream = this.mediaStream;
|
|
|
|
this._mediaStream = mediaStream;
|
|
|
|
this.emit('streamSwapped', {
|
|
|
|
oldStream,
|
|
|
|
newStream: this.mediaStream,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-13 01:50:16 +08:00
|
|
|
get mediaStream() {
|
2021-07-20 04:19:06 +08:00
|
|
|
return this._mediaStream;
|
|
|
|
}
|
|
|
|
|
2022-07-13 01:50:16 +08:00
|
|
|
set virtualBgService(service) {
|
2021-07-20 04:19:06 +08:00
|
|
|
this._virtualBgService = service;
|
|
|
|
}
|
|
|
|
|
2022-07-13 01:50:16 +08:00
|
|
|
get virtualBgService() {
|
2021-07-20 04:19:06 +08:00
|
|
|
return this._virtualBgService;
|
|
|
|
}
|
|
|
|
|
2022-07-13 01:50:16 +08:00
|
|
|
_trackOriginalStreamTermination() {
|
2022-09-06 03:06:22 +08:00
|
|
|
const notify = ({ id }) => {
|
|
|
|
this.emit('inactive', { id });
|
2021-07-20 04:19:06 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
BBBVideoStream.trackStreamTermination(this.originalStream, notify);
|
|
|
|
}
|
|
|
|
|
2022-07-13 01:50:16 +08:00
|
|
|
_changeVirtualBackground(type, name, customParams) {
|
2021-07-20 04:19:06 +08:00
|
|
|
try {
|
|
|
|
this.virtualBgService.changeBackgroundImage({
|
|
|
|
type,
|
|
|
|
name,
|
2022-07-13 01:50:16 +08:00
|
|
|
isVirtualBackground: BBBVideoStream.isVirtualBackground(type),
|
2022-04-12 01:09:13 +08:00
|
|
|
customParams,
|
2021-07-20 04:19:06 +08:00
|
|
|
});
|
2021-12-03 20:49:32 +08:00
|
|
|
this.virtualBgType = type;
|
|
|
|
this.virtualBgName = name;
|
2021-07-20 04:19:06 +08:00
|
|
|
return Promise.resolve();
|
|
|
|
} catch (error) {
|
|
|
|
return Promise.reject(error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-13 01:50:16 +08:00
|
|
|
startVirtualBackground(type, name = '', customParams) {
|
2022-04-12 01:09:13 +08:00
|
|
|
if (this.virtualBgService) return this._changeVirtualBackground(type, name, customParams);
|
2021-07-20 04:19:06 +08:00
|
|
|
|
|
|
|
return createVirtualBackgroundStream(
|
|
|
|
type,
|
|
|
|
name,
|
2022-07-13 01:50:16 +08:00
|
|
|
BBBVideoStream.isVirtualBackground(type),
|
2022-04-12 01:09:13 +08:00
|
|
|
this.mediaStream,
|
|
|
|
customParams,
|
2021-07-20 04:19:06 +08:00
|
|
|
).then(({ service, effect }) => {
|
|
|
|
this.virtualBgService = service;
|
|
|
|
this.virtualBgType = type;
|
|
|
|
this.virtualBgName = name;
|
|
|
|
this.originalStream = this.mediaStream;
|
|
|
|
this.mediaStream = effect;
|
|
|
|
this.isVirtualBackgroundEnabled = true;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-08-26 22:50:46 +08:00
|
|
|
changeCameraBrightness(brightness) {
|
|
|
|
if (!this.virtualBgService) return;
|
|
|
|
|
|
|
|
this.virtualBgService.brightness = brightness;
|
|
|
|
}
|
|
|
|
|
|
|
|
toggleCameraBrightnessArea(value) {
|
|
|
|
if (!this.virtualBgService) return;
|
|
|
|
|
|
|
|
this.virtualBgService.wholeImageBrightness = value;
|
|
|
|
}
|
|
|
|
|
2022-07-13 01:50:16 +08:00
|
|
|
stopVirtualBackground() {
|
2021-07-20 04:19:06 +08:00
|
|
|
if (this.virtualBgService != null) {
|
|
|
|
this.virtualBgService.stopEffect();
|
|
|
|
this.virtualBgService = null;
|
|
|
|
}
|
|
|
|
|
2021-12-03 20:49:32 +08:00
|
|
|
this.virtualBgType = EFFECT_TYPES.NONE_TYPE;
|
|
|
|
this.virtualBgName = undefined;
|
2021-07-20 04:19:06 +08:00
|
|
|
this.mediaStream = this.originalStream;
|
|
|
|
this.isVirtualBackgroundEnabled = false;
|
|
|
|
}
|
|
|
|
|
2022-07-13 01:50:16 +08:00
|
|
|
stop() {
|
2021-07-20 04:19:06 +08:00
|
|
|
if (this.isVirtualBackgroundEnabled) {
|
|
|
|
this.stopVirtualBackground();
|
|
|
|
}
|
|
|
|
|
|
|
|
MediaStreamUtils.stopMediaStreamTracks(this.mediaStream);
|
|
|
|
this.originalStream = null;
|
|
|
|
this.mediaStream = null;
|
|
|
|
}
|
|
|
|
}
|