|
@@ -1,175 +1,175 @@
|
|
|
-import { defineComponent, ref } from 'vue'
|
|
|
-import * as RTC from '@rongcloud/plugin-rtc'
|
|
|
-import Header from './header'
|
|
|
-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'
|
|
|
-import runtime, * as RuntimeUtils from './runtime'
|
|
|
-import Chronography from './chronography'
|
|
|
-// import { removeMedia } from './helpers'
|
|
|
-import styles from './index.module.less'
|
|
|
-
|
|
|
-const videoRef = ref<HTMLVideoElement | null>(null)
|
|
|
-
|
|
|
-let microphoneAudioTrack: RTC.RCLocalTrack
|
|
|
-let cameraVideoTrack: RTC.RCLocalTrack
|
|
|
-
|
|
|
-export default defineComponent({
|
|
|
- name: 'LiveBroadcast',
|
|
|
- data() {
|
|
|
- return {
|
|
|
- headerStatus: false
|
|
|
- }
|
|
|
- },
|
|
|
- computed: {
|
|
|
- isLive() {
|
|
|
- console.log(runtime.videoStatus)
|
|
|
- if(runtime.videoStatus === 'liveing') {
|
|
|
- setTimeout(() => {
|
|
|
- this.headerStatus = true
|
|
|
- }, 3000);
|
|
|
- } else {
|
|
|
- this.headerStatus = false
|
|
|
- }
|
|
|
- return runtime.videoStatus === 'liveing'
|
|
|
- }
|
|
|
- },
|
|
|
- async mounted() {
|
|
|
- this.initializeRoom()
|
|
|
- RuntimeUtils.loopSyncLike()
|
|
|
- event.on(LIVE_EVENT_MESSAGE['RC:Chatroom:Like'], this.onLikeMessage)
|
|
|
- window.onbeforeunload = this.beforeunload
|
|
|
- },
|
|
|
- beforeUnmount() {
|
|
|
- event.off(LIVE_EVENT_MESSAGE['RC:Chatroom:Like'], this.onLikeMessage)
|
|
|
- window.onbeforeunload = null
|
|
|
- },
|
|
|
- methods: {
|
|
|
- beforeunload() {
|
|
|
- if (runtime.videoStatus === 'liveing') {
|
|
|
- return '当前正在直播中是否确认关闭页面?'
|
|
|
- }
|
|
|
- },
|
|
|
- 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 {
|
|
|
- runtime.likeCount = state.user?.likeNum || 0
|
|
|
- runtime.lookCount = state.user?.lookNum || 0
|
|
|
- const isLiveing = sessionStorage.getItem(RuntimeUtils.START_LIVE_STATUS) === 'liveing'
|
|
|
- // IM连接
|
|
|
- await RuntimeUtils.connectIM(state.user?.imToken)
|
|
|
- runtime.videoRef = videoRef.value
|
|
|
- // 获取设备
|
|
|
- await RuntimeUtils.getMicrophones()
|
|
|
- await RuntimeUtils.getCameras()
|
|
|
- // 设置播放设备
|
|
|
- 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', isLiveing)
|
|
|
- // await RuntimeUtils.getTrack('microphone')
|
|
|
- microphoneAudioTrack = await RuntimeUtils.getTrack('microphone')
|
|
|
- // microphoneAudioTrack.play()
|
|
|
- // console.log(microphoneAudioTrack)
|
|
|
- // console.log(runtime.deviceStatus)
|
|
|
- runtime.videoStatus = 'stream'
|
|
|
- const join = await RuntimeUtils.joinRoom(state.user?.roomUid, RTC.RCLivingType.VIDEO, {
|
|
|
- onMessageReceive(name, content) {
|
|
|
- console.log(name, content)
|
|
|
- },
|
|
|
- onKickOff(byServer: boolean) {
|
|
|
- console.log(byServer)
|
|
|
- },
|
|
|
- async onTrackPublish (tracks: RTC.RCRemoteTrack[]) {
|
|
|
- const subscribeRes = await join?.room?.subscribe(tracks)
|
|
|
- console.log(subscribeRes)
|
|
|
- if (subscribeRes?.code && subscribeRes.code !== RTC.RCRTCCode.SUCCESS) {
|
|
|
- console.log('资源订阅失败 ->', subscribeRes.code)
|
|
|
- }
|
|
|
- },
|
|
|
- onTrackUnpublish(tracks: RTC.RCRemoteTrack[]) {
|
|
|
- console.log(tracks)
|
|
|
- event.emit(LIVE_EVENT_MESSAGE['RM:RTC:TrackUnpublish'], tracks)
|
|
|
- },
|
|
|
- onSwitchRole(userId: string, role: RTC.RCRTCLiveRole) {
|
|
|
- event.emit(LIVE_EVENT_MESSAGE['RM:RTC:SwitchRole'], {
|
|
|
- userId,
|
|
|
- role,
|
|
|
- })
|
|
|
- },
|
|
|
- onTrackReady (track: RTC.RCRemoteTrack) {
|
|
|
- if (track.isAudioTrack()) {
|
|
|
- // 音轨不需要传递播放控件
|
|
|
- track.play()
|
|
|
- }
|
|
|
- },
|
|
|
- onUserJoin (userIds: string[]) {
|
|
|
- console.log('onUserJoin', userIds)
|
|
|
- },
|
|
|
- onUserLeave (userIds: string[]) {
|
|
|
- event.emit(LIVE_EVENT_MESSAGE['RM:RTC:UserLeave'], userIds)
|
|
|
- console.log('onUserLeave', userIds)
|
|
|
- },
|
|
|
- })
|
|
|
- if (join.room && join.code === RTC.RCRTCCode.SUCCESS) {
|
|
|
- runtime.joinedRoom = join.room
|
|
|
- }
|
|
|
- if (isLiveing) {
|
|
|
- await RuntimeUtils.startLive(false)
|
|
|
- runtime.videoStatus = 'liveing'
|
|
|
- } else {
|
|
|
- await RuntimeUtils.setTrack([cameraVideoTrack], 'camera', false)
|
|
|
- await RuntimeUtils.setTrack([microphoneAudioTrack], 'microphone', false)
|
|
|
- }
|
|
|
- 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)
|
|
|
- }
|
|
|
- },
|
|
|
- closeLive() {
|
|
|
- // removeMedia(runtime.mediaStreams, runtime.mediaStreamTrack)
|
|
|
- runtime.videoStatus = 'stream'
|
|
|
- }
|
|
|
- },
|
|
|
- render() {
|
|
|
- return (
|
|
|
- <div class={styles.main}>
|
|
|
- {this.isLive ? null : null}
|
|
|
- <div class={[styles.headerSection]}>
|
|
|
- <Header class={[styles.headerContent, this.headerStatus ? styles["header-top"] : null]} />
|
|
|
- </div>
|
|
|
- <div class={styles.video}>
|
|
|
- <video ref={videoRef}></video>
|
|
|
- {!runtime.screenShareStatus ? <VideoStatus/> : null}
|
|
|
- {runtime.videoStatus === 'liveing' ? <Chronography/> : null}
|
|
|
- </div>
|
|
|
- <ActionBar/>
|
|
|
- {/* <div>video: {runtime.videoStatus}, imStatus: {runtime.imConnectStatus}</div> */}
|
|
|
- </div>
|
|
|
- )
|
|
|
- }
|
|
|
-})
|
|
|
+import { defineComponent, ref } from 'vue'
|
|
|
+import * as RTC from '@rongcloud/plugin-rtc'
|
|
|
+import Header from './header'
|
|
|
+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'
|
|
|
+import runtime, * as RuntimeUtils from './runtime'
|
|
|
+import Chronography from './chronography'
|
|
|
+// import { removeMedia } from './helpers'
|
|
|
+import styles from './index.module.less'
|
|
|
+
|
|
|
+const videoRef = ref<HTMLVideoElement | null>(null)
|
|
|
+
|
|
|
+let microphoneAudioTrack: RTC.RCLocalTrack
|
|
|
+let cameraVideoTrack: RTC.RCLocalTrack
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'LiveBroadcast',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ headerStatus: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ isLive() {
|
|
|
+ console.log(runtime.videoStatus)
|
|
|
+ if(runtime.videoStatus === 'liveing') {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.headerStatus = true
|
|
|
+ }, 3000);
|
|
|
+ } else {
|
|
|
+ this.headerStatus = false
|
|
|
+ }
|
|
|
+ return runtime.videoStatus === 'liveing'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async mounted() {
|
|
|
+ this.initializeRoom()
|
|
|
+ RuntimeUtils.loopSyncLike()
|
|
|
+ event.on(LIVE_EVENT_MESSAGE['RC:Chatroom:Like'], this.onLikeMessage)
|
|
|
+ window.onbeforeunload = this.beforeunload
|
|
|
+ },
|
|
|
+ beforeUnmount() {
|
|
|
+ event.off(LIVE_EVENT_MESSAGE['RC:Chatroom:Like'], this.onLikeMessage)
|
|
|
+ window.onbeforeunload = null
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ beforeunload() {
|
|
|
+ if (runtime.videoStatus === 'liveing') {
|
|
|
+ return '当前正在直播中是否确认关闭页面?'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ 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 {
|
|
|
+ runtime.likeCount = state.user?.likeNum || 0
|
|
|
+ runtime.lookCount = state.user?.lookNum || 0
|
|
|
+ const isLiveing = sessionStorage.getItem(RuntimeUtils.START_LIVE_STATUS) === 'liveing'
|
|
|
+ // IM连接
|
|
|
+ await RuntimeUtils.connectIM(state.user?.imToken)
|
|
|
+ runtime.videoRef = videoRef.value
|
|
|
+ // 获取设备
|
|
|
+ await RuntimeUtils.getMicrophones()
|
|
|
+ await RuntimeUtils.getCameras()
|
|
|
+ // 设置播放设备
|
|
|
+ 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', isLiveing)
|
|
|
+ // await RuntimeUtils.getTrack('microphone')
|
|
|
+ microphoneAudioTrack = await RuntimeUtils.getTrack('microphone')
|
|
|
+ // microphoneAudioTrack.play()
|
|
|
+ // console.log(microphoneAudioTrack)
|
|
|
+ // console.log(runtime.deviceStatus)
|
|
|
+ runtime.videoStatus = 'stream'
|
|
|
+ const join = await RuntimeUtils.joinRoom(state.user?.roomUid, RTC.RCLivingType.VIDEO, {
|
|
|
+ onMessageReceive(name, content) {
|
|
|
+ console.log(name, content)
|
|
|
+ },
|
|
|
+ onKickOff(byServer: boolean) {
|
|
|
+ console.log(byServer)
|
|
|
+ },
|
|
|
+ async onTrackPublish (tracks: RTC.RCRemoteTrack[]) {
|
|
|
+ const subscribeRes = await join?.room?.subscribe(tracks)
|
|
|
+ console.log(subscribeRes)
|
|
|
+ if (subscribeRes?.code && subscribeRes.code !== RTC.RCRTCCode.SUCCESS) {
|
|
|
+ console.log('资源订阅失败 ->', subscribeRes.code)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onTrackUnpublish(tracks: RTC.RCRemoteTrack[]) {
|
|
|
+ console.log(tracks)
|
|
|
+ event.emit(LIVE_EVENT_MESSAGE['RM:RTC:TrackUnpublish'], tracks)
|
|
|
+ },
|
|
|
+ onSwitchRole(userId: string, role: RTC.RCRTCLiveRole) {
|
|
|
+ event.emit(LIVE_EVENT_MESSAGE['RM:RTC:SwitchRole'], {
|
|
|
+ userId,
|
|
|
+ role,
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onTrackReady (track: RTC.RCRemoteTrack) {
|
|
|
+ if (track.isAudioTrack()) {
|
|
|
+ // 音轨不需要传递播放控件
|
|
|
+ track.play()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onUserJoin (userIds: string[]) {
|
|
|
+ console.log('onUserJoin', userIds)
|
|
|
+ },
|
|
|
+ onUserLeave (userIds: string[]) {
|
|
|
+ event.emit(LIVE_EVENT_MESSAGE['RM:RTC:UserLeave'], userIds)
|
|
|
+ console.log('onUserLeave', userIds)
|
|
|
+ },
|
|
|
+ })
|
|
|
+ if (join.room && join.code === RTC.RCRTCCode.SUCCESS) {
|
|
|
+ runtime.joinedRoom = join.room
|
|
|
+ }
|
|
|
+ if (isLiveing) {
|
|
|
+ await RuntimeUtils.startLive(false)
|
|
|
+ runtime.videoStatus = 'liveing'
|
|
|
+ } else {
|
|
|
+ await RuntimeUtils.setTrack([cameraVideoTrack], 'camera', false)
|
|
|
+ await RuntimeUtils.setTrack([microphoneAudioTrack], 'microphone', false)
|
|
|
+ }
|
|
|
+ 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)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ closeLive() {
|
|
|
+ // removeMedia(runtime.mediaStreams, runtime.mediaStreamTrack)
|
|
|
+ runtime.videoStatus = 'stream'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ render() {
|
|
|
+ return (
|
|
|
+ <div class={styles.main}>
|
|
|
+ {this.isLive ? null : null}
|
|
|
+ <div class={[styles.headerSection]}>
|
|
|
+ <Header class={[styles.headerContent, this.headerStatus ? styles["header-top"] : null]} />
|
|
|
+ </div>
|
|
|
+ <div class={styles.video}>
|
|
|
+ <video ref={videoRef}></video>
|
|
|
+ {!runtime.screenShareStatus ? <VideoStatus/> : null}
|
|
|
+ {runtime.videoStatus === 'liveing' ? <Chronography/> : null}
|
|
|
+ </div>
|
|
|
+ <ActionBar/>
|
|
|
+ {/* <div>video: {runtime.videoStatus}, imStatus: {runtime.imConnectStatus}</div> */}
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }
|
|
|
+})
|