Explorar o código

update 直播服务

warrior hai 4 meses
pai
achega
59944f2ddc

+ 1 - 0
projects/live-app/src/moduls/live/link-page/link-page.component.ts

@@ -107,6 +107,7 @@ export class LinkPageComponent implements OnInit {
         this.liveService.updatePublishedAudioTrack();
         break;
       case 'camera':
+        this.liveService.changeCamera();
         break;
       case 'mute':
         this.liveService.muteAudio();

+ 116 - 50
projects/live-app/src/services/live.service.ts

@@ -49,6 +49,9 @@ export class LiveService {
     videoDevice: '',
   };
   room?: Parse.Object; //直播间
+  connection_state?: string; //连接状态
+  surplusNumber: number = 0; //剩余可通话时长(单位:秒s)
+
   constructor(
     private http: HttpService,
     private aiServ: AiChatService,
@@ -109,14 +112,14 @@ export class LiveService {
         this.alertTips('获取媒体权限失败');
       });
   }
-
+  /* 获取token */
   async getToken(room: Parse.Object) {
     this.room = room;
     this.timer && clearTimeout(this.timer);
     let remoteEle = document.getElementById('vice-video');
     (remoteEle as any).style.display = 'none';
     //获取频道token记录
-    if (room?.get('profile').id == this.profile) {
+    if (room?.get('user')?.id === Parse.User.current()?.id) {
       this.UID = 111111;
       let uid = Parse.User.current()?.id;
       if (!uid) {
@@ -128,8 +131,8 @@ export class LiveService {
       let baseurl = 'https://server.fmode.cn/api/webrtc/build_token';
       let reqBody = {
         company: this.company, // this.aiSer.company,
-        profile: this.profile,
-        channelName: this.profile,
+        profile: room?.get('profile').id,
+        channelName: room?.get('profile').id,
       };
       let data: any = await this.http.httpRequst(baseurl, reqBody, 'POST');
       console.log(data);
@@ -152,7 +155,6 @@ export class LiveService {
     }
     this.join();
   }
-  /* 获取token */
   async updateToken(pid: string) {
     let sql = `select  "rtc"."objectId" as "rid","rtc"."channel", "rtc"."token",  "rtc"."expiraTime" from "RtcToken" as "rtc" where "rtc"."profile" = '${pid}' and "rtc"."expiraTime" >= now() order by "createdAt" desc limit 1`;
     let tokenData: any = await this.http.customSQL(sql);
@@ -167,25 +169,40 @@ export class LiveService {
       return null;
     }
   }
-  // 进入频道
+  /* 进入频道 */
   async join() {
     let path = location.pathname;
     if (path.indexOf('/live/link-room/') == -1) return;
     console.log('频道:', this.options.channel);
-    let data = await Promise.all([
-      this.client.join(
+    this.client
+      .join(
         this.options.appid,
         this.options.channel,
         this.options.token,
         this.UID
-      ),
+      )
+      .then(async (uid: any) => {
+        // await this.client.setClientRole('host');
+        console.log('进入频道当前uid:', uid);
+        this.client.connectionState;
+        this.connection_state = this.client.connectionState;
+        await this.publishSelf();
+        await this.joinReady();
+        this.monitorDevices();
+      })
+      .catch((err: any) => {
+        console.log('进入频道失败:', err);
+      });
+  }
+  /* 发布本地视频 */
+  async publishSelf() {
+    let data = await Promise.all([
       /* 创建音频和视频轨道 */
-      AgoraRTC.createMicrophoneAudioTrack(),
-      AgoraRTC.createCameraVideoTrack(),
+      AgoraRTC.createMicrophoneAudioTrack(this.currentUsedDevice.audioDevice),
+      AgoraRTC.createCameraVideoTrack(this.currentUsedDevice.videoDevice),
     ]);
-    // await this.client.setClientRole('host');
-    this.localTracks.audioTrack = data[1];
-    this.localTracks.videoTrack = data[2];
+    this.localTracks.audioTrack = data[0];
+    this.localTracks.videoTrack = data[1];
     // console.log(this.localTracks);
     let remoteEle = document.getElementById('vice-video');
     if (remoteEle) {
@@ -198,15 +215,10 @@ export class LiveService {
     } else {
       this.localTracks.audioTrack.setEnabled(true);
     }
-    await this.joinReady();
-  }
-  /* 发布本地视频 */
-  async publishSelf() {
     await this.client.publish(Object.values(this.localTracks));
   }
   /* 订阅远程视频 */
   async joinReady() {
-    await this.publishSelf();
     this.client.remoteUsers.forEach((user: any) => {
       console.log('remoteUsers', user.uid);
       this.client.subscribe(user, 'audio').then((audioTrack: any) => {
@@ -222,37 +234,10 @@ export class LiveService {
         videoTrack.play('video');
       });
     });
-    // this.timer && clearInterval(this.timer);
-    // console.log(this.client.remoteUsers);
-    // const isAnchor = this.room?.get('user')?.id === Parse.User.current()?.id
-    // if(isAnchor){
-    //   console.log('当前用户身份:房主');
-    //   // this.localTracks.audioTrack.setEnabled(false);
-    //   // this.localTracks.videoTrack.setEnabled(false);
-    //   await this.publishSelf()
-    // }else{
-    //   console.log('当前用户身份:用户');
-    //   console.log('主播在线状态',this.client.remoteUsers.length);
-    //   if (location.pathname.indexOf('/live/link-room/') == -1) return;
-    //   /* 如果主播还没有上线,等待主播上线后发布 */
-    //   if(this.client.remoteUsers.length == 0){
-    //     setTimeout(() => {
-    //       this.joinReady()
-    //     }, 1000);
-    //     return
-    //   }
-    // }
     this.client.on('user-joined', (user: any) => {
       console.log(user, `${user.uid} 加入频道`);
     });
     this.client.on('user-published', async (user: any, mediaType: string) => {
-      /* 当用户进入直播间,主播重新推流视频:解决订阅者remoteUsers无法渲染问题 */
-      // if(isAnchor){
-      //   // await this.client.unpublish(Object.values(this.localTracks));
-      //   // await this.client.publish(Object.values(this.localTracks));
-      //   // this.localTracks.videoTrack.setEnabled(true);
-      //   // this.localTracks.audioTrack.setEnabled(true);
-      // }
       console.log('用户推流成功', user);
       await this.client.subscribe(user, mediaType);
       let remoteEle = document.getElementById('video');
@@ -282,11 +267,70 @@ export class LiveService {
         this.alertTips('对方已离开直播间');
       }
     });
-    // if(!isAnchor){
-    //   this.publishSelf()
-    // }
+    this.client.on(
+      'connection-state-change',
+      (curState: any, prevState: any) => {
+        this.connection_state = curState;
+        console.log(this.connection_state);
+        console.log(prevState);
+      }
+    );
+  }
+
+  /* 开始计时 */
+  computeDuration() {
+    //每10秒保存一次数据
+    this.timer && clearInterval(this.timer);
+    this.timer = setInterval(() => {
+      let url = 'http://test.fmode.cn/api/ailiao/count/duration';
+      let params = {
+        company: this.company,
+        profile:this.profile?.id,
+        rid: this.room?.id,
+        uid: Parse.User.current()?.id,
+      };
+      this.http.httpRequst(url, params,'POST');
+    }, 10000);
+  }
+
+  /* 监听音视频设备插拔 */
+  monitorDevices() {
+    AgoraRTC.onMicrophoneChanged = async (changedDevice: any) => {
+      // 插入麦克风设备时,切换到新插入的设备
+      if (changedDevice.state === 'ACTIVE') {
+        this.localTracks.audioTrack.setDevice(changedDevice.device.deviceId);
+        this.currentUsedDevice.audioDevice = changedDevice.device.deviceId;
+
+        // 拔出设备为当前设备时,切换到一个已有的设备
+      } else if (
+        changedDevice.device.label ===
+        this.localTracks.audioTrack.getTrackLabel()
+      ) {
+        const oldMicrophones = await AgoraRTC.getMicrophones();
+        oldMicrophones[0] &&
+          this.localTracks.audioTrack.setDevice(oldMicrophones[0].deviceId);
+        this.currentUsedDevice.audioDevice = oldMicrophones[0].deviceId;
+      }
+    };
+
+    AgoraRTC.onCameraChanged = async (changedDevice: any) => {
+      // 插入相机设备时,切换到新插入的设备
+      if (changedDevice.state === 'ACTIVE') {
+        this.localTracks.videoTrack.setDevice(changedDevice.device.deviceId);
+        this.currentUsedDevice.videoDevice = changedDevice.device.deviceId;
+        // 拔出设备为当前设备时,切换到一个已有的设备
+      } else if (
+        changedDevice.device.label ===
+        this.localTracks.videoTrack.getTrackLabel()
+      ) {
+        const oldCameras = await AgoraRTC.getCameras();
+        oldCameras[0] &&
+          this.localTracks.videoTrack.setDevice(oldCameras[0].deviceId);
+        this.currentUsedDevice.videoDevice = oldCameras[0].deviceId;
+      }
+    };
   }
-  /* 停止音频推流 */
+  /* 关开麦 */
   async updatePublishedAudioTrack() {
     this.tools['audio'] = !this.tools['audio'];
     if (this.tools['audio'] && this.localTracks.audioTrack) {
@@ -315,6 +359,28 @@ export class LiveService {
     }
   }
 
+  /* 切换摄像头 */
+  async changeCamera() {
+    const oldCameras = await AgoraRTC.getCameras(true);
+    let newCamers = oldCameras.find(
+      (item: any) => item.deviceId !== this.currentUsedDevice.videoDevice
+    );
+    console.log(newCamers);
+    newCamers &&
+      this.localTracks.videoTrack
+        .setDevice(newCamers.deviceId)
+        .then(() => {
+          this.tools['camera'] = !this.tools['camera'];
+          this.currentUsedDevice.videoDevice = newCamers.deviceId;
+        })
+        .catch((err: any) => {
+          console.log('set device error', err);
+          this.alertTips('切换摄像头失败');
+        });
+    return true;
+  }
+
+  /* 提示 */
   async alertTips(message: string, title?: string, callBack?: Function) {
     this.alert = await this.alertController.create({
       header: title || '提示',