|
@@ -2,8 +2,10 @@ import { reactive, ref, Ref } from 'vue'
|
|
|
import * as RongIMLib from '@rongcloud/imlib-next'
|
|
|
import * as RTC from '@rongcloud/plugin-rtc'
|
|
|
import request from '/src/helpers/request'
|
|
|
+import { state } from '/src/state'
|
|
|
import event, { LIVE_EVENT_MESSAGE } from './event'
|
|
|
import { removeMedia } from './helpers'
|
|
|
+// import { SeatsCtrl } from './message-type'
|
|
|
|
|
|
type imConnectStatus = 'connecting' | 'connected' | 'disconnect'
|
|
|
|
|
@@ -46,6 +48,8 @@ const runtime = reactive({
|
|
|
lastLikeCount: 0,
|
|
|
/** 当前活跃的数据流 */
|
|
|
activeTracks: {} as ActiveTracks,
|
|
|
+ /** 是否允许连麦 */
|
|
|
+ allowSeatsCtrl: true,
|
|
|
})
|
|
|
|
|
|
export default runtime
|
|
@@ -57,6 +61,14 @@ RongIMLib.init({
|
|
|
appkey: RONG_IM_TOKEN,
|
|
|
})
|
|
|
|
|
|
+// 注册自定义消息类型
|
|
|
+
|
|
|
+// 控制是否允许连麦
|
|
|
+const MessageSeatsCtrl = RongIMLib.registerMessageType('RC:Chatroom:SeatsCtrl', true, true)
|
|
|
+
|
|
|
+// 控制是否允许发言
|
|
|
+const MessageChatBan = RongIMLib.registerMessageType('RC:Chatroom:ChatBan', true, true)
|
|
|
+
|
|
|
type MessageProps = {
|
|
|
messageType: 'RC:Chatroom:Welcome' | 'RC:TxtMsg' | 'RC:Chatroom:Barrage' | 'RC:Chatroom:Like',
|
|
|
content: any,
|
|
@@ -235,25 +247,29 @@ export const getTrack = async (trackType: TrackType): Promise<RTC.RCLocalTrack>
|
|
|
* 添加视频流,会同步修改当先视频与推送的流
|
|
|
* @param track
|
|
|
*/
|
|
|
-export const setTrack = async (tracks: RTC.RCLocalTrack[], trackType: TrackType) => {
|
|
|
+export const setTrack = async (tracks: RTC.RCLocalTrack[], trackType: TrackType, needPublish = true) => {
|
|
|
for (const track of tracks) {
|
|
|
// @ts-ignore
|
|
|
await runtime.mediaStreams?.addTrack(track._msTrack)
|
|
|
runtime.activeTracks[trackType] = track
|
|
|
}
|
|
|
- await runtime.joinedRoom?.publish(tracks)
|
|
|
+ if (needPublish) {
|
|
|
+ await runtime.joinedRoom?.publish(tracks)
|
|
|
+ }
|
|
|
}
|
|
|
/**
|
|
|
* 删除视频流,会同步修改当先视频与推送的流
|
|
|
* @param track
|
|
|
*/
|
|
|
-export const removeTrack = async (tracks: RTC.RCLocalTrack[], trackType: TrackType) => {
|
|
|
+export const removeTrack = async (tracks: RTC.RCLocalTrack[], trackType: TrackType, needPublish = true) => {
|
|
|
for (const track of tracks) {
|
|
|
// @ts-ignore
|
|
|
await runtime.mediaStreams?.removeTrack(track._msTrack)
|
|
|
runtime.activeTracks[trackType] = null
|
|
|
}
|
|
|
- await runtime.joinedRoom?.unpublish(tracks)
|
|
|
+ if (needPublish) {
|
|
|
+ await runtime.joinedRoom?.unpublish(tracks)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
export const joinRoom = async (roomId: string, type: RTC.RCLivingType, listenEvents: RTC.IRoomEventListener | null) => {
|
|
@@ -270,7 +286,19 @@ export const joinRoom = async (roomId: string, type: RTC.RCLivingType, listenEve
|
|
|
|
|
|
export const startLive = async () => {
|
|
|
if (runtime.videoStatus !== 'stream') throw Error('当前无视频流')
|
|
|
-
|
|
|
+ const room = runtime.joinedRoom
|
|
|
+ if (room) {
|
|
|
+ const microphoneAudioTrack = await getTrack('microphone')
|
|
|
+ const cameraVideoTrack = await getTrack('camera')
|
|
|
+ await setTrack([cameraVideoTrack], 'camera')
|
|
|
+ runtime.videoStatus = 'liveing'
|
|
|
+ await setTrack([microphoneAudioTrack], 'microphone')
|
|
|
+ const builder = await runtime.joinedRoom?.getMCUConfigBuilder()
|
|
|
+ // @ts-ignore
|
|
|
+ await builder.setOutputVideoRenderMode?.(RTC.MixVideoRenderMode.WHOLE)
|
|
|
+ // @ts-ignore
|
|
|
+ await builder.flush()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -279,6 +307,14 @@ export const startLive = async () => {
|
|
|
export const closeLive = async () => {
|
|
|
removeMedia(runtime.mediaStreams, runtime.mediaStreamTrack)
|
|
|
runtime.videoStatus = 'stopped'
|
|
|
+ for (const key in runtime.activeTracks) {
|
|
|
+ if (Object.prototype.hasOwnProperty.call(runtime.activeTracks, key)) {
|
|
|
+ const track = runtime.activeTracks[key as TrackType] as RTC.RCLocalTrack
|
|
|
+ if (track) {
|
|
|
+ removeTrack([track], key as TrackType)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -293,6 +329,44 @@ export const loopSyncLike = async () => {
|
|
|
}
|
|
|
setTimeout(() => {
|
|
|
loopSyncLike()
|
|
|
- }, 1000 * 60 * 5)
|
|
|
+ }, 1000 * 60)
|
|
|
}
|
|
|
|
|
|
+type SendMessageType = 'text' | 'image' | 'audio' | 'video' | 'file' | 'SeatsCtrl' | 'ChatBan'
|
|
|
+
|
|
|
+export const getSendMessageUser = () => {
|
|
|
+ return {
|
|
|
+ id: state.user?.id,
|
|
|
+ name: state.user?.realName,
|
|
|
+ userId: state.user?.id,
|
|
|
+ userName: state.user?.realName,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @param msg 消息内容
|
|
|
+ * @param type 消息类型
|
|
|
+ * @returns null 或者 发送消息的结果
|
|
|
+ */
|
|
|
+export const sendMessage = async (msg: any, type: SendMessageType = 'text') => {
|
|
|
+ let message: RongIMLib.BaseMessage<unknown> | null = null
|
|
|
+ if (!msg) return
|
|
|
+ const conversation = {
|
|
|
+ conversationType: RongIMLib.ConversationType.CHATROOM,
|
|
|
+ targetId: runtime.joinedRoom?._roomId as string,
|
|
|
+ }
|
|
|
+ if (type === 'text') {
|
|
|
+ message = new RongIMLib.TextMessage({
|
|
|
+ user: getSendMessageUser(),
|
|
|
+ content: msg
|
|
|
+ })
|
|
|
+ } else if (type === 'SeatsCtrl') {
|
|
|
+ message = new MessageSeatsCtrl(msg)
|
|
|
+ } else if (type === 'ChatBan') {
|
|
|
+ message = new MessageChatBan(msg)
|
|
|
+ }
|
|
|
+ if (!message) return
|
|
|
+ console.log(msg)
|
|
|
+ await RongIMLib.sendMessage(conversation, message)
|
|
|
+}
|