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