Skip to content

普通视频监控窗口

普通视频监控窗口案例演示如何组合已有的装备与弹窗 API:监控点通过 viewer.createEntity 创建,用户选中监控装备后,将原生 HTMLVideoElement 作为 PopupManager 的自定义内容显示在地理位置上。

该案例属于 API 组合示例,不新增 VideoWindow 类。

能力边界

职责API / 所有者
监控装备创建与回收viewer.createEntity / EntityManager
弹窗定位、出屏隐藏与 DOM 外壳PopupManager
视频播放、MediaStream 与动画帧业务调用方
视频贴到 Cesium 多边形表面VideoMaterialProperty,不属于本案例

PopupManager 接受 HTMLElement,因此原生 <video>、播放提示和关闭按钮 都可以作为模板内容传入:

ts
const popupManager = new PopupManager(viewer)
const video = document.createElement('video')
video.controls = true
video.autoplay = true
video.muted = true
video.playsInline = true

const popup = popupManager.add({
  position: Cesium.Cartesian3.fromDegrees(106.455, 29.505, 12),
  template: video,
  anchor: 'top-left',
  offset: { x: 20, y: -80 },
})

装备创建原则

监控摄像头是场景中的业务装备,必须先安装实体扩展,再通过统一入口创建:

ts
nexaGis.extend(viewerEntityMixin)

const monitor = viewer.createEntity({
  id: 'monitor-camera-01',
  name: '监控 1',
  entityType: 'other',
  metadata: { mediaKind: 'canvas-stream' },
  components: [
    { id: 'position', type: 'PositionComponent', lon: 106.455, lat: 29.505, alt: 12 },
    { id: 'billboard', type: 'BillboardComponent', url: cameraIcon, scale: 0.56 },
  ],
  modules: [],
})

不要在效果或弹窗代码中绕过该入口直接创建监控 Entity。PopupManager 只绑定 装备的位置,不创建、删除或接管装备。

自动播放策略

现代浏览器通常只允许静音媒体自动播放。创建视频时应同时设置:

ts
video.autoplay = true
video.muted = true
video.defaultMuted = true
video.playsInline = true

try {
  await video.play()
} catch {
  // 显示“点击播放”按钮,由用户手势再次调用 video.play()
}

不要忽略 play() 返回的 Promise。即使使用静音播放,浏览器策略、低电量模式或 媒体状态仍可能拒绝播放,界面必须提供用户手势回退。

生命周期与清理

弹窗被移除不等于媒体已释放。业务调用方应对自己创建的媒体资源执行幂等清理:

ts
cancelAnimationFrame(animationFrame)
video.pause()
stream.getTracks().forEach(track => track.stop())
video.srcObject = null
popup.close()

此外还应保存并调用 viewer.selectedEntityChanged.addEventListener(...) 返回的注销 函数,最后调用 popupManager.destroy()。多个监控窗口可使用以装备 ID 为键的 Map 管理;同一装备已打开时复用现有窗口,避免重复创建 MediaStream。

资源策略

案例使用 Canvas 与 captureStream() 程序化生成监控画面,不请求外部 MP4、 3D Tiles 或流媒体服务,也不依赖 video.js。这样可以离线运行,并避免示例媒体的 版权、跨域和服务可用性问题。

captureStream() 需要现代浏览器支持;推荐使用项目支持范围内的 Chromium、 Firefox 或 Safari 版本进行验收。

RTMP 非目标

浏览器不能原生播放 rtmp:// 地址,Flash 方案也已淘汰。本案例只覆盖浏览器原生 媒体与 MediaStream。需要接入 RTMP 时,应先在服务端转换为 HLS、WebRTC 或其他 浏览器可消费的协议,再单独设计鉴权、重连、延迟和播放器生命周期;不应把 RTMP 传输逻辑加入 PopupManager