rtc-live.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. const { v4: uuidv4 } = require("uuid")
  2. const server = require("http").createServer()
  3. const port = 10010
  4. const io = require("socket.io")(server, {
  5. path: "/im-rtc",
  6. serveClient: false,
  7. pingInterval: 10000,
  8. pingTimeout: 5000,
  9. cors: {
  10. origin: "*",
  11. methods: ["GET", "POST"],
  12. },
  13. })
  14. io.on("connection", socket => new ClientRequest(socket))
  15. server.listen(port)
  16. const __rooms = {}
  17. class ClientRequest {
  18. constructor(socket) {
  19. this.socket = socket
  20. this.option = socket.handshake.query
  21. this.init()
  22. // 没有roomId时新建
  23. if (!this.option.roomId) {
  24. this.option.roomId = uuidv4()
  25. }
  26. // 没有角色时默认为主持人
  27. if (!this.option.role) {
  28. this.option.role = "leader"
  29. }
  30. // 判断roomId在房间列表中是否存在
  31. if (!__rooms[this.option.roomId]) {
  32. // 初始化房间
  33. __rooms[this.option.roomId] = []
  34. }
  35. // 没有userId时新建
  36. if (!this.option.userId) {
  37. // 没有userId就新建
  38. this.option.userId = "user-" + (__rooms[this.option.roomId].length + 1)
  39. }
  40. let { role, type, roomId, userId, userName } = this.option
  41. let user = { role, type, roomId, userId, userName }
  42. let users = __rooms[this.option.roomId]
  43. users.push(user)
  44. this.socket.join(this.option.roomId)
  45. this.socket.emit("join", {
  46. user,
  47. users,
  48. })
  49. this.onUserJoin(user, users)
  50. }
  51. init() {
  52. this.socket.on("disconnect", reason => this.onDisconnect(reason))
  53. this.socket.on("reconnect", reason => this.onReconnect(reason))
  54. // 通用事件
  55. this.socket.on("action", data => {
  56. this.socket.broadcast.to(this.option.roomId).emit("action", data)
  57. })
  58. // 踢人
  59. this.socket.on("getOut", userId => this.onGetOut(userId))
  60. // 静音
  61. this.socket.on("muted", (muted, userId) => this.onMuted(muted, userId))
  62. }
  63. onDisconnect(reason) {
  64. let user = null
  65. let users = __rooms[this.option.roomId]
  66. for (let i = 0; i < users.length; i++) {
  67. if (this.option.userId == users[i].userId) {
  68. let splices = users.splice(i, 1)
  69. if (splices.length) {
  70. user = splices[0]
  71. }
  72. break
  73. }
  74. }
  75. user && this.onUserLeave(user, users)
  76. }
  77. onReconnect(reason) {}
  78. /**
  79. * 踢人
  80. */
  81. onGetOut(userId) {
  82. if (!this.isLeader()) {
  83. return
  84. }
  85. this.socket.broadcast.to(this.option.roomId).emit("getOut", userId)
  86. }
  87. /**
  88. * 静音
  89. * @param {*} muted 静音状态
  90. * @param {*} userId 如果有userId,则设置指定用户静音
  91. */
  92. onMuted(muted, userId) {
  93. // 群体静音只有主持人才能使用
  94. if (!this.isLeader()) {
  95. return
  96. }
  97. let user = null
  98. let users = __rooms[this.option.roomId]
  99. if (userId) {
  100. for (let i = 0; i < users.length; i++) {
  101. if (users[i].userId == userId) {
  102. user = users[i]
  103. user.muted = muted
  104. break
  105. }
  106. }
  107. // 没找到指定参与人时不做操作
  108. if (!user) {
  109. return
  110. }
  111. } else {
  112. // 设置所有参与人除主持人外静音状态
  113. users.forEach(item => {
  114. if(item.role == 'leader'){
  115. return
  116. }
  117. item.muted = muted
  118. });
  119. }
  120. this.socket.broadcast.to(this.option.roomId).emit("muted", muted, userId)
  121. }
  122. /**
  123. * 通知其他用户有人加入房间
  124. */
  125. onUserJoin(user, users) {
  126. this.socket.broadcast.to(this.option.roomId).emit("userJoin", { user, users })
  127. }
  128. /**
  129. * 通知其他用户有人离开房间
  130. */
  131. onUserLeave(user, users) {
  132. this.socket.broadcast.to(this.option.roomId).emit("userLeave", { user, users })
  133. console.log(`用户[${user.userId}]离开房间`)
  134. }
  135. isLeader() {
  136. return this.option.role == "leader"
  137. }
  138. }