Skip to content

Commit

Permalink
fix(service-providers): use standalone avatar for testing devices (#1876
Browse files Browse the repository at this point in the history
)
  • Loading branch information
hyrious authored Mar 23, 2023
1 parent edf7501 commit c2893e7
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
IServiceVideoChatUID,
} from "@netless/flat-services";
import { SideEffectManager } from "side-effect-manager";
import { RTCTestAvatar } from "./rtc-test-avatar";
import { RTCRemoteAvatar } from "./rtc-remote-avatar";
import { RTCLocalAvatar } from "./rtc-local-avatar";
import { AgoraRTCWebShareScreen } from "./rtc-share-screen";
Expand Down Expand Up @@ -205,8 +206,9 @@ export class AgoraRTCWeb extends IServiceVideoChat {
return remoteAvatar;
}

private _testAvatar?: RTCTestAvatar;
public getTestAvatar(): IServiceVideoChatAvatar {
return this.localAvatar;
return (this._testAvatar ??= new RTCTestAvatar({ rtc: this }));
}

public getVolumeLevel(uid?: IServiceVideoChatUID): number {
Expand Down
145 changes: 145 additions & 0 deletions service-providers/agora-rtc/agora-rtc-web/src/rtc-test-avatar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { IServiceVideoChatAvatar } from "@netless/flat-services";
import { SideEffectManager } from "side-effect-manager";
import { Val } from "value-enhancer";
import { AgoraRTCWeb } from "./agora-rtc-web";

export interface RTCAvatarConfig {
rtc: AgoraRTCWeb;
element?: HTMLElement | null;
}

export class RTCTestAvatar implements IServiceVideoChatAvatar {
private static LOW_VOLUME_LEVEL_THRESHOLD = 0.00001;

private readonly _rtc: AgoraRTCWeb;
private readonly _sideEffect = new SideEffectManager();

private readonly _shouldCamera$ = new Val(false);
private readonly _shouldMic$ = new Val(false);

private _volumeLevel = 0;

private readonly _el$: Val<HTMLElement | undefined | null>;

public enableCamera(enabled: boolean): void {
this._shouldCamera$.setValue(enabled);
}

public enableMic(enabled: boolean): void {
this._shouldMic$.setValue(enabled);
}

public setElement(el: HTMLElement | null): void {
this._el$.setValue(el);
}

public getVolumeLevel(): number {
return this._volumeLevel;
}

public constructor(config: RTCAvatarConfig) {
this._rtc = config.rtc;
this._el$ = new Val(config.element);
this._sideEffect.addDisposer(
this._shouldMic$.subscribe(async shouldMic => {
this._volumeLevel = 0;

try {
let localMicTrack = this._rtc.localMicTrack;
if (shouldMic && !localMicTrack) {
localMicTrack = await this._rtc.createLocalMicTrack();
}
if (localMicTrack) {
await localMicTrack.setEnabled(shouldMic);
}

const lowVolumeLevelDisposerID = "local-mic-volume-level";
if (shouldMic) {
let lowVolumeLevelCount = 0;
this._sideEffect.setInterval(
() => {
if (this._rtc.localMicTrack) {
try {
const volumeLevel =
this._rtc.localMicTrack.getVolumeLevel() || 0;
if (Math.abs(this._volumeLevel - volumeLevel) > 0.00001) {
this._volumeLevel = volumeLevel;
this._rtc.events.emit(
"volume-level-changed",
volumeLevel,
);
}
if (
volumeLevel <= RTCTestAvatar.LOW_VOLUME_LEVEL_THRESHOLD
) {
if (++lowVolumeLevelCount >= 10) {
this._rtc.events.emit("err-low-volume");
this._sideEffect.flush(lowVolumeLevelDisposerID);
return;
}
} else {
lowVolumeLevelCount = 0;
}
} catch (e) {
console.error(e);
}
}
},
500,
lowVolumeLevelDisposerID,
);
} else {
this._sideEffect.flush(lowVolumeLevelDisposerID);
}
} catch (e) {
this._rtc.events.emit("err-set-mic", e);
}
}),
);

this._sideEffect.addDisposer(
this._shouldCamera$.subscribe(async shouldCamera => {
try {
let localCameraTrack = this._rtc.localCameraTrack;
if (shouldCamera && !localCameraTrack) {
localCameraTrack = await this._rtc.createLocalCameraTrack();
if (this._el$.value) {
localCameraTrack.play(this._el$.value);
}
}
if (localCameraTrack) {
await localCameraTrack.setEnabled(shouldCamera);
}
} catch (e) {
this._rtc.events.emit("err-set-camera", e);
}
}),
);

this._sideEffect.addDisposer(
this._el$.reaction(async el => {
if (el && this._rtc.localCameraTrack) {
try {
this._rtc.localCameraTrack.play(el);
await this._rtc.localCameraTrack.setEnabled(this._shouldCamera$.value);
} catch (e) {
console.error(e);
}
}
}),
);

this._sideEffect.addDisposer(async () => {
try {
await this._rtc.localCameraTrack?.setEnabled(false);
await this._rtc.localMicTrack?.setEnabled(false);
} catch {
// do nothing
}
});
}

public destroy(): void {
this._sideEffect.flushAll();
}
}

0 comments on commit c2893e7

Please sign in to comment.