今日看

import React, { FC, useState, useEffect } from 'react'
import $dp from 'dataProvider'
import auth from 'utils/auth'
import i18n from 'i18n'
import audioicon from 'theme/images/audio.png'
import audiocloseicon from 'theme/images/audio_close.png'
import cameraicon from 'theme/images/camera.png'
import cameracloseicon from 'theme/images/camera_close.png'
import { Modal, message } from 'components/ui-components'
import { getUCNickName } from 'utils/ucUser'
import {
  showAlert, initialization, getSubscribeInfo, setConfigRemote, receivePublishManual
} from './utils'

import styles from './style.module.scss'

interface IWebRTCBodyProps {
  channelId: string
  ownerId: string
  onOwnerLeave: ()=>void
}

const WebRTC: FC<IWebRTCBodyProps> = (props) => {
  const {
    channelId, ownerId, onOwnerLeave
  } = props

  const [openAudia, setOpenAudia] = useState(true)
  const [openCamera, setOpenCamera] = useState(true)

  let publisherList: any[]
  let aliToken: any
  let isCameraEnable: boolean = true
  let currentUser: any = auth.getAuth()
  let nickName = getUCNickName(currentUser)
  let t = i18n.getFixedT(null, 'message')
  const aliWebrtc = window.aliWebrtc

  function removeDom(userid: any) {
  }

  function compareIsOwner(compareOwnerId: string) {
    let newOwnerId
    if (compareOwnerId.length > 1) {
      newOwnerId = compareOwnerId.substr(0, compareOwnerId.length - 1)
    }
    return ownerId === newOwnerId
  }

  function detelePublisher(userId: any) {
    let index = (publisherList as any).getIndexByProprety(userId, 'userId')
    if (index !== -1) {
      publisherList.splice(index, 1)
      detelePublisher(userId)
    } else {
      console.log('未找到之前的推流数据')// 删除推流用户
    }
  }

  function updateUserList() {
    let videoList = document.getElementById('remote-user-list-video')
    let userList = aliWebrtc.getUserList()

    if (videoList && videoList.hasChildNodes()) {
      let childList = videoList.childNodes
      for (let i = childList.length - 1; i >= 1; i--) {
        let childDiv = childList[i]
        let currentId = (childDiv as HTMLElement).id.substr(9)
        let isFind = false
        for (let j = 0; j < userList.length; j++) {
          let currentUser = userList[j]
          if (currentId === currentUser.userId) {
            isFind = true
            break
          }
        }
        if (!isFind) {
          videoList.removeChild(childList[i])
        }
      }
    }
    // let frg = document.createDocumentFragment()
    userList.forEach((user: any) => {
      let isFind = false
      let videoList = document.getElementById('remote-user-list-video')

      if (videoList && videoList.hasChildNodes()) {
        let childList = videoList.childNodes
        for (let i = childList.length - 1; i >= 1; i--) {
          let childDiv = childList[i]
          let currentId = (childDiv as HTMLElement).id.substr(9)
          if (currentId === user.userId) {
            isFind = true
            break
          }
        }
      }
      if (!isFind && videoList) {
        if (user.userId !== aliToken.userid) {
          if (!compareIsOwner(user.userId)) {
            let videoDiv = document.createElement('div')
            videoDiv.className = styles['video-box']
            videoDiv.id = `video-box${user.userId}`
            let videoText = document.createElement('div')
            videoText = document.createElement('div')
            videoText.className = styles['video-box-text']
            videoDiv.appendChild(videoText)
            let videoName = document.createElement('p')
            videoName.align = 'center'
            videoName.className = styles['video-text-p']
            videoName.innerHTML = `${user.displayName}`
            videoName.id = `videoName${user.userId}`
            videoText.appendChild(videoName)
            let videoParent = document.createElement('div')
            videoParent.className = styles['video-box-parent']
            videoDiv.appendChild(videoParent)
            let videoEle = document.createElement('video')
            videoEle.autoplay = true
            // videoEle.playsinline = true
            videoEle.controls = false
            videoEle.width = 146
            videoEle.height = 110
            videoEle.style.marginTop = '5'
            videoEle.id = `video${user.userId}`
            videoParent.appendChild(videoEle)

            let leftNameDiv = document.createElement('div')
            leftNameDiv.className = styles['video-box-text-2']
            videoDiv.appendChild(leftNameDiv)
            leftNameDiv.id = `videoBoxText2${user.userId}`
            let leftNamePara = document.createElement('p')
            leftNamePara.className = styles['video-text-p-2']
            leftNamePara.id = `videoName2${user.userId}`
            leftNameDiv.appendChild(leftNamePara)
            leftNameDiv.style.display = 'none'
            videoList.appendChild(videoDiv)
          }
        }
      }
    })
  }

  function unSubn(streamConfigWithPublisherInfo: any) {
    if (streamConfigWithPublisherInfo.subscribed) {
      console.log('已经订阅')
      return
    }
    console.log(`----onPublisher${streamConfigWithPublisherInfo.userId} ${streamConfigWithPublisherInfo.displayName}`)
    receivePublishManual(streamConfigWithPublisherInfo)
      .then((re: any) => {
        if (compareIsOwner(streamConfigWithPublisherInfo.userId)) {
          let videoEleID = 'local-video-window'
          let video = document.getElementById(videoEleID)
          // let videoNameEleID = 'videoName' + publisher.userId
          // let p = document.getElementById(videoNameEleID)
          // p.innerHTML = publisher.displayName
          if (streamConfigWithPublisherInfo.label !== 'sophon_video_screen_share') {
            aliWebrtc.setDisplayRemoteVideo(streamConfigWithPublisherInfo.userId, video, 1)
          } else {
            aliWebrtc.setDisplayRemoteVideo(streamConfigWithPublisherInfo.userId, video, 2)
          }

          // aliWebrtc.setDisplayRemoteVideo(streamConfigWithPublisherInfo.userId, video, 1)
        } else {
          let videoEleID = `video${streamConfigWithPublisherInfo.userId}`
          let video = document.getElementById(videoEleID)
          let videoNameEleID = `videoName${streamConfigWithPublisherInfo.userId}`
          let p = document.getElementById(videoNameEleID)

          let videoNameEleID2 = `videoName2${streamConfigWithPublisherInfo.userId}`
          let p2 = document.getElementById(videoNameEleID2)

          if (p) {
            p.innerHTML = streamConfigWithPublisherInfo.displayName
          }
          if (p2) {
            p2.innerHTML = streamConfigWithPublisherInfo.displayName
          }

          let videoBoxText2 = `videoBoxText2${streamConfigWithPublisherInfo.userId}`
          let videoBoxText2Ele = document.getElementById(videoBoxText2)
          let newpublisher = aliWebrtc.getUserInfo(re)

          if (videoBoxText2Ele) {
            for (let stream of newpublisher.streamConfigs) {
              if (stream.label === 'sophon_video_camera_large') {
                if (stream.state === 'active') {
                  videoBoxText2Ele.style.display = 'block'
                } else {
                  videoBoxText2Ele.style.display = 'none'
                }
                break
              }
            }
          }
          if (streamConfigWithPublisherInfo.label !== 'sophon_video_screen_share') {
            aliWebrtc.setDisplayRemoteVideo(streamConfigWithPublisherInfo.userId, video, 1)
          } else {
            aliWebrtc.setDisplayRemoteVideo(streamConfigWithPublisherInfo.userId, video, 2)
          }
          // aliWebrtc.setDisplayRemoteVideo(streamConfigWithPublisherInfo.userId, video, 1)
        }
      }).catch((err: any) => {
        console.log(`订阅断开 重新订阅失败${err}`)
        detelePublisher(streamConfigWithPublisherInfo.userId)
        removeDom(streamConfigWithPublisherInfo.userId)
      })
  }

  function autoSub(publisher: any, label: string) {
    var i = publisher.streamConfigs.findIndex(((e:any) => e.label === label && e.state === 'active' && e.subscribed === false
    ))

    if (i > -1) {
      var o = publisher.streamConfigs[i]
      o.userId = publisher.userId
      o.displayName = publisher.displayName
      unSubn(o)
    }
  }

  function updatePublisherStream(publisher: any, index: number) {
    let oldStreamConfigs = JSON.parse(JSON.stringify(publisherList[index].streamConfigs))
    let newStreamConfigs = publisher.streamConfigs
    let subscribeInfo = getSubscribeInfo(publisher.userId)
    oldStreamConfigs.forEach((v: any, i: any, a: any) => {
      let newStream = newStreamConfigs.getObjByProprety(v.label, 'label')
      // 判断流状态改变了 但不确定我们是否订阅了该流
      if (v.state !== newStream.state) {
        console.log(`流的状态变了${v.label}`, v, v.type, `>${v.state}>>${newStream.state}>`, newStream, subscribeInfo)
        // 并且要取消订阅某个流,不然就不能再次订阅了
        subscribeInfo.subscribeInfoArr.forEach((sv) => {
          if (v.label === sv.label) {
            console.log('setConfigRemote取消订阅调用[api]:subscribe', publisher.userId, sv.type, sv.label)
            setConfigRemote(publisher.userId, sv.type, sv.label).then((re: any) => {
              // 移除dom
              removeDom(publisher.userId)
            }).catch((error: any) => {
              console.error('流的状态变了重新订阅出问题', error)
            })
          }
        })
      }
    })
    publisherList.splice(index, 1, publisher)

    setTimeout(() => {
      autoSub(publisher, 'sophon_video_screen_share')
      autoSub(publisher, 'sophon_video_camera_large')
    }, 2000)
  }

  function init() {
    /**
      * remote用户加入房间 onJoin
      * 更新在线用户列表
      */
    aliWebrtc.on('onJoin', (publisher: any) => {
      aliWebrtc.configRemoteAudio(publisher.userId, false)
      aliWebrtc.configRemoteCameraTrack(publisher.userId, false, false)

      if (publisher.userId && !compareIsOwner(publisher.userId)) {
        console.log(`join: ${publisher.userId}`)
        updateUserList()
      }
      // 重置订阅状态
      // 默认订阅远端音频和视频大流,但需要调用subscribe才能生效
      // 这里取消默认订阅,根据需求进行订阅
      // aliWebrtc.configRemoteAudio(publisher.userId, true)
      // aliWebrtc.configRemoteCameraTrack(publisher.userId, true, true)
      // showAlert(publisher.displayName + '加入房间','success')
      // console.log(`${publisher.displayName}加入房间`)
    })

    aliWebrtc.on('onNotify', (data: any) => {
      console.log('用户状态回调')
      console.log(data)
    })

    /**
     * remote流发布事件 onPublish
     * 将该用户新增到推流列表
     * 若该用户已存在推流列表,则进行状态更新
     */
    aliWebrtc.on('onPublisher', (publisher: any) => {
      console.log('onPublisher', publisher)
      let index = (publisherList as any).getIndexByProprety(publisher.userId, 'userId')
      if (index === -1) {
        // 新增
        publisherList.push(publisher)
        if (publisher.userId !== aliToken.userid) {
          const o = publisher.streamConfigs.findIndex(((e: any) => e.type === 'audio' && e.state === 'active'
          ))
          const n = publisher.streamConfigs.findIndex(((e: any) => e.label === 'sophon_video_screen_share' && e.state === 'active'
          ))
          let r = publisher.streamConfigs.findIndex(((e: any) => e.label === 'sophon_video_camera_large' && e.state === 'active'
          ))
          if (r === -1 && (r = publisher.streamConfigs.findIndex(((e: any) => e.label === 'sophon_video_camera_small' && e.state === 'active'
          ))) > -1 && o > -1) {
            const a = publisher.streamConfigs[o]
            a.userId = publisher.userId
            a.displayName = publisher.displayName
            unSubn(a)
          }
          if (n > -1) {
            const s = publisher.streamConfigs[n]
            s.userId = publisher.userId
            s.displayName = publisher.displayName
            unSubn(s)
          }
          if (r > -1) {
            const c = publisher.streamConfigs[r]
            c.userId = publisher.userId
            c.displayName = publisher.displayName
            unSubn(c)
          }
        }
      } else {
        // 流状态更新
        updatePublisherStream(publisher, index)
      }
    })

    /**
     * remote流结束发布事件 onUnPublisher
     * 推流列表删除该用户
     * 移除用户视图
     * 初始化订阅状态
     */
    aliWebrtc.on('onUnPublisher', (publisher: any) => {
      console.log('onUnPublisher', publisher)
      detelePublisher(publisher.userId)
      removeDom(publisher.userId)
      initialization(publisher.userId)
    })

    /**
     * 检测到用户离开频道
     * 更新用户列表
     * 移除用户视图
     */
    aliWebrtc.on('onLeave', (publisher: any) => {
      if (publisher.userId.includes(ownerId)) {
        onOwnerLeave()
      }
      initialization(publisher.userId)
      updateUserList()
      removeDom(publisher.userId)
      // message.info(`${publisher.displayName}离开房间`)
    })
  }

  function getConfigAndJoinRoom() {
    let userId: string
    if (currentUser && currentUser.user_id) {
      userId = `${String(currentUser.user_id)}3`
    } else {
      return
    }

    $dp.aliRTC.channelToken
      .replace({ channel_id: channelId, user_id: userId })
      .get()
      .then((token: any) => {
        aliToken = token
        aliToken.channel = token.channel_id
        aliToken.userid = token.user_id
        joinRoom(aliToken)
      })
      .catch((error:any) => {
        console.log(error)
        message.warning('aliwebrtc token get failed!')
      })
  }

  function doJoinRoomProc(authInfo: any) {
    aliWebrtc.joinChannel(authInfo, nickName).then(() => {
      // showAlert('加入房间成功', 'success', 0)
      // 4. 发布本地流
      aliWebrtc.configLocalAudioPublish = true
      aliWebrtc.configLocalCameraPublish = isCameraEnable
      aliWebrtc.publish().then((res: any) => {
        // Msg.warn(t('webrtc success'))
        // setTimeout(() => {
        //   console.log('发布流成功')
        // }, 1000)
        console.log('发布流成功')
      }, (error: any) => {
        let errorTitle = `[推流失败]${error.message}`
        console.log(errorTitle)
        // $('.streamType').show()
        showAlert(`[推流失败]${error.message}`, 'danger', 0)
        message.warning(`[推流失败]${error.message}`)
      })
    }).catch((error: any) => {
      // showAlert('[加入房间失败]' + error.message, 'danger',0)
      message.warning(`[加入房间失败]${error.message}`)
    })
  }

  function joinRoom(authInfo: any) {
    // 1.预览
    var localVideo = document.getElementById('local-video-currentuser')
    // var localVideo = $('.local-video video')
    aliWebrtc.startPreview(localVideo).then((obj: any) => {
      showAlert('----[开启预览成功]', 'danger', 0)
      setTimeout(() => {
        let videoLocalELe = document.getElementById('local-video-currentuser')
        // console.log(videoLocalELe.videoWidth, videoLocalELe.videoHeight)
        let videoWidth: number = (videoLocalELe as any).videoWidth
        let videoHeight: number = (videoLocalELe as any).videoHeight
        if (videoWidth < 50 || videoHeight < 50) {
          setTimeout(() => {
            videoLocalELe = document.getElementById('local-video-currentuser')
            videoWidth = (videoLocalELe as any).videoWidth
            videoHeight = (videoLocalELe as any).videoHeight
            console.log(videoWidth, videoHeight)
            if (videoWidth < 50 || videoHeight < 50) {
              isCameraEnable = false
              // this.setState({
              //   openCamera: false
              // })
              let name2 = document.getElementById('video-box-text-2')
              if (name2) {
                name2.style.display = 'none'
              }
            }
            doJoinRoomProc(authInfo)
          }, 2000)
        } else {
          doJoinRoomProc(authInfo)
        }
      }, 2000)
    }).catch((error: any) => {
      showAlert(`[开启预览失败]${error.message}`, 'danger', 0)
      isCameraEnable = false
      // this.setState({
      //   openCamera: false
      // })
      let name2 = document.getElementById('video-box-text-2')
      if (name2) {
        name2.style.display = 'none'
      }
      doJoinRoomProc(authInfo)
    })
  }

  function audioAction() {
    if (!openAudia) {
      console.log('open Audia')
      // window.aliWebrtc.enableHighDefinitionPreview(true)
      aliWebrtc.configLocalAudioPublish = true
      aliWebrtc.publish().then((res:any) => {
        setTimeout(() => {
          console.log('发布流成功')
        }, 1000)
      }, (error:any) => {
        // $('.streamType').show()
        showAlert(`[推流失败]${error.message}`, 'danger', 0)
      })
      setOpenAudia(true)
    } else {
      console.log('close Audia')
      // window.aliWebrtc.enableHighDefinitionPreview(false)
      aliWebrtc.configLocalAudioPublish = false
      aliWebrtc.unPublish().then(() => {
        aliWebrtc.publish().then((res:any) => {
          setTimeout(() => {
            console.log('发布流成功')
          }, 1000)
        }, (error:any) => {
          // $('.streamType').show()
          showAlert(`[推流失败]${error.message}`, 'danger', 0)
        })
      }, (error:any) => {
        console.log(error.message)
      })
      setOpenAudia(false)
    }
  }

  function cameraAction() {
    if (!openCamera) {
      console.log('open camera')
      if (!isCameraEnable) {
        // Modal.warning({ title: t('bad camera') })
        return
      }
      let winTips = document.getElementById('local-video-currentuser-parent')
      if (winTips) {
        winTips.style.display = 'block'
      }

      let name2 = document.getElementById('video-box-text-2')
      if (name2) {
        name2.style.display = 'block'
      }
      aliWebrtc.configLocalCameraPublish = true
      aliWebrtc.publish().then((res:any) => {
        setTimeout(() => {
          console.log('发布流成功')
        }, 2000)
      }, (error:any) => {
        showAlert(`[推流失败]${error.message}`, 'danger', 0)
      })
      setOpenCamera(true)
    } else {
      console.log('close camera')
      let winTips = document.getElementById('local-video-currentuser-parent')
      if (winTips) {
        winTips.style.display = 'none'
      }
      let name2 = document.getElementById('video-box-text-2')
      if (name2) {
        name2.style.display = 'none'
      }

      aliWebrtc.configLocalCameraPublish = false
      aliWebrtc.unPublish().then(() => {
        aliWebrtc.publish().then((res:any) => {
          setTimeout(() => {
            console.log('发布流成功')
          }, 2000)
        }, (error:any) => {
          // $('.streamType').show()
          showAlert(`[推流失败]${error.message}`, 'danger', 0)
        })
      }, (error:any) => {
        console.log(error.message)
      })
      setOpenCamera(false)
    }
  }

  function createAliyun() {
    publisherList = []

    /**
     * AliWebRTC isSupport检测
     */
    aliWebrtc.isSupport().then((re: any) => {
      console.log(re)
      init()
      getConfigAndJoinRoom()
    }).catch((error: any) => {
      // self.sendCmdMsg(NTF_MSG_TYPE.LIVE_CANCEL_APPLY_CONNECT, LIVE_CONNECT_TYPE.APPLY)
      // let message
      // $bus.preprocess.publish(CTL_MSG_TYPE.LIVE_CMD_MSG, {
      //   type: NTF_MSG_TYPE.LIVE_CANCEL_APPLY_CONNECT,
      //   data: {}
      // })
      // if (!error.audioDevice) {
      //   message = this.t('audio not found')
      // } else if (!error.videoDevice) {
      //   message = this.t('video not found')
      // } else {
      //   message = error.message
      // }

      // Modal.warning({
      //   title: message,
      //   onOK() {
      //   }
      // })
    })
  }

  useEffect(() => {
    // runningMarquee()
    createAliyun()
    return () => {
      console.log('----container leavechannel')
      aliWebrtc.stopPreview().then().catch()
      aliWebrtc.leaveChannel()
    }
  }, [])

  return (
    <div>
      <div className={styles['remote-user-list']}>
        <div className={styles['remote-user-list-video']} id="remote-user-list-video">
          <div className={styles['video-box']}>
            <div className={styles['video-box-text']}>
              <p className={styles['video-text-p']}>{nickName}</p>
            </div>
            <div className={styles['video-box-parent']} id="local-video-currentuser-parent">
              <video id="local-video-currentuser" autoPlay controls={false} width="146px" height="110px" />
            </div>
            <div className={styles['video-box-text-2']} id="video-box-text-2">
              <p className={styles['video-text-p-2']}>{nickName}</p>
            </div>
          </div>
        </div>
      </div>
      <div className={styles['local-video']}>
        <div className={styles['local-video-window-close']} id="local-video-window-close">
          <div className={styles['local-video-window-close-tips']}>
            <h1 className={styles['local-video-window-close-tips-title']}>{t('closed camera')}</h1>
          </div>
        </div>
        <div className={styles['local-video-window-parent']}>
          <video id="local-video-window" autoPlay controls={false} width="100%" height="100%"> </video>
        </div>
      </div>
      <div className={styles['bottom-view']}>
        <div className={styles['operation-container-head']} onClick={() => audioAction()}><img className={styles.img} src={openAudia ? audioicon : audiocloseicon} width="30px" /></div>
        <div className={styles['operation-container-head']} onClick={() => cameraAction()}><img className={styles.img} src={openCamera ? cameraicon : cameracloseicon} width="30px" margin-left="-15px" /></div>
        {/* <div className={styles['operation-container-righticon']} type="primary" onClick={() => this.audioAction()}><img className={styles['img']} src={this.state.openAudia ? audioicon : audiocloseicon} align="left" width="30px" /></div>
                    <div className={styles['operation-container-head']} type="primary" onClick={() => this.cameraAction()}><img className={styles['img']} src={this.state.openCamera ? cameraicon : cameracloseicon} width="30px" margin-left="-15px" /></div> */}
      </div>
    </div>
  )
}

export default WebRTC

 

posted @ 2020-11-30 22:53  slivens  阅读(209)  评论(0编辑  收藏  举报