meeting.service.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import TRTC from 'trtc-sdk-v5'
  2. import { useNotification } from 'naive-ui'
  3. import { ref } from 'vue'
  4. import userData from '@/utils/userdata'
  5. interface RoomOption {
  6. userId: string,
  7. roomId: number,
  8. sdkAppId: number,
  9. userSig: string
  10. }
  11. export interface UserList {
  12. userName: string,
  13. userId: number,
  14. isMute: boolean, // 是否静音
  15. isVideo: boolean, // 是否有视频
  16. isState: boolean, // 是否到场
  17. manageId: number,
  18. type: boolean,
  19. orgName: string,
  20. isCreate: number,
  21. isMe: boolean
  22. }
  23. class meetingService {
  24. private trtc: any = null
  25. private notification = useNotification()
  26. public list = ref([] as UserList[])
  27. private loginInfo = userData.getUserData().loginInfo
  28. // 监测设备
  29. private async detectionDevice() {
  30. let status = true
  31. const micList = await TRTC.getMicrophoneList()
  32. const speakerList = await TRTC.getSpeakerList()
  33. const hasMicrophoneDevice = micList.length > 0
  34. const hasSpeakerDevice = speakerList.length > 0
  35. if (!hasMicrophoneDevice || !hasSpeakerDevice) {
  36. status = false
  37. }
  38. if (hasMicrophoneDevice) {
  39. try {
  40. await this.trtc.startLocalAudio({ publish: false })
  41. await this.trtc.enableAudioVolumeEvaluation(250)
  42. await this.trtc.stopLocalAudio()
  43. } catch (error) {
  44. status = false
  45. }
  46. }
  47. return status
  48. }
  49. // 加入房间+发布local video|audio
  50. public async joinRoom(options: RoomOption, videoDomID: string) {
  51. if (!this.trtc) return
  52. await this.trtc.enterRoom(options)
  53. this.isStartLocalVideo(false, videoDomID)
  54. this.isStartLocalAuido(false)
  55. const { userId } = options
  56. this.list.value.forEach((el) => {
  57. if (+userId === el.userId) {
  58. el.isState = true
  59. el.isMute = false
  60. el.isVideo = false
  61. }
  62. })
  63. }
  64. // 退出房间
  65. public async exitRoom() {
  66. if (!this.trtc) return
  67. await this.trtc.exitRoom()
  68. await this.trtc.stopLocalVideo()
  69. await this.trtc.stopLocalAudio()
  70. this.destroy()
  71. }
  72. // 是否静音远程用户
  73. public async isStartRomoteAudio(userId: string, mute: boolean) {
  74. if (!this.trtc) return
  75. await this.trtc.muteRemoteAudio(userId, mute)
  76. }
  77. // 是否本地视频推送
  78. public async isStartLocalVideo(mute: boolean, videoDomID: string) {
  79. if (!this.trtc) return
  80. if (mute) await this.trtc.stopLocalVideo()
  81. if (!mute) await this.trtc.startLocalVideo({ view: document.getElementById(videoDomID) })
  82. }
  83. // 是否本地音频推送
  84. public async isStartLocalAuido(mute: boolean) {
  85. if (!this.trtc) return
  86. if (mute) await this.trtc.stopLocalAudio()
  87. if (!mute) await this.trtc.startLocalAudio()
  88. }
  89. // 设置参会人员
  90. public setUserList(userList: UserList[]) {
  91. // 找出自己
  92. const arr = []
  93. for (let k = 0; k < userList.length; k++) {
  94. const el = userList[k]
  95. if (el.isCreate) {
  96. arr.unshift({
  97. ...el, isMute: true, isVideo: true, isState: false, isMe: this.loginInfo.userId === el.userId, type: !!el.isCreate
  98. })
  99. } else {
  100. arr.push({
  101. ...el, isMute: true, isVideo: true, isState: false, isMe: this.loginInfo.userId === el.userId, type: !!el.isCreate
  102. })
  103. }
  104. }
  105. console.log('参会人员', arr)
  106. this.list.value = arr
  107. }
  108. // 初始化
  109. public async _init() {
  110. if (this.trtc) this.destroy()
  111. // creta
  112. this.trtc = TRTC.create()
  113. // 检测设备
  114. const status = await this.detectionDevice()
  115. if (!status) this.notification.error({ content: '请检查你的麦克风或扬声器是否正常' })
  116. // 监听房间事件
  117. this.trtc.on(TRTC.EVENT.ERROR, this.handleError.bind(this))
  118. // this.trtc.on(TRTC.EVENT.KICKED_OUT, this.handleKickedOut.bind(this))
  119. this.trtc.on(TRTC.EVENT.REMOTE_USER_ENTER, this.handleRemoteUserEnter.bind(this))
  120. this.trtc.on(TRTC.EVENT.REMOTE_USER_EXIT, this.handleRemoteUserExit.bind(this))
  121. this.trtc.on(TRTC.EVENT.REMOTE_AUDIO_UNAVAILABLE, this.handleRemoteAudioUnavailable.bind(this))
  122. this.trtc.on(TRTC.EVENT.REMOTE_AUDIO_AVAILABLE, this.handleRemoteAudioAvailable.bind(this))
  123. this.trtc.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, this.handleRemoteVideoAvailable.bind(this))
  124. this.trtc.on(TRTC.EVENT.REMOTE_VIDEO_UNAVAILABLE, this.handleRemoteVideoUnavailable.bind(this))
  125. // this.trtc.on(TRTC.EVENT.AUDIO_VOLUME, this.handleAudioVolume.bind(this))
  126. return true
  127. }
  128. // 错误信息
  129. private handleError(error: { message: string }) {
  130. this.notification.error({
  131. content: error.message,
  132. duration: 2000
  133. })
  134. }
  135. // 远程用户加入
  136. private handleRemoteUserEnter(event: { userId: string }) {
  137. console.log('远程用户加入', event)
  138. const { userId } = event
  139. this.list.value.forEach((el) => {
  140. if (+userId === el.userId) {
  141. el.isState = true
  142. }
  143. })
  144. }
  145. // 远程用户离开
  146. private handleRemoteUserExit(event: { userId: string }) {
  147. console.log('远程用户离开', event)
  148. const { userId } = event
  149. this.list.value.forEach((el) => {
  150. if (+userId === el.userId) {
  151. el.isState = false
  152. el.isMute = true
  153. el.isVideo = true
  154. }
  155. })
  156. }
  157. // 远程用户音频不可用
  158. private handleRemoteAudioUnavailable(event: { userId: string }) {
  159. console.log('远程用户音频不可用', event)
  160. const { userId } = event
  161. this.list.value.forEach((el) => {
  162. if (+userId === el.userId) {
  163. el.isMute = true
  164. }
  165. })
  166. }
  167. // 远程用户音频可用
  168. private handleRemoteAudioAvailable(event: { userId: string }) {
  169. console.log('远程用户音频可用', event)
  170. const { userId } = event
  171. this.list.value.forEach((el) => {
  172. if (+userId === el.userId) {
  173. el.isMute = false
  174. }
  175. })
  176. }
  177. // 远程用户视频不可用
  178. private handleRemoteVideoUnavailable(event: { userId: string; streamType: string }) {
  179. console.log('远程用户视频不可用', event)
  180. const { userId, streamType } = event
  181. this.trtc.updateRemoteVideo({
  182. userId,
  183. streamType,
  184. view: `D-${userId}`
  185. })
  186. this.list.value.forEach((el) => {
  187. if (+userId === el.userId) {
  188. el.isVideo = true
  189. }
  190. })
  191. }
  192. // 远程用户视频可用
  193. private handleRemoteVideoAvailable(event: { userId: string; streamType: string }) {
  194. console.log('远程用户视频可用', event)
  195. const { userId, streamType } = event
  196. this.trtc.startRemoteVideo({
  197. userId,
  198. streamType,
  199. view: `D-${userId}`
  200. })
  201. this.list.value.forEach((el) => {
  202. if (+userId === el.userId) {
  203. el.isVideo = false
  204. }
  205. })
  206. }
  207. private destroy() {
  208. if (this.trtc) this.trtc.destroy()
  209. this.trtc = null
  210. }
  211. }
  212. export default meetingService