Procházet zdrojové kódy

优化部分功能

wolyshaw před 3 roky
rodič
revize
121893a431

+ 28 - 37
src/components/live-broadcast/action-bar.tsx

@@ -1,52 +1,43 @@
-import { defineComponent } from 'vue'
+import { defineComponent, reactive } from 'vue'
 import { ElButton, ElDropdown, ElDropdownMenu, ElDropdownItem, ElSlider, ElDialog, ElIcon } from 'element-plus'
 import runtime, * as RuntimeUtils from './runtime'
 import styles from './action-bar.module.less'
 import Share from './share'
+
+export const state = reactive({
+  volume: 30,
+  barStatus: {
+    camera: false, // 摄像头
+    volume: false, // 声音调节
+    microphone: false, // 麦克风
+    screen: false, // 共享屏幕
+    share: false, // 分享
+  },
+  shareVisiable: false
+})
+
 export default defineComponent({
   name: 'LiveBroadcast-ActionBar',
-  data() {
-    return {
-      volume: 30,
-      barStatus: {
-        camera: false, // 摄像头
-        volume: false, // 声音调节
-        microphone: false, // 麦克风
-        screen: false, // 共享屏幕
-        share: false, // 分享
-      },
-      shareVisiable: false
-    }
-  },
   computed: {
     isCameraDisabled() {
-      // @ts-ignore
-      return this.barStatus.camera && runtime.deviceStatus.camera !== 'denied' && runtime.cameras.length
+      return state.barStatus.camera && runtime.deviceStatus.camera !== 'denied' && runtime.cameras.length
     },
     isMicrophoneDisabled() {
-      // @ts-ignore
-      const isDisabled = this.barStatus.microphone && runtime.deviceStatus.microphone !== 'denied' && runtime.microphones.length
+      const isDisabled = state.barStatus.microphone && runtime.deviceStatus.microphone !== 'denied' && runtime.microphones.length
       return isDisabled
     },
     isVolumeDisabled() {
-      // @ts-ignore
-      return this.barStatus.volume && this.volume === 0
+      return state.volume === 0
     }
   },
   methods: {
     startShare() {
       console.log('调用')
-      this.shareVisiable = true
+      state.shareVisiable = true
     },
     volumeChange(value: number) {
-      this.volume = value
-      console.log(runtime.activeTracks)
+      state.volume = value
       RuntimeUtils.setVolume(value)
-      // @ts-ignore
-      if (runtime.activeTracks.microphone && runtime.activeTracks.microphone._element) {
-        // @ts-ignore
-        runtime.activeTracks.microphone._element.volume = value / 100
-      }
     }
   },
   render() {
@@ -57,7 +48,7 @@ export default defineComponent({
             <div class={styles.btnInner}>
               <SvgIcon
                 onClick={() => {
-                  this.barStatus.camera = !this.barStatus.camera
+                  state.barStatus.camera = !state.barStatus.camera
                   RuntimeUtils.toggleDevice('camera')
                 }}
                 name={this.isCameraDisabled ? 'bar-camera-disabled' : 'bar-camera'}
@@ -96,11 +87,11 @@ export default defineComponent({
             <div class={styles.btnInner}>
               <SvgIcon
                 onClick={() => {
-                  this.barStatus.volume = !this.barStatus.volume;
-                  if(!this.barStatus.volume) {
+                  state.barStatus.volume = !state.barStatus.volume;
+                  if(!state.barStatus.volume) {
                     sessionStorage.getItem('volume') && this.volumeChange(Number(sessionStorage.getItem('volume')))
                   } else {
-                    sessionStorage.setItem('volume', this.volume.toString())
+                    sessionStorage.setItem('volume', state.volume.toString())
                     this.volumeChange(0)
                   }
                 }}
@@ -118,7 +109,7 @@ export default defineComponent({
                   dropdown: () => (
                     <div class={styles.volumeSlider}>
                       <SvgIcon class={styles.volumeIcon} name="message-voice" color="#fff" />
-                      <ElSlider modelValue={this.volume} onInput={this.volumeChange} size="small" />
+                      <ElSlider modelValue={state.volume} onInput={this.volumeChange} size="small" />
                     </div>
                   )
                 }}
@@ -166,8 +157,8 @@ export default defineComponent({
               <SvgIcon
                 onClick={() => {
                   const needPublish = runtime.videoStatus === 'liveing'
-                  this.barStatus.microphone = !this.barStatus.microphone
-                  if (!this.barStatus.microphone) {
+                  state.barStatus.microphone = !state.barStatus.microphone
+                  if (!state.barStatus.microphone) {
                     RuntimeUtils.openDevice('microphone', needPublish)
                   } else {
                     RuntimeUtils.closeDevice('microphone', needPublish)
@@ -225,8 +216,8 @@ export default defineComponent({
         {/* <ElButton onClick={RuntimeUtils.shareScreenVideo}>屏幕共享</ElButton> */}
         <ElDialog width="510px"
         destroy-on-close
-          append-to-body modelValue={this.shareVisiable} title="分享" before-close={() => { this.shareVisiable = false }}>
-            <Share onClose={()=>this.shareVisiable = false}/>
+          append-to-body modelValue={state.shareVisiable} title="分享" before-close={() => { state.shareVisiable = false }}>
+            <Share onClose={()=>state.shareVisiable = false}/>
         </ElDialog>
       </div>
     )

+ 25 - 3
src/components/live-broadcast/index.tsx

@@ -1,7 +1,7 @@
 import { defineComponent, ref } from 'vue'
 import * as RTC from '@rongcloud/plugin-rtc'
 import Header from './header'
-import ActionBar from './action-bar'
+import ActionBar, { state as ActionBarRuntime} from './action-bar'
 import VideoStatus from './video-status'
 import { state } from '/src/state'
 import event, { LIVE_EVENT_MESSAGE } from './event'
@@ -29,15 +29,32 @@ export default defineComponent({
     onLikeMessage(msg: any) {
       runtime.likeCount += msg.counts
     },
+    getDeviceByDeviceType(type: RuntimeUtils.TrackType) {
+      const videoDeviceId = localStorage.getItem(RuntimeUtils.VIDEO_DEVICE_ID)
+      const audioDeviceId = localStorage.getItem(RuntimeUtils.AUDIO_DEVICE_ID)
+      if (type === 'camera') {
+        if (videoDeviceId) {
+          return runtime.cameras.find(camera => camera.deviceId === videoDeviceId) || runtime.cameras[0]
+        }
+        return runtime.cameras[0]
+      }
+      if (audioDeviceId) {
+        return runtime.microphones.find(microphone => microphone.deviceId === audioDeviceId) || runtime.microphones[0]
+      }
+      return runtime.microphones[0]
+    },
     async initializeRoom () {
       if (!state.user) throw Error('请先登录')
       try {
+        // IM连接
         await RuntimeUtils.connectIM(state.user?.imToken)
         runtime.videoRef = videoRef.value
+        // 获取设备
         await RuntimeUtils.getMicrophones()
         await RuntimeUtils.getCameras()
-        RuntimeUtils.setSelectCamera(runtime.cameras[0])
-        RuntimeUtils.setSelectMicrophone(runtime.microphones[0])
+        // 设置播放设备
+        RuntimeUtils.setSelectCamera(this.getDeviceByDeviceType('camera'))
+        RuntimeUtils.setSelectMicrophone(this.getDeviceByDeviceType('microphone'))
         cameraVideoTrack = await RuntimeUtils.getTrack('camera')
         runtime.videoRef && cameraVideoTrack.play(runtime.videoRef)
         await RuntimeUtils.setTrack([cameraVideoTrack], 'camera', false)
@@ -91,6 +108,11 @@ export default defineComponent({
           await RuntimeUtils.startLive(false)
           runtime.videoStatus = 'liveing'
         }
+        const volume =localStorage.getItem(RuntimeUtils.AUDIO_DEVICE_VOLUME)
+        if (volume) {
+          ActionBarRuntime.volume = parseInt(volume)
+          RuntimeUtils.setVolume(parseInt(volume))
+        }
       } catch (error) {
         runtime.videoStatus = 'error'
         console.log(error)

+ 15 - 1
src/components/live-broadcast/runtime.ts

@@ -11,7 +11,7 @@ type imConnectStatus = 'connecting' | 'connected' | 'disconnect'
 
 type VideoStatus = 'init' | 'stream' | 'liveing' | 'stopped' | 'error' | 'loading'
 
-type TrackType = 'microphone' | 'camera' | 'screen'
+export type TrackType = 'microphone' | 'camera' | 'screen'
 
 type ActiveTracks = {
   [key in TrackType]: RTC.RCLocalTrack | null
@@ -25,6 +25,12 @@ export const START_LIVE_TIME = 'start-live-time'
 
 export const START_LIVE_STATUS = 'start-live-status'
 
+export const VIDEO_DEVICE_ID = 'video-deviceId'
+
+export const AUDIO_DEVICE_ID = 'audio-deviceId'
+
+export const AUDIO_DEVICE_VOLUME = 'audio-device-volume'
+
 const runtime = reactive({
   /** 房间id */
   roomUid: 'LIVE-2112263-12345',
@@ -162,9 +168,15 @@ const Events = RongIMLib.Events
  * @param Value 声音大小
  */
 export const setVolume = (value: number) => {
+  localStorage.setItem(AUDIO_DEVICE_VOLUME, value.toString())
   if(runtime.videoRef) {
     runtime.videoRef.volume = value / 100
   }
+  // @ts-ignore
+  if (runtime.activeTracks.microphone && runtime.activeTracks.microphone._element) {
+    // @ts-ignore
+    runtime.activeTracks.microphone._element.volume = value / 100
+  }
 }
 
 /**
@@ -239,6 +251,7 @@ export const getCameras = async () => {
  */
 export const setSelectCamera = async (camera: MediaDeviceInfo) => {
   runtime.selectedCamera = camera
+  localStorage.setItem(VIDEO_DEVICE_ID, camera.deviceId)
   const oldTrack = runtime.activeTracks.camera as RTC.RCLocalTrack
   if (oldTrack) {
     await removeTrack([oldTrack], 'camera', oldTrack.isPublished())
@@ -254,6 +267,7 @@ export const setSelectCamera = async (camera: MediaDeviceInfo) => {
  */
 export const setSelectMicrophone = async (microphone: MediaDeviceInfo) => {
   runtime.selectedMicrophone = microphone
+  localStorage.setItem(AUDIO_DEVICE_ID, microphone.deviceId)
   const oldTrack = runtime.activeTracks.microphone as RTC.RCLocalTrack
   if (oldTrack) {
     await removeTrack([oldTrack], 'microphone', oldTrack.isPublished())