eq
This commit is contained in:
+214
-75
@@ -1,106 +1,245 @@
|
||||
import {Injectable, Inject, PLATFORM_ID} from '@angular/core';
|
||||
import {isPlatformBrowser} from '@angular/common';
|
||||
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
|
||||
import { isPlatformBrowser } from '@angular/common';
|
||||
|
||||
const TRTC: any = await import('trtc-sdk-v5');
|
||||
const VOICE_CLIENT_URL = 'https://wfzwn9fhbmfd.stupideyes.com/dist/voice-client.iife.js';
|
||||
const VOICE_SERVER = 'https://wfzwn9fhbmfd.stupideyes.com';
|
||||
const VOICE_APP_ID = 'va_20260622_vjx5D1WN';
|
||||
const VOICE_APP_SECRET = 'sk_ldqdikFBlutc-7xZGQ0aSjZlDuM-NSr9sQ_IiqE_A3-XAnh0';
|
||||
|
||||
type NotifyCallback = (res?: any) => void;
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class TrtcService {
|
||||
private trtc: any = null;
|
||||
private client: any = null;
|
||||
private sdkLoadPromise: Promise<any> | null = null;
|
||||
private sessionId = 0;
|
||||
private connectedNotified = false;
|
||||
private call: {
|
||||
join: Function,
|
||||
out: Function
|
||||
join: NotifyCallback;
|
||||
out: NotifyCallback;
|
||||
} | null = null;
|
||||
|
||||
constructor(@Inject(PLATFORM_ID) private platformId: any) {
|
||||
}
|
||||
|
||||
initTRTC(): any {
|
||||
if (this.trtc == null) {
|
||||
// 只在浏览器环境中加载 TRTC SDK
|
||||
const trtc = TRTC.default || TRTC;
|
||||
this.trtc = trtc.create()
|
||||
const that = this;
|
||||
this.trtc.on("remote-user-enter", (res: any) => {
|
||||
if (that.call && that.call.join) {
|
||||
that.call.join(res)
|
||||
}
|
||||
})
|
||||
this.trtc.on("remote-user-exit", (res: any) => {
|
||||
if (that.call && that.call.out) {
|
||||
that.call.out(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
return this.trtc;
|
||||
}
|
||||
constructor(@Inject(PLATFORM_ID) private platformId: object) {}
|
||||
|
||||
createClient() {
|
||||
if (!isPlatformBrowser(this.platformId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadVoiceSDK().catch((err) => console.error('failed to load voice sdk', err));
|
||||
}
|
||||
|
||||
onJoinNotify(callback: NotifyCallback) {
|
||||
this.getCallbacks().join = callback;
|
||||
}
|
||||
|
||||
onOutNotify(callback: NotifyCallback) {
|
||||
this.getCallbacks().out = callback;
|
||||
}
|
||||
|
||||
async enterRoom(_sdkAppId: number | string, userId: string, _userSig: string, roomId: number | string) {
|
||||
if (!isPlatformBrowser(this.platformId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.initTRTC();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
if (this.client) {
|
||||
await this.exitRoom(true);
|
||||
}
|
||||
|
||||
onJoinNotify(callback: any) {
|
||||
if (!this.call) {
|
||||
this.call = {
|
||||
join: (res: any) => {
|
||||
}, out: (res: any) => {
|
||||
}
|
||||
};
|
||||
}
|
||||
this.call.join = callback;
|
||||
}
|
||||
const sdk = await this.loadVoiceSDK();
|
||||
const timestamp = Date.now();
|
||||
const room = String(roomId);
|
||||
const user = String(userId);
|
||||
const sign = await sdk.VoiceClient.generateSign(
|
||||
VOICE_APP_ID,
|
||||
user,
|
||||
room,
|
||||
timestamp,
|
||||
VOICE_APP_SECRET,
|
||||
);
|
||||
const currentSession = ++this.sessionId;
|
||||
|
||||
onOutNotify(callback: any) {
|
||||
if (!this.call) {
|
||||
this.call = {
|
||||
join: (res: any) => {
|
||||
}, out: (res: any) => {
|
||||
}
|
||||
};
|
||||
}
|
||||
this.call.out = callback;
|
||||
}
|
||||
this.connectedNotified = false;
|
||||
this.client = await sdk.VoiceClient.join({
|
||||
appId: VOICE_APP_ID,
|
||||
userId: user,
|
||||
roomId: room,
|
||||
sign,
|
||||
timestamp,
|
||||
server: VOICE_SERVER,
|
||||
audioElement: this.getRemoteAudioElement(),
|
||||
onStateChange: (state: string) => {
|
||||
if (!this.isCurrentSession(currentSession)) {
|
||||
return;
|
||||
}
|
||||
|
||||
async enterRoom(sdkAppId: number, userId: string, userSig: string, roomId: number) {
|
||||
try {
|
||||
await this.initTRTC()?.enterRoom({
|
||||
sdkAppId: sdkAppId, userId: userId, userSig: userSig, roomId: roomId
|
||||
})
|
||||
this.startLocalAudio();
|
||||
if (state === 'connected') {
|
||||
this.notifyJoined({ state });
|
||||
}
|
||||
if (state === 'ended') {
|
||||
this.client = null;
|
||||
this.connectedNotified = false;
|
||||
this.getCallbacks().out({ state });
|
||||
}
|
||||
},
|
||||
onPeerJoined: (peerUserId: string, username: string) => {
|
||||
if (this.isCurrentSession(currentSession)) {
|
||||
this.notifyJoined({ userId: peerUserId, username });
|
||||
}
|
||||
},
|
||||
onPeerLeft: (peerUserId: string, username: string) => {
|
||||
if (this.isCurrentSession(currentSession)) {
|
||||
this.getCallbacks().out({ userId: peerUserId, username });
|
||||
}
|
||||
},
|
||||
onError: (message: string) => {
|
||||
if (!this.isCurrentSession(currentSession)) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.error('voice sdk error', message);
|
||||
this.client = null;
|
||||
this.connectedNotified = false;
|
||||
this.getCallbacks().out({ message });
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('failed to enter room ' + error);
|
||||
console.error('failed to enter room', error);
|
||||
this.client = null;
|
||||
this.connectedNotified = false;
|
||||
this.getCallbacks().out({ error });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
startLocalAudio() {
|
||||
this.initTRTC()?.startLocalAudio()
|
||||
this.client?.unmute();
|
||||
}
|
||||
|
||||
|
||||
stopLocalAudio() {
|
||||
this.initTRTC()?.stopLocalAudio();
|
||||
this.client?.mute();
|
||||
}
|
||||
|
||||
|
||||
startMuteRemoteAudio(fid: string) {
|
||||
this.initTRTC()?.muteRemoteAudio(fid, false);
|
||||
startMuteRemoteAudio(_fid: string) {
|
||||
this.client?.unmuteSpeaker();
|
||||
}
|
||||
|
||||
|
||||
stopMuteRemoteAudio(fid: string) {
|
||||
this.initTRTC()?.muteRemoteAudio(fid, true);
|
||||
stopMuteRemoteAudio(_fid: string) {
|
||||
this.client?.muteSpeaker();
|
||||
}
|
||||
|
||||
async exitRoom() {
|
||||
await this.initTRTC()?.exitRoom();
|
||||
async exitRoom(silent = false) {
|
||||
if (!this.client) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initTRTC()?.destroy();
|
||||
this.trtc = null;
|
||||
this.sessionId++;
|
||||
const client = this.client;
|
||||
this.client = null;
|
||||
this.connectedNotified = false;
|
||||
|
||||
try {
|
||||
client.hangup();
|
||||
} catch (error) {
|
||||
if (!silent) {
|
||||
console.error('failed to exit room', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private isCurrentSession(sessionId: number) {
|
||||
return sessionId === this.sessionId;
|
||||
}
|
||||
|
||||
private notifyJoined(res?: any) {
|
||||
if (this.connectedNotified) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.connectedNotified = true;
|
||||
this.getCallbacks().join(res);
|
||||
}
|
||||
|
||||
private getCallbacks() {
|
||||
if (!this.call) {
|
||||
this.call = {
|
||||
join: () => {},
|
||||
out: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
return this.call;
|
||||
}
|
||||
|
||||
private async loadVoiceSDK(): Promise<any> {
|
||||
const win = window as any;
|
||||
if (win.VoiceCallSDK?.VoiceClient) {
|
||||
return win.VoiceCallSDK;
|
||||
}
|
||||
|
||||
if (this.sdkLoadPromise) {
|
||||
return this.sdkLoadPromise;
|
||||
}
|
||||
|
||||
this.sdkLoadPromise = new Promise((resolve, reject) => {
|
||||
const existing = document.querySelector<HTMLScriptElement>(`script[src="${VOICE_CLIENT_URL}"]`);
|
||||
const script = existing || document.createElement('script');
|
||||
let timeoutId: ReturnType<typeof setTimeout>;
|
||||
|
||||
const cleanup = () => {
|
||||
clearTimeout(timeoutId);
|
||||
script.removeEventListener('load', onLoad);
|
||||
script.removeEventListener('error', onError);
|
||||
};
|
||||
const onLoad = () => {
|
||||
cleanup();
|
||||
if (win.VoiceCallSDK?.VoiceClient) {
|
||||
resolve(win.VoiceCallSDK);
|
||||
} else {
|
||||
this.sdkLoadPromise = null;
|
||||
reject(new Error('VoiceCallSDK.VoiceClient not found'));
|
||||
}
|
||||
};
|
||||
const onError = () => {
|
||||
cleanup();
|
||||
this.sdkLoadPromise = null;
|
||||
reject(new Error('voice sdk script load failed'));
|
||||
};
|
||||
|
||||
script.addEventListener('load', onLoad);
|
||||
script.addEventListener('error', onError);
|
||||
timeoutId = setTimeout(() => {
|
||||
if (win.VoiceCallSDK?.VoiceClient) {
|
||||
onLoad();
|
||||
return;
|
||||
}
|
||||
|
||||
onError();
|
||||
}, 10000);
|
||||
|
||||
if (!existing) {
|
||||
script.src = VOICE_CLIENT_URL;
|
||||
script.async = true;
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
});
|
||||
|
||||
return this.sdkLoadPromise;
|
||||
}
|
||||
|
||||
private getRemoteAudioElement(): HTMLAudioElement {
|
||||
let audio = document.getElementById('remoteAudio') as HTMLAudioElement | null;
|
||||
if (!audio) {
|
||||
audio = document.createElement('audio');
|
||||
audio.id = 'remoteAudio';
|
||||
audio.style.display = 'none';
|
||||
document.body.appendChild(audio);
|
||||
}
|
||||
|
||||
audio.autoplay = true;
|
||||
audio.setAttribute('playsinline', 'true');
|
||||
return audio;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=375, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<script src="https://wfzwn9fhbmfd.stupideyes.com/dist/voice-client.iife.js"></script>
|
||||
<script type="text/javascript">
|
||||
// 动态计算缩放比例
|
||||
function adjustScale() {
|
||||
@@ -43,3 +44,4 @@
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user