You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JavaScript通过ONVIF接口获取摄像头录像数据

问题描述

尝试通过ONVIF接口获取VIVOTEK品牌摄像头的录像数据,参照ONVIF官方recording.wsdl文档调用exportRecordedData函数时未得到预期结果,抛出如下错误:

2022-06-10T04:39:59.728Z error: exportRecordedData(): Error: Error: ONVIF SOAP Fault: Operation Action Not Implemented. The requested action operation is not implemented by the device.

需要明确JavaScript环境下通过ONVIF协议正确拉取摄像头录像的实现方式。

故障原因

报错Operation Action Not Implemented的核心原因是VIVOTEK主流在售机型均未实现ONVIF规范中的exportRecordedData接口。该接口属于ONVIF Recording Search服务的可选实现项,不属于ONVIF强制要求厂商适配的功能,直接调用必然返回未实现错误。

正确实现步骤
  • 第一步:先做设备能力探测,禁止直接硬编码调用接口。首先调用ONVIF标准的GetCapabilities接口,查询设备实际支持的服务端点,重点确认设备是否开放Replay服务(对应ONVIF标准的录像回放拉流能力),不要在未做能力探测的前提下直接调用Recording服务下的导出类接口。
  • 第二步:查询设备存储的录像列表。依次调用FindRecordings、GetRecordingSearchResults接口,获取设备本地存储的录像片段对应的时间范围、录像源token信息。调用前需要先登录摄像头Web后台,给对应ONVIF账号开启录像查看权限,否则会返回403权限错误。
  • 第三步:获取录像回放流地址。拿到有效录像token和需要拉取的起止时间范围后,调用Replay服务的GetReplayUri接口,传入流传输配置、录像token、拉流时间范围,获取RTSP格式的录像回放流地址。
  • 第四步:拉取并保存录像。拿到RTSP回放地址后,使用Node.js生态下的ffmpeg封装库、node-rtsp-stream等工具拉取RTSP流,直接保存为本地录像文件或者做后续转码处理即可,不需要通过SOAP接口传输录像二进制数据。

核心实现代码参考(基于常用的onvif npm包):

const onvif = require('onvif');
const { exec } = require('child_process');
// 初始化摄像头连接
const cam = new onvif.Cam({
  hostname: '摄像头局域网IP',
  username: 'ONVIF账号',
  password: 'ONVIF密码',
  port: 80
}, async err => {
  if (err) throw err;
  // 拉取设备能力列表
  await cam.getCapabilities();
  const replayServiceAddr = cam.capabilities.replay?.XAddr;
  if (!replayServiceAddr) throw new Error('当前设备不支持ONVIF标准录像回放服务');
  // 构造GetReplayUri请求体
  const soapBody = `
  <GetReplayUri xmlns="http://www.onvif.org/ver10/replay.wsdl">
    <StreamSetup>
      <Stream xmlns="http://www.onvif.org/ver10/schema">RTP-Unicast</Stream>
      <Transport xmlns="http://www.onvif.org/ver10/schema">
        <Protocol>RTSP</Protocol>
      </Transport>
    </StreamSetup>
    <RecordingToken>查询到的目标录像片段token</RecordingToken>
  </GetReplayUri>`;
  // 发送SOAP请求获取回放RTSP地址
  cam._request(replayServiceAddr, soapBody, (err, res) => {
    if (err) throw err;
    const rtspUrl = res[0].getElementsByTagName('Uri')[0].textContent;
    console.log('录像回放RTSP地址:', rtspUrl);
    // 示例:调用ffmpeg拉流保存为mp4文件
    exec(`ffmpeg -i "${rtspUrl}" -c copy ./record-${Date.now()}.mp4`, (err) => {
      if (err) console.error('录像保存失败', err);
    });
  });
});

注意事项:

  1. 部分旧版本VIVOTEK固件的ONVIF实现存在时区偏差问题,传入拉流起止时间时需要和设备本地时区对齐,否则会返回找不到对应录像的错误。
  2. 如果GetReplayUri接口同样返回未实现错误,可以直接使用VIVOTEK私有RTSP回放规则拼接地址,格式为rtsp://账号:密码@摄像头IP:554/live/回放通道号?starttime=YYYYMMDDTHHMMSS&endtime=YYYYMMDDTHHMMSS,无需走ONVIF SOAP接口即可拉取录像。

内容的提问来源于stack exchange,提问作者Aseem Mangla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 12:06:15