各设备类型的计数
根据代码系统里点播/观看人数的计数与关闭前是否查计数如下。一、各设备类型的计数关键字设备类型计数存储位置Redis / 字段 Key 格式计数值含义国标 GB28181Redis StringWVP_GB_PLAY_COUNT_{deviceId}逗号分隔的userId列表DJI 无人机Redis StringWVP_DJI_PLAY_COUNT_{droneSn}_{payloadIndex}逗号分隔的userId列表MeshT 单兵(onlineType3)Member 对象字段WS_MEMBER_ID_{memberId}内的demandList点播者 ID 列表非独立 PLAY_COUNT keyAndroid 终端(onlineType1)同上WS_MEMBER_ID_{memberId}→demandList同上主要维护状态关闭逻辑见下Web 终端(onlineType2)同上WS_MEMBER_ID_{memberId}→demandList同上副屏播放叠加层Redis StringscreenPlay_{userId}_{devId}JSON Setmain、secondary{uuid}、newScreen-{screenId}补充DJI 相关非人数计数live:{droneSn}:{payloadIndex}— 缓存 LiveDTO供多人复用流地址设备离线时会直接delete所有WVP_DJI_PLAY_COUNT_*不查人数无点播计数机制的设备窄带NARROWBAND、手环watch、账号类account等代码里没有对应的 PLAY_COUNT 逻辑。常量定义//统计点播国标的key public static final String WVP_GB_PLAY_COUNT WVP_GB_PLAY_COUNT_; // ... //统计点播DJI的key public static final String WVP_DJI_PLAY_COUNT WVP_DJI_PLAY_COUNT_;二、关闭前会查计数的设备1. 国标 GB28181 — 会查WVP_GB_PLAY_COUNT正常停止subPlayCount减人数后若为空且checkPlanStopState(deviceId)为 true才发 BYE 真正关流录像计划closeGBPlayCmdplayCount为空才关强制停止deletePlayCount/playStopRea有计数才关注意普通 stop 接口里有if(true)接口层不真正关流但subPlayCount仍会更新计数并在人数为 0 时尝试关流。public void subPlayCount(String deviceId,String userId,String channelId){ String playKey VideoManagerConstants.WVP_GB_PLAY_COUNT deviceId; // ... if(sb.toString().isEmpty()){ boolean isOpen wvpRecordPlanService.checkPlanStopState(deviceId); if(isOpen) { redisTemplate.delete(playKey); // 发送 BYE 关闭点播 } } }2. DJI 无人机 — 会查WVP_DJI_PLAY_COUNTliveStopreducePlayCount后 0 直接返回不推live_stop_push 0 才真正关流liveStopByForce切镜头不查计数强制关并清 key录像计划closeDjiPlayCmd走liveStop同样受计数约束public HttpResultResponse liveStop(LiveTypeDTO liveParam) { int playCount reducePlayCount(liveParam); if(playCount 0){ return HttpResultResponse.success(); // 还有人看不关 } // 人数为 0才下发 live_stop_push3. MeshT 单兵 (onlineType3) — 会查demandListcloseCmd/closeForMeshTCmd从demandList移除当前点播者仅当列表为空才发CLOSE_PLAY_VIDEO_MSG若在录像计划时段内checkOpenRecord/checkPlanStopState可能跳过关闭清新双摄像头QX按镜头维度判断demandList是否还含该 cameraif(demandList null || demandList.size()0){ if(memberById.getOnlineType().equals(3)){ boolean isOpen checkOpenRecord(memberById.getId()); if(isOpen) { closePlayCmd(...); // 无人点播才关 } } }4. 副屏播放screenPlay— 会查screenPlay_{userId}_{devId}适用于 Mesh / MeshT / Web / Android 等走 WebRTC 点播且开了副屏的场景关闭入口行为主屏关闭/colse、/closeForMeshT先减mainSet 非空则不关副屏 WS 断开handleCloseScreenPlay最后一个secondary{uuid}才关/minusScreenNum最后一个newScreen-{screenId}才关String redisKey screenPlay_ demanderId _ providerId; // 有副屏播放时只减数set.size() 0 则 isNeedClose false if(isNeedClose){ playService.closeCmd(...); }5. Android / Web (onlineType1/2) — Service 层不查人数closeCmd里对非 MeshT设备会直接closePlayCmd不判断demandList是否还有人if(!memberById.getOnlineType().equals(3)){ closePlayCmd(eventId, demanderId, providerId,camera); // 总是关 }若开了副屏Controller 层的screenPlay_*计数仍会拦截过早关闭。Android 音视频通话closeAndroidCmd也没有类似点播人数计数。三、整体关系简图国标DJIMeshTAndroid/Web是否Set 非空Set 为空用户关闭点播设备类型?WVP_GB_PLAY_COUNT 减 1WVP_DJI_PLAY_COUNT 减 1demandList 移除Service 直接关 / 或经 screenPlay 拦截人数0?有 screenPlay 副屏?真正关流 BYE / live_stop_push仅减计数不关流四、一句话总结设备计数 Key关闭前查计数国标 GBWVP_GB_PLAY_COUNT_{deviceId}✅ 查人数为 0 非录像计划时段才关DJI 无人机WVP_DJI_PLAY_COUNT_{sn}_{payloadIndex}✅ 查liveStop强制关不查MeshT 单兵demandList在WS_MEMBER_ID_*内✅ 查Android / WebdemandList仅维护❌ Service 不查有副屏时查screenPlay_*副屏screenPlay_{userId}_{devId}✅ 查窄带 / 手环 / 账号无❌如需某条关闭链路的完整调用栈例如从前端live/index.vue到后端可以指定设备类型我帮你追一遍。目前在主屏通过拖曳视频到小窗口从而投屏过程中或者通过小窗口拖曳视频到主屏过程中后面那路播放的视频可能因为前者的播放而destroy了它的播放导致它播放时需要重新拉流 我现在想到了个好办法在这种交换的视频播放中为了保障后者的播放我提前进行一个后者播放的计数增加计数的逻辑参考上面我们对计数的总结我们可以在服务端写一个统一的计数增加的方法供前端调用 这样所有的destroy流程延用前面的当它想关闭推流时发现计数不为0而无法真正关闭而新增加的重复计数因为已经有了相同的的只会覆盖不会计数出错。这样是否完美解决了需要重新拉流的问题