Skip to content

视联网综合管理平台:视频流与智能交互复盘

项目概述

平台面向 安防/物联 场景,统一纳管摄像头资产,提供 实时/准实时预览、多路分屏、设备健康与告警、以及语音驱动的数字人指令入口。前端 Vue 3 + Ant Design Vue;后端 Spring Boot 负责设备元数据、信令转发、权限与对接第三方流媒体能力。


视频播放方案选型

业务上需在 延迟、服务端成本、浏览器兼容性 之间权衡。

方案协议路径延迟量级服务端成本适用场景
RTSP → WebSocket + MSE/JSMpeg拉流后转码/封装为浏览器可解格式低(常 <500ms 量级,视链路而定)CPU/带宽 占用高指挥调度、需近实时操作
HLS(m3u8 + ts/fMP4)CDN/边缘分发,浏览器 hls.js/播放器较高(数秒~十余秒 常见)边缘缓存友好回放、对延迟不敏感监控

RTSP → WS:前端可用 JSMpeg 等在 Canvas 上绘制 MPEG-TS 流;服务端需稳定转码/推流进程,并做好 并发路数与 CPU 容量规划。可参考站内整理:前端视频流播放实现;开源流媒体可参考 SRS

HLS:优先选成熟播放器(hls.js、Video.js、西瓜等);若需轻量封装可评估 EasyPlayer.js 等。无需自建转码时运维简单,但要接受 GOP 与分片 带来的固有延迟。

示例:hls.js 绑定 <video>(Vue3 中在 onMounted 里初始化)

ts
import Hls from 'hls.js';
import { onMounted, onUnmounted, ref, type Ref } from 'vue';

export function useHlsPlayer(videoRef: Ref<HTMLVideoElement | null>, src: string) {
  let hls: Hls | null = null;

  onMounted(() => {
    const el = videoRef.value;
    if (!el) return;
    if (Hls.isSupported()) {
      hls = new Hls({ enableWorker: true, lowLatencyMode: false });
      hls.loadSource(src);
      hls.attachMedia(el);
    } else if (el.canPlayType('application/vnd.apple.mpegurl')) {
      el.src = src; // Safari 原生 HLS
    }
  });

  onUnmounted(() => {
    hls?.destroy();
    hls = null;
  });
}

示例:JSMpeg + WebSocket(低延迟链路示意;URL 为后端转码后的 ws 地址)

ts
// npm包名一般为 jsmpeg,具体以项目依赖为准
import JSMpeg from 'jsmpeg';

export function openLowLatencyStream(canvas: HTMLCanvasElement, wsUrl: string) {
  return new JSMpeg.Player(wsUrl, { canvas });
}

数字人语音交互链路

将需求拆解为 采集 → 识别 → 语义/指令 → 执行与反馈(含视频)

  1. 音频采集
    浏览器侧使用 Recorder 等完成 录音、格式封装(mp3/wav)与可视化;注意 HTTPS 权限、采样率与码率 对识别准确率的影响。

  2. 语音识别(ASR)
    录音上传至后端或直接调用云厂商 一句话识别 / 实时识别 API,输出 稳定文本;需处理 噪声、方言、专有名词(摄像头编号、预置位名等)——可通过 热词/定制语言模型 提升命中率。

  3. 指令解析与执行
    文本进入 规则引擎或 LLM(视项目阶段),映射为 平台内可执行操作(如:打开某路流、切换分屏布局、查询告警)。关键约束:权限校验、操作幂等、危险指令二次确认

  4. 反馈返回 TTS 音频 / 数字人视频流 / 页面状态变更;与现有 设备控制 API、播放器状态机 打通,保证 UI 与真实设备状态一致。

工程要点:全链路 超时、重试与降级(ASR 失败时提示重录;识别歧义时列出候选操作);日志 关联 traceId,便于联调排障。

示例:Recorder 录音并上传后触发识别(流程骨架)

ts
// 伪代码:具体 API 以 Recorder 文档为准
async function recordAndRecognize() {
  const rec = new Recorder({ type: 'mp3', sampleRate: 16000 });
  rec.open(() => rec.start());
  // 实际由 UI「停止录音」回调触发 stop,此处省略等待逻辑
  rec.stop(
    async (blob: Blob) => {
      const form = new FormData();
      form.append('file', blob, 'voice.mp3');
      const { data } = await api.post('/asr/upload', form);
      await executeIntent(data.text); // 映射为打开通道、切换分屏等
    },
    (err: unknown) => console.error(err),
  );
}

示例:指令落库前做权限校验(Spring 控制器片段)

java
@PostMapping("/voice/intent")
public Result<?> intent(@RequestBody IntentCmd cmd, @AuthenticationPrincipal UserPrincipal me) {
    if (!permissionService.canControlCamera(me.getId(), cmd.getCameraId())) {
        return Result.fail(403, "无该路视频操作权限");
    }
    return deviceFacade.apply(cmd); // 内部再保证幂等 / 限流
}

其他核心能力(摘要)

  • 设备主数据:多字段 CRUD、分组与区域维度检索。
  • 分屏布局:1/4/9 宫格等模板,与 路数授权、码率预算 联动。
  • 告警中心:告警列表、详情、确认与统计;可与 订阅推送 扩展。

示例:四分屏网格与播放器槽位(Vue 模板骨架)

vue
<script setup lang="ts">
import { ref } from 'vue';

const layout = ref<'1' | '4' | '9'>('4');
const slots = ref<{ id: string; streamUrl: string }[]>([]);

function setCell(i: number, cam: { id: string; streamUrl: string }) {
  slots.value[i] = cam;
}
</script>

<template>
  <div class="grid" :class="`grid-${layout}`">
    <div v-for="i in layout === '4' ? 4 : 9" :key="i" class="cell">
      <video v-if="slots[i - 1]" :src="slots[i - 1].streamUrl" controls muted />
    </div>
  </div>
</template>

实际工程里 streamUrl 多为 HLS 地址封装好的 Player 组件,并需处理 自动播放策略(静音、用户手势)。


复盘小结

视联网类项目的难度集中在 流媒体协议与资源消耗、多端播放器差异、以及「语音→可靠控制」的闭环。在材料中突出 量化指标(支持并发路数、P95 延迟、告警处理 SLA)会显著增强 资深参与感。本文档可按实际上线数据补全一节 性能与容量