RtcService.Live.cs 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. using WingServerCommon.Service;
  2. using WingInterfaceLibrary.Internal.Interface;
  3. using WingInterfaceLibrary.DTO.RtcRoom;
  4. using WingInterfaceLibrary.DB.Request;
  5. using WingInterfaceLibrary.DTO.LiveRoom;
  6. using WingInterfaceLibrary.Internal.Request;
  7. using WingInterfaceLibrary.Rtc;
  8. using WingInterfaceLibrary.Enum;
  9. using WingInterfaceLibrary.LiveConsultation;
  10. using WingServerCommon.Interfaces.Cache;
  11. using WingServerCommon.Utilities;
  12. using WingServerCommon.Log;
  13. using WingInterfaceLibrary.Request;
  14. using Newtonsoft.Json;
  15. namespace WingRtcService
  16. {
  17. /// <summary>
  18. /// RTC服务
  19. /// </summary>
  20. public partial class RtcService : JsonRpcService, IRtcService
  21. {
  22. /// <summary>
  23. /// 获取房间详情和发送关闭推流通知给设备端
  24. /// </summary>
  25. /// <returns></returns>
  26. public async Task<LiveRoomDTO> GetOrCloseDeviceAsync(GetOrCloseDeviceRequest request)
  27. {
  28. var liveRoomCode = request.LiveRoomCode;
  29. var deviceShortCode = request.DeviceShortCode;
  30. var closeDevicePush = request.CloseDevicePush;
  31. Logger.WriteLineInfo($"RtcService GetOrCloseDeviceAsync liveRoomCode:{liveRoomCode}, deviceShortCode:{deviceShortCode}, closeDevicePush:{closeDevicePush}");
  32. RtcRoom room = null;
  33. if (!string.IsNullOrWhiteSpace(liveRoomCode))
  34. {
  35. room = _rtcRoomManager.Get(liveRoomCode, false);
  36. }
  37. else if (!string.IsNullOrWhiteSpace(deviceShortCode))
  38. {
  39. var device = await _deviceDBService.FindDeviceInfoByShortCodeAsync(deviceShortCode);
  40. if (device != null)
  41. {
  42. room = _rtcRoomManager.GetInitiatingRoomByDeviceCode(device.DeviceCode, "");
  43. }
  44. }
  45. if (room != null && closeDevicePush && room.DeviceInfos != null && room.DeviceInfos.Any())
  46. {
  47. room.CloseDevicePushAction();
  48. room = _rtcRoomManager.Get(room.LiveRoomCode, false);
  49. await AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest { LiveRoom = room });
  50. var syncInfo = new BaseLiveConsultationJson
  51. {
  52. ConsultationRecordCode = room.LiveRoomCode,
  53. RoomCode = room.LiveRoomCode,
  54. InitatorCode = room.InitiatorCode,
  55. OperatorCode = "",
  56. };
  57. await SyncToMasterAsync(SyncTypeEnum.CloseDeviceLive, room.LiveRoomCode, room.Name, syncInfo);
  58. }
  59. return await Task.FromResult<LiveRoomDTO>(room);
  60. }
  61. /// <summary>
  62. /// 检查关闭设备直播
  63. /// </summary>
  64. /// <returns></returns>
  65. public async Task CheckDeviceLiveRoomAsync(TokenRequest request)
  66. {
  67. var cacheRooms = _rtcRoomManager.GetCacheRooms();
  68. var deviceRooms = cacheRooms.Where(x => x.Status == LiveRoomStatus.Initiating && x.DeviceInfos.Any(u => u.Code == x.LiveRoomCode && u.Status == LiveMemberStatus.Joined))?.ToList() ?? new List<RtcRoom>();
  69. foreach (var room in deviceRooms)
  70. {
  71. var timeoutTime = DateTime.UtcNow.AddSeconds(-1 * (_reportStateIntervalSeconds + 60));
  72. if (!room.ViewerInfos.Any(x => x.LastReportTime >= timeoutTime))
  73. {
  74. var device = room.UserInfos?.FirstOrDefault(x => x.Code == room.LiveRoomCode) ?? new LiveMemberDTO();
  75. Logger.WriteLineInfo($"RtcService CheckDeviceLiveRoomAsync, roomId:{room.LiveRoomCode}, device:{device.Name}");
  76. room.CloseDevicePushAction();
  77. var liveRoom = _rtcRoomManager.Get(room.LiveRoomCode, false);
  78. await AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest { LiveRoom = liveRoom });
  79. }
  80. }
  81. }
  82. /// <summary>
  83. /// 创建或更新房间信息
  84. /// </summary>
  85. /// <returns></returns>
  86. public async Task<LiveRoomDTO> AddOrUpdateLiveRoomAsync(AddOrUpdateLiveRoomRequest request)
  87. {
  88. var req = new AddOrUpdateLiveRoomDBRequest
  89. {
  90. Data = request.LiveRoom
  91. };
  92. var roomId = await _liveRoomDBService.AddOrUpdateLiveRoomAsync(req);
  93. var room = _rtcRoomManager.Get(roomId, true);
  94. return await Task.FromResult(room);
  95. }
  96. /// <summary>
  97. /// 获取房间信息
  98. /// </summary>
  99. /// <returns></returns>
  100. public async Task<LiveRoomDTO> GetLiveRoomAsync(GetLiveRoomRequest request)
  101. {
  102. var roomId = request.LiveRoomCode;
  103. var room = _rtcRoomManager.Get(roomId);
  104. return await Task.FromResult(room);
  105. }
  106. /// <summary>
  107. /// 查询房间白板交互数据
  108. /// </summary>
  109. /// <returns></returns>
  110. public async Task<IList<LiveBoardDataDTO>> GetLiveBoardDatasAsync(GetLiveBoardDatasRequest request)
  111. {
  112. var roomId = request.LiveRoomCode;
  113. var room = _rtcRoomManager.Get(roomId);
  114. return await Task.FromResult(room?.BoardDataInfos ?? new List<LiveBoardDataDTO>());
  115. }
  116. /// <summary>
  117. /// 查询房间用户列表
  118. /// </summary>
  119. /// <returns></returns>
  120. public async Task<List<LiveConsultationMember>> GetLiveMemberInfosAsync(GetLiveMemberInfosRequest request)
  121. {
  122. var roomId = request.LiveRoomCode;
  123. var members = _rtcRoomManager.GetLiveMemberInfos(roomId);
  124. return await Task.FromResult(members);
  125. }
  126. /// <summary>
  127. /// 根据用户codes查询房间用户状态
  128. /// </summary>
  129. /// <returns></returns>
  130. public async Task<IList<LiveMemberStatusDTO>> GetLiveMemberStatusInfosAsync(GetLiveMemberStatusInfosRequest request)
  131. {
  132. var members = _rtcRoomManager.GetLiveMemberStatusInfos(request.UserCodes);
  133. return await Task.FromResult(members);
  134. }
  135. /// <summary>
  136. /// 查询正在推流的设备房间
  137. /// </summary>
  138. /// <returns></returns>
  139. public async Task<LiveRoomDTO> GetInitiatingRoomByDeviceCodeAsync(GetInitiatingRoomByDeviceCodeRequest request)
  140. {
  141. var deviceCode = request.DeviceCode;
  142. var room = _rtcRoomManager.GetInitiatingRoomByDeviceCode(deviceCode, "");
  143. return await Task.FromResult(room);
  144. }
  145. /// <summary>
  146. /// 开始直播
  147. /// </summary>
  148. /// <returns></returns>
  149. public async Task<LiveRoomDTO> InitiateAsync(InitiateRequest request)
  150. {
  151. var roomId = request.LiveRoomCode;
  152. var initiatorCode = request.InitiatorCode;
  153. var room = _rtcRoomManager.Get(roomId);
  154. Logger.WriteLineInfo($"RTCService InitiateAsync 1, room:{ JsonConvert.SerializeObject(room) }");
  155. var deviceCode = room.DeviceInfos.FirstOrDefault()?.Code ?? string.Empty;
  156. var existedRoom = _rtcRoomManager.GetInitiatingRoomByDeviceCode(deviceCode, room.LiveRoomCode);
  157. Logger.WriteLineInfo($"RTCService InitiateAsync 2, existedRoom:{JsonConvert.SerializeObject(existedRoom)}");
  158. var rtcRoomId = room.RtcRoomId;
  159. var existedLiveRooms = new List<LiveMemberDTO>();
  160. if (rtcRoomId == 0 || room.Status != LiveRoomStatus.Initiating)
  161. {
  162. if (existedRoom != null)
  163. {
  164. rtcRoomId = existedRoom.RtcRoomId;
  165. existedLiveRooms = existedRoom.GetRoomMemberInfos() ?? new List<LiveMemberDTO>();
  166. Logger.WriteLineInfo($"RTCService InitiateAsync 3, existedRoom:{JsonConvert.SerializeObject(existedRoom)}");
  167. }
  168. else
  169. {
  170. var getRoomIdRequest = new GetRoomIdRequest
  171. {
  172. UniqueId = roomId
  173. };
  174. var getRoomIdResult = await GetRoomIdAsync(getRoomIdRequest);
  175. rtcRoomId = (int)getRoomIdResult.RoomId;
  176. Logger.WriteLineInfo($"RTCService InitiateAsync 4, getRoomIdResult:{JsonConvert.SerializeObject(getRoomIdResult)}");
  177. }
  178. }
  179. var deviceTokenInfo = CacheMaintenance.Instance.Get<ITokensManager>().Where(x => x.ClientId == deviceCode).FirstOrDefault();
  180. if (deviceTokenInfo != null && deviceTokenInfo.IsOnline && deviceTokenInfo.IsOldPlatform)
  181. {
  182. await _deviceForwardService.GetDeviceVideoInfosAsync(new GetDeviceVideoInfosRequest { DeviceCode = deviceCode });
  183. }
  184. var appId = TRTCHelper.GetAppId();
  185. room.Initiate(initiatorCode, rtcRoomId, appId, request.LoginSource, true, existedLiveRooms);
  186. if (room.UserInfos != null && room.UserInfos.Any())
  187. {
  188. foreach (var user in room.UserInfos)
  189. {
  190. _rtcRoomManager.AddToCheckTimeoutSequence(roomId, user.Code, user.Name);
  191. }
  192. }
  193. Logger.WriteLineInfo($"RTCService InitiateAsync, roomId:{room.LiveRoomCode}, name:{room.Name}, rtcRoomId:{room.RtcRoomId}, initiator:{room.Initiator?.Name}");
  194. var liveRoom = await AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest { LiveRoom = room });
  195. var syncInfo = new InitiateLiveConsultationJson
  196. {
  197. ConsultationRecordCode = liveRoom.LiveRoomCode,
  198. RoomCode = liveRoom.LiveRoomCode,
  199. InitatorCode = initiatorCode,
  200. OperatorCode = initiatorCode,
  201. LoginSource = request.LoginSource,
  202. IntegerRoomId = liveRoom.RtcRoomId,
  203. DeviceCode = deviceCode,
  204. LiveMemberInfos = room.GetRoomMemberInfos(),
  205. };
  206. await SyncToMasterAsync(SyncTypeEnum.Initiate, roomId, liveRoom.Name, syncInfo);
  207. return liveRoom;
  208. }
  209. /// <summary>
  210. /// 同意
  211. /// </summary>
  212. /// <returns></returns>
  213. public async Task<LiveMemberDTO> AcceptAsync(AcceptRequest request)
  214. {
  215. var roomId = request.LiveRoomCode;
  216. var userCode = request.UserCode;
  217. var room = _rtcRoomManager.Get(roomId);
  218. LiveMemberDTO accepter = null;
  219. if (!string.IsNullOrEmpty(request.DeviceCode))
  220. {
  221. accepter = room.AcceptDevice(request.DeviceCode, request.UserCode, new List<LiveMemberDTO>());
  222. }
  223. else
  224. {
  225. accepter = room.Accept(userCode, request.LoginSource, new List<LiveMemberDTO>());
  226. }
  227. Logger.WriteLineInfo($"RTCService AcceptAsync, roomId:{room.LiveRoomCode}, name:{room.Name}, accepter:{accepter.Name}");
  228. await AddOrUpdateLiveMemberAsync(roomId, accepter);
  229. await AppletLiveMemberAcceptAsync(roomId, userCode);
  230. var syncInfo = new BaseLiveConsultationJson
  231. {
  232. ConsultationRecordCode = room.LiveRoomCode,
  233. RoomCode = room.LiveRoomCode,
  234. InitatorCode = room.Initiator?.Code,
  235. OperatorCode = userCode,
  236. LoginSource = request.LoginSource,
  237. LiveMemberInfos = room.GetRoomMemberInfos(),
  238. };
  239. if (!string.IsNullOrEmpty(request.DeviceCode))
  240. {
  241. syncInfo.OperatorCode = request.DeviceCode;
  242. syncInfo.ReferCodes = new List<string>() { request.UserCode };
  243. await SyncToMasterAsync(SyncTypeEnum.AcceptDevice, roomId, room.Name, syncInfo);
  244. }
  245. else
  246. {
  247. await SyncToMasterAsync(SyncTypeEnum.Accept, roomId, room.Name, syncInfo);
  248. }
  249. return accepter;
  250. }
  251. /// <summary>
  252. /// 拒绝
  253. /// </summary>
  254. /// <returns></returns>
  255. public async Task<bool> RejectAsync(RejectRequest request)
  256. {
  257. var roomId = request.LiveRoomCode;
  258. var userCode = request.UserCode;
  259. var room = _rtcRoomManager.Get(roomId);
  260. var rejecter = room.Reject(userCode);
  261. Logger.WriteLineInfo($"RTCService RejectAsync, roomId:{room.LiveRoomCode}, name:{room.Name}, accepter:{rejecter.Name}");
  262. await AddOrUpdateLiveMemberAsync(roomId, rejecter);
  263. var syncInfo = new BaseLiveConsultationJson
  264. {
  265. ConsultationRecordCode = room.LiveRoomCode,
  266. RoomCode = room.LiveRoomCode,
  267. InitatorCode = room.Initiator?.Code,
  268. OperatorCode = userCode,
  269. };
  270. await SyncToMasterAsync(SyncTypeEnum.Reject, roomId, room.Name, syncInfo);
  271. return true;
  272. }
  273. /// <summary>
  274. /// 取消直播
  275. /// </summary>
  276. /// <returns></returns>
  277. public async Task<bool> CancelAsync(CancelRequest request)
  278. {
  279. var roomId = request.LiveRoomCode;
  280. var userCode = request.UserCode;
  281. var room = _rtcRoomManager.Get(roomId);
  282. room.CancelInitiate();
  283. Logger.WriteLineInfo($"RTCService CancelAsync, roomId:{room.LiveRoomCode}, name:{room.Name}");
  284. await AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest { LiveRoom = room });
  285. var syncInfo = new BaseLiveConsultationJson
  286. {
  287. ConsultationRecordCode = room.LiveRoomCode,
  288. RoomCode = room.LiveRoomCode,
  289. InitatorCode = room.InitiatorCode,
  290. OperatorCode = userCode,
  291. };
  292. await SyncToMasterAsync(SyncTypeEnum.CancelInitiate, roomId, room.Name, syncInfo);
  293. return true;
  294. }
  295. /// <summary>
  296. /// 切换是否开启静音
  297. /// </summary>
  298. /// <returns></returns>
  299. public async Task<bool> ChangeMuteOpenedAsync(ChangeMuteOpenedRequest request)
  300. {
  301. var roomId = request.LiveRoomCode;
  302. var userCode = request.UserCode;
  303. var room = _rtcRoomManager.Get(roomId);
  304. var liveMember = room.ChangeMuteState(userCode, request.MuteOpened);
  305. Logger.WriteLineInfo($"RTCService ChangeMuteOpenedAsync, roomId:{room.LiveRoomCode}, name:{room.Name}, user:{liveMember.Name}");
  306. await AddOrUpdateLiveMemberAsync(roomId, liveMember);
  307. var syncInfo = new MuteLiveConsultationJson
  308. {
  309. ConsultationRecordCode = room.LiveRoomCode,
  310. RoomCode = room.LiveRoomCode,
  311. InitatorCode = room.InitiatorCode,
  312. OperatorCode = userCode,
  313. Mute = request.MuteOpened
  314. };
  315. await SyncToMasterAsync(SyncTypeEnum.ChangeMuteState, roomId, room.Name, syncInfo);
  316. return await Task.FromResult(true);
  317. }
  318. /// <summary>
  319. /// 切换是否开启视频
  320. /// </summary>
  321. /// <returns></returns>
  322. public async Task<bool> ChangeVideoOpenedAsync(ChangeVideoOpenedRequest request)
  323. {
  324. var roomId = request.LiveRoomCode;
  325. var userCode = request.UserCode;
  326. var room = _rtcRoomManager.Get(roomId);
  327. var liveMember = room.ChangeVideoOpenState(userCode, request.VideoOpened);
  328. Logger.WriteLineInfo($"RTCService ChangeVideoOpenedAsync, roomId:{room.LiveRoomCode}, name:{room.Name}, user:{liveMember.Name}");
  329. await AddOrUpdateLiveMemberAsync(roomId, liveMember);
  330. var syncInfo = new SwitchLiveConsultationVideoJson
  331. {
  332. ConsultationRecordCode = room.LiveRoomCode,
  333. RoomCode = room.LiveRoomCode,
  334. InitatorCode = room.InitiatorCode,
  335. OperatorCode = userCode,
  336. VideoOpend = request.VideoOpened,
  337. };
  338. await SyncToMasterAsync(SyncTypeEnum.ChangeVideoOpenState, roomId, room.Name, syncInfo);
  339. return await Task.FromResult(true);
  340. }
  341. /// <summary>
  342. /// 离开房间
  343. /// </summary>
  344. /// <returns></returns>
  345. public async Task<bool> LeaveAsync(LeaveRequest request)
  346. {
  347. var roomId = request.LiveRoomCode;
  348. var userCode = request.UserCode;
  349. var room = _rtcRoomManager.Get(roomId);
  350. LiveMemberDTO liveMember;
  351. if (!string.IsNullOrEmpty(request.DeviceCode))
  352. {
  353. liveMember = room.DeviceLeave(request.DeviceCode, request.UserCode);
  354. }
  355. else
  356. {
  357. liveMember = room.Leave(userCode, request.Closed);
  358. }
  359. var joindMembers = room.UserInfos.Where(x => x.Status == LiveMemberStatus.Joined)?.ToList() ?? new List<LiveMemberDTO>();
  360. Logger.WriteLineInfo($"RTCService LeaveAsync, closed:{request.Closed.ToString()}, roomId:{room.LiveRoomCode}, name:{room.Name}, user:{liveMember.Name}, joinedMembers:{string.Join(";", joindMembers.Select(x => x.Name))}");
  361. await AddOrUpdateLiveMemberAsync(roomId, liveMember);
  362. if (request.Closed)
  363. {
  364. await AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest { LiveRoom = room });
  365. await AppletLiveMemberLeaveAsync(roomId);
  366. }
  367. var syncInfo = new LeaveLiveConsultationJson
  368. {
  369. ConsultationRecordCode = room.LiveRoomCode,
  370. RoomCode = room.LiveRoomCode,
  371. InitatorCode = room.InitiatorCode,
  372. OperatorCode = userCode,
  373. Closed = request.Closed
  374. };
  375. if (!string.IsNullOrEmpty(request.DeviceCode))
  376. {
  377. //删掉超声机
  378. RemoveLiveMemberAsync(roomId, liveMember, room.InitiatorCode);
  379. Logger.WriteLineInfo($"RtcRoom LeaveAsync 1, roomId:{roomId}, room:{ JsonConvert.SerializeObject(room) }");
  380. room.DeviceInfos.Remove(liveMember);
  381. Logger.WriteLineInfo($"RtcRoom LeaveAsync 2, roomId:{roomId}, room:{ JsonConvert.SerializeObject(room) }");
  382. syncInfo.OperatorCode = request.DeviceCode;
  383. syncInfo.ReferCodes = new List<string>() { request.UserCode };
  384. await SyncToMasterAsync(SyncTypeEnum.LeaveDevice, roomId, room.Name, syncInfo);
  385. }
  386. else
  387. {
  388. await SyncToMasterAsync(SyncTypeEnum.Leave, roomId, room.Name, syncInfo);
  389. }
  390. return await Task.FromResult(true);
  391. }
  392. /// <summary>
  393. /// 关闭直播
  394. /// </summary>
  395. /// <returns></returns>
  396. public async Task<bool> CloseAsync(CloseRequest request)
  397. {
  398. var roomId = request.LiveRoomCode;
  399. var userCode = request.UserCode;
  400. var room = _rtcRoomManager.Get(roomId);
  401. room.Close();
  402. Logger.WriteLineInfo($"RTCService CloseAsync, roomId:{room.LiveRoomCode}, name:{room.Name}");
  403. await AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest { LiveRoom = room });
  404. await AppletLiveMemberLeaveAsync(roomId);
  405. var syncInfo = new BaseLiveConsultationJson
  406. {
  407. ConsultationRecordCode = room.LiveRoomCode,
  408. RoomCode = room.LiveRoomCode,
  409. InitatorCode = room.InitiatorCode,
  410. OperatorCode = userCode,
  411. };
  412. await SyncToMasterAsync(SyncTypeEnum.Close, roomId, room.Name, syncInfo);
  413. return await Task.FromResult(true);
  414. }
  415. private bool CloseRtcRoom(string roomId, string operatorCode)
  416. {
  417. try
  418. {
  419. var room = _rtcRoomManager.Get(roomId);
  420. if (room != null && room.Status == LiveRoomStatus.Initiating)
  421. {
  422. room.Close();
  423. var appletLiveMemberLeaveResult = AppletLiveMemberLeaveAsync(roomId).Result;
  424. Logger.WriteLineInfo($"RTCService CloseAsync, roomId:{room.LiveRoomCode}, name:{room.Name}");
  425. var updateLiveRoomResult = AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest { LiveRoom = room }).Result;
  426. var syncInfo = new BaseLiveConsultationJson
  427. {
  428. ConsultationRecordCode = room.LiveRoomCode,
  429. RoomCode = room.LiveRoomCode,
  430. InitatorCode = room.InitiatorCode,
  431. OperatorCode = operatorCode,
  432. };
  433. SyncToMasterAsync(SyncTypeEnum.Close, roomId, room.Name, syncInfo);
  434. }
  435. }
  436. catch (Exception ex)
  437. {
  438. Logger.WriteLineWarn($"RtcService CloseRtcRoom err, roomId:{roomId}, ex:{ex}");
  439. }
  440. return true;
  441. }
  442. /// <summary>
  443. /// 发送白板数据
  444. /// </summary>
  445. /// <returns></returns>
  446. public async Task<bool> SendBoardDataAsync(SendBoardDataRequest request)
  447. {
  448. var roomId = request.LiveRoomCode;
  449. var userCode = request.UserCode;
  450. var room = _rtcRoomManager.Get(roomId);
  451. var interactiveTime = DateTime.UtcNow;
  452. room.SendBoardData(userCode, request.BoardData, interactiveTime, request.IsClear);
  453. var syncInfo = new SendInteractiveBoardDataConsultationJson
  454. {
  455. ConsultationRecordCode = room.LiveRoomCode,
  456. RoomCode = room.LiveRoomCode,
  457. InitatorCode = room.InitiatorCode,
  458. OperatorCode = userCode,
  459. UserCode = userCode,
  460. IsClear = request.IsClear,
  461. BoardData = request.BoardData,
  462. InteractiveTime = interactiveTime,
  463. };
  464. await SyncToMasterAsync(SyncTypeEnum.SendInteractiveBoardData, roomId, room.Name, syncInfo);
  465. return await Task.FromResult(true);
  466. }
  467. /// <summary>
  468. /// 进入房间-心跳
  469. /// </summary>
  470. /// <returns></returns>
  471. public async Task<bool> HeartRateJoinedAsync(HeartRateJoinRequest request)
  472. {
  473. var roomId = request.LiveRoomCode;
  474. var userCode = request.UserCode;
  475. var room = _rtcRoomManager.Get(roomId);
  476. var liveMember = room.HeartRateJoin(userCode);
  477. Logger.WriteLineInfo($"RTCService HeartRateJoinedAsync, roomId:{room.LiveRoomCode}, name:{room.Name}, user:{liveMember.Name}");
  478. await AddOrUpdateLiveMemberAsync(roomId, liveMember);
  479. await AppletLiveMemberAcceptAsync(roomId, userCode);
  480. var syncInfo = new BaseLiveConsultationJson
  481. {
  482. ConsultationRecordCode = room.LiveRoomCode,
  483. RoomCode = room.LiveRoomCode,
  484. InitatorCode = room.InitiatorCode,
  485. OperatorCode = userCode,
  486. };
  487. await SyncToMasterAsync(SyncTypeEnum.HeartRateJoin, roomId, room.Name, syncInfo);
  488. return await Task.FromResult(true);
  489. }
  490. /// <summary>
  491. /// 网络质量不佳
  492. /// </summary>
  493. /// <returns></returns>
  494. public async Task<bool> NetworkErrorAsync(NetworkErrorRequest request)
  495. {
  496. var roomId = request.LiveRoomCode;
  497. var userCode = request.UserCode;
  498. var room = _rtcRoomManager.Get(roomId);
  499. room.NetworkErr(userCode);
  500. var syncInfo = new BaseLiveConsultationJson
  501. {
  502. ConsultationRecordCode = room.LiveRoomCode,
  503. RoomCode = room.LiveRoomCode,
  504. InitatorCode = room.InitiatorCode,
  505. OperatorCode = userCode,
  506. };
  507. await SyncToMasterAsync(SyncTypeEnum.NetworkErr, roomId, room.Name, syncInfo);
  508. return await Task.FromResult(true);
  509. }
  510. /// <summary>
  511. /// 离开房间-心跳
  512. /// </summary>
  513. /// <returns></returns>
  514. public async Task<bool> HeartRateLeavedAsync(HeartRateLeavedRequest request)
  515. {
  516. var roomId = request.LiveRoomCode;
  517. var userCode = request.UserCode;
  518. var room = _rtcRoomManager.Get(roomId);
  519. var liveMember = room.HeartRateLeave(userCode);
  520. Logger.WriteLineInfo($"RTCService HeartRateLeavedAsync, roomId:{room.LiveRoomCode}, name:{room.Name}, user:{liveMember.Name}");
  521. await AddOrUpdateLiveMemberAsync(roomId, liveMember);
  522. var syncInfo = new BaseLiveConsultationJson
  523. {
  524. ConsultationRecordCode = room.LiveRoomCode,
  525. RoomCode = room.LiveRoomCode,
  526. InitatorCode = room.InitiatorCode,
  527. OperatorCode = userCode,
  528. };
  529. await SyncToMasterAsync(SyncTypeEnum.HeartRateLeave, roomId, room.Name, syncInfo);
  530. return await Task.FromResult(true);
  531. }
  532. /// <summary>
  533. /// 直播中邀请
  534. /// </summary>
  535. /// <returns></returns>
  536. public async Task<bool> InviteInAsync(InviteInRequest request)
  537. {
  538. var roomId = request.LiveRoomCode;
  539. var userCode = request.UserCode;
  540. var room = _rtcRoomManager.Get(roomId);
  541. room.InviteIn(userCode, request.InviteCodes);
  542. if (request.InviteCodes != null && request.InviteCodes.Any())
  543. {
  544. var inviteUsers = await _userDBService.FindUserListByUserCodesAsync(request.InviteCodes);
  545. if (inviteUsers != null && inviteUsers.Any())
  546. {
  547. foreach (var user in inviteUsers)
  548. {
  549. _rtcRoomManager.AddToCheckTimeoutSequence(roomId, user.UserCode, user.DisplayName);
  550. }
  551. }
  552. }
  553. Logger.WriteLineInfo($"RTCService InviteInAsync, roomId:{room.LiveRoomCode}, name:{room.Name},OperationCode:{userCode}, inviteCodes:{string.Join(",", request.InviteCodes)}");
  554. var syncInfo = new InviteInLiveConsultationJson
  555. {
  556. ConsultationRecordCode = roomId,
  557. RoomCode = roomId,
  558. InitatorCode = room.Initiator?.Code,
  559. OperatorCode = userCode,
  560. UserCodes = request.InviteCodes.ToList(),
  561. };
  562. await SyncToMasterAsync(SyncTypeEnum.InviteIn, roomId, room.Name, syncInfo);
  563. return await Task.FromResult(true);
  564. }
  565. /// <summary>
  566. /// 取消直播中邀请
  567. /// </summary>
  568. /// <returns></returns>
  569. public async Task<bool> CancelInviteInAsync(CancelInviteInRequest request)
  570. {
  571. var roomId = request.LiveRoomCode;
  572. var userCode = request.UserCode;
  573. var room = _rtcRoomManager.Get(roomId);
  574. room.CancelInviteIn(userCode, request.InviteCodes);
  575. Logger.WriteLineInfo($"RTCService CancelInviteInAsync, roomId:{room.LiveRoomCode}, name:{room.Name}");
  576. var syncInfo = new CancelInviteInLiveConsultationJson
  577. {
  578. ConsultationRecordCode = roomId,
  579. RoomCode = roomId,
  580. InitatorCode = room.Initiator?.Code,
  581. OperatorCode = userCode,
  582. UserCodes = request.InviteCodes.ToList(),
  583. };
  584. await SyncToMasterAsync(SyncTypeEnum.CancelInviteIn, roomId, room.Name, syncInfo);
  585. return await Task.FromResult(true);
  586. }
  587. /// <summary>
  588. /// 直播中加入房间
  589. /// </summary>
  590. /// <returns></returns>
  591. public async Task<LiveMemberDTO> JoinInAsync(JoinInRequest request)
  592. {
  593. var roomId = request.LiveRoomCode;
  594. var userCode = request.UserCode;
  595. var room = _rtcRoomManager.Get(roomId);
  596. var liveMember = room.JoinIn(userCode, request.SortLevel, request.LoginSource, new List<LiveMemberDTO>());
  597. Logger.WriteLineInfo($"RTCService JoinInAsync, roomId:{room.LiveRoomCode}, name:{room.Name}, user:{liveMember.Name}");
  598. await AddOrUpdateLiveMemberAsync(roomId, liveMember);
  599. var syncInfo = new JoinInConsultationJson
  600. {
  601. ConsultationRecordCode = roomId,
  602. RoomCode = roomId,
  603. InitatorCode = room.Initiator?.Code,
  604. OperatorCode = userCode,
  605. LoginSource = request.LoginSource,
  606. SortLevel = request.SortLevel,
  607. LiveMemberInfos = room.GetRoomMemberInfos(),
  608. };
  609. await SyncToMasterAsync(SyncTypeEnum.AcceptIn, roomId, room.Name, syncInfo);
  610. return await Task.FromResult(liveMember);
  611. }
  612. /// <summary>
  613. /// 拒绝直播中邀请
  614. /// </summary>
  615. /// <returns></returns>
  616. public async Task<bool> RejectInviteAsync(RejectInviteRequest request)
  617. {
  618. var roomId = request.LiveRoomCode;
  619. var userCode = request.UserCode;
  620. var room = _rtcRoomManager.Get(roomId);
  621. room.RejectIn(userCode);
  622. var syncInfo = new BaseLiveConsultationJson
  623. {
  624. ConsultationRecordCode = roomId,
  625. RoomCode = roomId,
  626. InitatorCode = room.Initiator?.Code,
  627. OperatorCode = userCode,
  628. };
  629. await SyncToMasterAsync(SyncTypeEnum.RejectIn, roomId, room.Name, syncInfo);
  630. return await Task.FromResult(true);
  631. }
  632. /// <summary>
  633. /// 加入房间
  634. /// </summary>
  635. /// <returns></returns>
  636. public async Task<bool> AgreeInAsync(AgreeInRequest request)
  637. {
  638. var roomId = request.LiveRoomCode;
  639. var userCode = request.UserCode;
  640. var room = _rtcRoomManager.Get(roomId);
  641. var liveMember = room.AcceptIn(userCode, request.SortLevel, new List<LiveMemberDTO>());
  642. Logger.WriteLineInfo($"RTCService AgreeInAsync, roomId:{room.LiveRoomCode}, name:{room.Name}, user:{liveMember.Name}");
  643. await AddOrUpdateLiveMemberAsync(roomId, liveMember);
  644. var syncInfo = new AgreeInConsultationJson
  645. {
  646. ConsultationRecordCode = roomId,
  647. RoomCode = roomId,
  648. InitatorCode = room.Initiator?.Code,
  649. OperatorCode = userCode,
  650. SortLevel = request.SortLevel,
  651. LiveMemberInfos = room.GetRoomMemberInfos(),
  652. };
  653. await SyncToMasterAsync(SyncTypeEnum.Agree, roomId, room.Name, syncInfo);
  654. return await Task.FromResult(true);
  655. }
  656. /// <summary>
  657. /// 切换房间
  658. /// </summary>
  659. /// <returns></returns>
  660. public async Task<bool> ChangeRoomAsync(ChangeRoomRequest request)
  661. {
  662. var roomId = request.OriginalCode;
  663. var currentRoomId = request.CurrentCode;
  664. var userCode = request.UserCode;
  665. var original = _rtcRoomManager.Get(roomId);
  666. var current = _rtcRoomManager.Get(currentRoomId);
  667. original.ChangeRoom(userCode, current, original.GetRoomMemberInfos());
  668. await AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest { LiveRoom = original });
  669. await AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest { LiveRoom = current });
  670. var syncInfo = new ChangeConsultationJson
  671. {
  672. ConsultationRecordCode = original.LiveRoomCode,
  673. RoomCode = original.LiveRoomCode,
  674. InitatorCode = original.Initiator?.Code,
  675. OperatorCode = userCode,
  676. ReferCodes = new List<string> { roomId, currentRoomId },
  677. OriginalRoomId = roomId,
  678. CurrentRoomId = currentRoomId,
  679. LiveMemberInfos = current.GetRoomMemberInfos(),
  680. };
  681. await SyncToMasterAsync(SyncTypeEnum.ChangeRoom, roomId, original.Name, syncInfo);
  682. return await Task.FromResult(true);
  683. }
  684. /// <summary>
  685. /// 切换调参状态
  686. /// </summary>
  687. /// <returns></returns>
  688. public async Task<bool> ChangeControllingStateAsync(ChangeControllingStateRequest request)
  689. {
  690. var userCode = request.UserCode;
  691. RtcRoom room = null;
  692. if (!string.IsNullOrWhiteSpace(request.LiveRoomCode))
  693. {
  694. room = _rtcRoomManager.Get(request.LiveRoomCode);
  695. }
  696. else
  697. {
  698. room = _rtcRoomManager.GetRoomInfoByConditionCode(request.UserCode, request.DeviceCode);
  699. }
  700. if (room != null)
  701. {
  702. var liveMember = room.ChangeControllingParameterState(userCode, request.IsControllingParameter);
  703. await AddOrUpdateLiveMemberAsync(room.LiveRoomCode, liveMember);
  704. var syncInfo = new ControllingParameterInLiveConsultationJson
  705. {
  706. ConsultationRecordCode = room.LiveRoomCode,
  707. RoomCode = room.LiveRoomCode,
  708. InitatorCode = room.Initiator?.Code,
  709. OperatorCode = userCode,
  710. IsControllingParameter = request.IsControllingParameter
  711. };
  712. await SyncToMasterAsync(SyncTypeEnum.ChangeControllingParameter, room.LiveRoomCode, room.Name, syncInfo);
  713. return await Task.FromResult(true);
  714. }
  715. return await Task.FromResult(false);
  716. }
  717. /// <summary>
  718. /// 记录直播观看人信息
  719. /// </summary>
  720. /// <param name="request">请求实体</param>
  721. /// <returns>false</returns>
  722. public async Task<bool> SaveViewerAsync(SaveViewerRequest request)
  723. {
  724. var roomId = request.LiveRoomCode;
  725. var userCode = request.UserCode;
  726. var room = _rtcRoomManager.Get(roomId);
  727. if (room != null)
  728. {
  729. room.AddOrUpdateViewer(request.UserCode, request.UserName);
  730. await _liveRoomDBService.AddOrUpdateViewerAsync(new AddOrUpdateViewerDBRequest
  731. {
  732. LiveRoomCode = request.LiveRoomCode,
  733. UserCode = request.UserCode,
  734. UserName = request.UserName,
  735. });
  736. var syncInfo = new BaseLiveConsultationJson
  737. {
  738. ConsultationRecordCode = roomId,
  739. RoomCode = roomId,
  740. InitatorCode = room.Initiator?.Code,
  741. OperatorCode = userCode
  742. };
  743. await SyncToMasterAsync(SyncTypeEnum.SaveViewer, roomId, room.Name, syncInfo);
  744. return await Task.FromResult(true);
  745. }
  746. return await Task.FromResult(false);
  747. }
  748. /// <summary>
  749. /// 删除直播观看人信息
  750. /// </summary>
  751. /// <param name="request">请求实体</param>
  752. /// <returns>false</returns>
  753. public async Task<bool> RemoveViewerAsync(RemoveViewerRequest request)
  754. {
  755. var roomId = request.LiveRoomCode;
  756. var userCode = request.UserCode;
  757. var room = _rtcRoomManager.Get(roomId);
  758. if (room != null)
  759. {
  760. room.DeleteViewer(request.UserCode);
  761. await _liveRoomDBService.DeleteViewerAsync(new DeleteViewerDBRequest
  762. {
  763. LiveRoomCode = request.LiveRoomCode,
  764. UserCode = request.UserCode,
  765. });
  766. var syncInfo = new BaseLiveConsultationJson
  767. {
  768. ConsultationRecordCode = roomId,
  769. RoomCode = roomId,
  770. InitatorCode = room.Initiator?.Code,
  771. OperatorCode = userCode
  772. };
  773. await SyncToMasterAsync(SyncTypeEnum.DeleteViewer, roomId, room.Name, syncInfo);
  774. return await Task.FromResult(true);
  775. }
  776. return await Task.FromResult(false);
  777. }
  778. /// <summary>
  779. /// 查询用户在房间的状态
  780. /// </summary>
  781. /// <param name="request">请求实体</param>
  782. /// <returns>用户房间信息</returns>
  783. public async Task<LiveMemberDTO> GetLiveMemberByRoomIdAsync(GetLiveMemberByRoomIdRequest request)
  784. {
  785. var userCode = request.UserCode;
  786. var roomId = request.LiveRoomCode;
  787. LiveMemberDTO liveMember = null;
  788. var room = _rtcRoomManager.Get(roomId);
  789. if (room != null && room.UserInfos != null && room.UserInfos.Any(x => x.Code == userCode && x.Status == LiveMemberStatus.Joined))
  790. {
  791. liveMember = room.UserInfos.FirstOrDefault(x => x.Code == userCode);
  792. }
  793. return await Task.FromResult(liveMember);
  794. }
  795. private RtcRoom GetLiveRoomAsync(string liveRoomCode)
  796. {
  797. var getLiveRoomRequest = new GetLiveRoomByCodeDBRequest
  798. {
  799. LiveRoomCode = liveRoomCode,
  800. };
  801. var liveRoom = _liveRoomDBService.GetLiveRoomByCodeAsync(getLiveRoomRequest).Result;
  802. if (!string.IsNullOrWhiteSpace(liveRoom?.LiveRoomCode))
  803. {
  804. return new RtcRoom(liveRoom.LiveRoomCode, liveRoom.Name, liveRoom.RtcRoomId, liveRoom.SdkAppId, liveRoom.InitiatorCode
  805. , liveRoom.Status, liveRoom.BusinessModule, liveRoom.RelatedCode
  806. , liveRoom.UserInfos, liveRoom.DeviceInfos, liveRoom.ViewerInfos);
  807. }
  808. return null;
  809. }
  810. private async Task AddOrUpdateLiveMemberAsync(string liveRoomCode, LiveMemberDTO liveMember)
  811. {
  812. var saveLiveMemberRequest = new AddOrUpdateLiveMemberDBRequest
  813. {
  814. LiveRoomCode = liveRoomCode,
  815. MemberCode = liveMember.Code,
  816. MemberType = liveMember.MemberType,
  817. Name = liveMember.Name,
  818. HeadImageToken = liveMember.HeadImageToken,
  819. Status = liveMember.Status,
  820. MuteOpened = liveMember.MuteOpened,
  821. VideoOpened = liveMember.VideoOpened,
  822. IsControllingParameter = liveMember.IsControllingParameter,
  823. SortLevel = liveMember.SortLevel,
  824. LoginSource = liveMember.LoginSource,
  825. VideoDeviceInfos = liveMember.VideoDeviceInfos,
  826. InviterCode = liveMember.InviterCode ?? "",
  827. BackgroundRole = liveMember.BackgroundRole
  828. };
  829. if (liveMember.Status == LiveMemberStatus.Joined || liveMember.Status == LiveMemberStatus.Left)
  830. {
  831. saveLiveMemberRequest.Status = LiveMemberStatus.Accepted;
  832. }
  833. if (liveMember.LiveData != null)
  834. {
  835. var liveData = liveMember.LiveData;
  836. saveLiveMemberRequest.LiveData = new LiveDataDTO
  837. {
  838. Width = liveData.Width,
  839. Height = liveData.Height,
  840. RtmpPullUrl = liveData.RtmpPullUrl,
  841. RtmpPushUrl = liveData.RtmpPushUrl,
  842. HlsPullUrl = liveData.HlsPullUrl,
  843. HttpPullUrl = liveData.HttpPullUrl,
  844. };
  845. }
  846. await _liveRoomDBService.AddOrUpdateLiveMemberAsync(saveLiveMemberRequest);
  847. }
  848. /// <summary>
  849. /// 移除成员
  850. /// </summary>
  851. /// <returns></returns>
  852. private async Task RemoveLiveMemberAsync(string liveRoomCode, LiveMemberDTO liveMember, string initiatorCode)
  853. {
  854. if (initiatorCode != liveMember.Code)
  855. {
  856. var removeLiveMemberRequest = new RemoveLiveMemberDBRequest
  857. {
  858. LiveRoomCode = liveRoomCode,
  859. MemberCode = liveMember.Code,
  860. MemberType = liveMember.MemberType
  861. };
  862. await _liveRoomDBService.RemoveLiveMemberAsync(removeLiveMemberRequest);
  863. }
  864. }
  865. private bool DeviceInitiatingRoomExisted(string deviceCode, string excludeRoomId)
  866. {
  867. return _rtcRoomManager.GetInitiatingRoomByDeviceCode(deviceCode, excludeRoomId) != null;
  868. }
  869. /// <summary>
  870. /// 设备直播中加入房间
  871. /// </summary>
  872. /// <returns></returns>
  873. public async Task<LiveMemberDTO> DeviceJoinInAsync(DeviceJoinInRequest request)
  874. {
  875. var roomId = request.LiveRoomCode;
  876. var deviceCode = request.DeviceCode;
  877. var room = _rtcRoomManager.Get(roomId);
  878. var deviceTokenInfo = CacheMaintenance.Instance.Get<ITokensManager>().Where(x => x.ClientId == deviceCode).FirstOrDefault();
  879. if (deviceTokenInfo != null && deviceTokenInfo.IsOnline && deviceTokenInfo.IsOldPlatform)
  880. {
  881. await _deviceForwardService.GetDeviceVideoInfosAsync(new GetDeviceVideoInfosRequest { DeviceCode = deviceCode });
  882. }
  883. var liveMember = room.DeviceJoinIn(deviceCode, new List<LiveMemberDTO>());
  884. Logger.WriteLineInfo($"RTCService DeviceJoinInAsync, roomId:{room.LiveRoomCode}, name:{room.Name}, user:{liveMember.Name}");
  885. await AddOrUpdateLiveMemberAsync(roomId, liveMember);
  886. var syncInfo = new JoinInConsultationJson
  887. {
  888. ConsultationRecordCode = roomId,
  889. RoomCode = roomId,
  890. InitatorCode = room.Initiator?.Code,
  891. OperatorCode = deviceCode,
  892. LiveMemberInfos = room.GetRoomMemberInfos(),
  893. };
  894. await SyncToMasterAsync(SyncTypeEnum.DeviceAcceptIn, roomId, room.Name, syncInfo);
  895. return await Task.FromResult(liveMember);
  896. }
  897. /// <summary>
  898. /// 开启关闭共享信息
  899. /// </summary>
  900. /// <param name="request">请求实体</param>
  901. /// <returns>true</returns>
  902. /// <show>false</show>
  903. public async Task<bool> ChangedShareInfoAsync(ChangedShareInfoRequest request)
  904. {
  905. var roomId = request.LiveRoomCode;
  906. var room = _rtcRoomManager.Get(roomId);
  907. var result = room.SetShareInfo(request.OperatorCode, request.ShareInfo);
  908. Logger.WriteLineInfo($"RTCService ChangedShareInfoAsync, roomId:{room.LiveRoomCode}, name:{room.Name},");
  909. room.ShareInfo = request.ShareInfo;
  910. var liveRoom = await AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest { LiveRoom = room });
  911. var syncInfo = new ChangedShareInfoCourseJson
  912. {
  913. ConsultationRecordCode = liveRoom.LiveRoomCode,
  914. RoomCode = liveRoom.LiveRoomCode,
  915. InitatorCode = request.OperatorCode,
  916. OperatorCode = request.OperatorCode,
  917. // LoginSource = request.LoginSource,
  918. CurrentShareState = (int)request.ShareInfo?.CurrentShareState,
  919. CurrentShareType = (int)request.ShareInfo?.CurrentShareType,
  920. CurrentShareMemberCode = request.ShareInfo?.CurrentShareMemberCode,
  921. CurrentShareMemberName = request.ShareInfo?.CurrentShareMemberName,
  922. };
  923. await SyncToMasterAsync(SyncTypeEnum.SetShareInfo, roomId, liveRoom.Name, syncInfo);
  924. return await Task.FromResult(true);
  925. }
  926. }
  927. }