☰
Scrypted Google Device Access 第二代摄像头接入:Rebroadcast 预缓冲与快照缺失问题实战指南
2026/10/15 11:21:18 网站建设 项目流程
  • 音视频
  • 后端
  • 物联网
  • 计算机视觉

【免费下载链接】scrypted

Scrypted is a high performance video integration and automation platform

项目地址:https://gitcode.com/gh_mirrors/sc/scrypted
点击查看免费下载

导读

本文围绕 Scrypted 官方 Google Device Access 插件(Nest / Google 摄像头接入)中的Gen 2(第二代)摄像头配置文档展开,讲解"云摄像头 + 预缓冲(Prebuffer)"这一核心组合:为什么云摄像头默认不启用预缓冲、开启预缓冲的带宽前提、以及 Gen 2 摄像头在 HomeKit 中显示 "Snapshot Unavailable" 的成因与解决办法。读完本文,你将掌握在 Scrypted 中让 Gen 2 云摄像头获得完整运动事件回溯与持续可用快照的完整配置方案,并能理解底层takePicture的实现路径。

一、Gen 2 摄像头在 Scrypted 中的定位

Scrypted 的 Google Device Access 插件位于 plugins/google-device-access,用于导入并控制用户的 Nest 与 Google 设备。插件将摄像头分为两类,并据此返回不同的使用说明:

  • Gen 1(第一代)摄像头:通过 RTSP 拉流,属于VideoCamera接口,阅读的是 README-camera-v1.md;
  • Gen 2(第二代)摄像头:支持 WebRTC 直播协议,属于RTCSignalingChannel接口,阅读的是本文的主角 README-camera-v2.md。

这个分流逻辑可以直接在源码中印证。在 main.ts 中,插件启动时用fs.readFileSync同时加载了两份文档:

const readmeV1 = fs.readFileSync('README-camera-v1.md').toString(); const readmeV2 = fs.readFileSync('README-camera-v2.md').toString();

而设备实例在 getReadmeMarkdown 中根据设备能力决定展示哪一份:

async getReadmeMarkdown(): Promise<string> { return this.isWebRtc ? readmeV2 : readmeV1; }

其中isWebRtc的判断来自设备 traits 中sdm.devices.traits.CameraLiveStream的supportedProtocols是否包含WEB_RTC(见 deviceIsWebRtc)。也就是说,第二代摄像头本质上是通过 Google 的 WebRTC 协议拉流的云摄像头,这也是下文所有配置建议(预缓冲、快照)的出发点。

二、第一步:安装 Rebroadcast(预缓冲)插件

Gen 2 摄像头配置文档的第一条指令非常明确:

Install the Rebroadcast Plugin.

即必须安装 Scrypted 的Rebroadcast Plugin(软件包名@scrypted/prebuffer-mixin)。这一点同时体现在插件的依赖声明中:查看 package.json,scrypted.pluginDependencies明确列出了:

"pluginDependencies": [ "@scrypted/snapshot", "@scrypted/webrtc", "@scrypted/cloud", "@scrypted/prebuffer-mixin" ]

其中@scrypted/prebuffer-mixin就是文档所说的 Rebroadcast Plugin。它的官方定位见 plugins/prebuffer-mixin/README.md:

该插件对所有已连接的摄像头维持持续连接,并缓冲一小段最近视频用于即时回放(instant replay)。这些即时回放被 HomeKit Secure Video 使用,同时也能加快实时直播流的加载速度。

从实现上看,main.ts 中定义了prebufferDurationMs = 10000,即默认保留约10 秒的环形视频缓冲,足够覆盖大多数运动事件发生前的画面。

说明:Google Device Access 插件的完整接入流程(Google Cloud 项目、OAuth 客户端、Smart Device Management API、Cloud Pub/Sub 推送订阅等)请参考 plugins/google-device-access/README.md,本文聚焦摄像头使用层面的预缓冲与快照配置。

三、云摄像头为什么不默认预缓冲:带宽取舍

文档明确指出:

Since this is a cloud camera, prebuffering is not enabled by default. This means that any motion leading up to an event may not be captured. Enable prebuffering if your internet service will not have bandwidth issues with a persistent connection continually downloading your camera stream.

翻译过来就是两个关键事实:

  1. 云摄像头默认不启用预缓冲。因为预缓冲的本质是"保持一条持续连接、源源不断地把摄像头视频流拉回本地",这对本地局域网摄像头毫无压力,但对云端摄像头意味着持续占用上行(对摄像头而言)与下行(对 Scrypted 主机而言)的互联网带宽。
  2. 不预缓冲的后果:运动事件发生前的一段画面不会被捕获。当 HomeKit Secure Video 或事件回放需要"事件前画面"时,由于本地没有任何历史缓冲,只能从事件发生的那一刻起开始拉流,事件触发前的关键几秒会丢失。

Rebroadcast 插件的设置项也印证了这一设计。在 stream-settings.ts 中,"Prebuffered Streams" 选项的描述明确写着:

Prebuffering maintains an active connection to the stream and improves load times. Prebuffer also retains the recent video for capturing motion events with HomeKit Secure video.Enabling Prebuffer is not recommended on Cloud cameras.

也就是说,官方在插件内部同样提示:云摄像头不建议启用预缓冲,除非你的网络条件允许。

何时应该开启预缓冲

文档给出的判断标准是:

  • 你的互联网服务不会因一条持续下载摄像头流的持久连接而产生带宽问题;
  • 你希望捕获运动事件发生前的画面(即事件的完整上下文);
  • 你希望摄像头的快照始终可用(见下一节)。

如果家庭/机房的上行带宽充裕(例如已有多路 1080p 码流持续传输仍然游刃有余),那么开启预缓冲是提升体验的正确选择——它同时解决运动前画面缺失和快照不可用两个问题。

四、Gen 2 摄像头没有快照:"Snapshot Unavailable" 的成因

文档的第二个要点:

Gen 2 Cameras do not provide snapshots. You will see "Snapshot Unavailable" in HomeKit while the stream is inactive. If prebuffering is enabled, the snapshots will always be available.

Gen 2 摄像头不提供快照(snapshot)。这意味着当视频流处于非活动状态时,HomeKit 里会显示 "Snapshot Unavailable"(快照不可用)。而一旦启用预缓冲,快照就始终可用。

为什么?可以从NestCamera.takePicture的实现看清全貌。在 main.ts 中,takePicture依次尝试三条路径:

路径一:预缓冲帧(最优先)

async takePicture(options?: PictureOptions): Promise<MediaObject> { // if this stream is prebuffered, its safe to use the prebuffer to generate an image const realDevice = systemManager.getDeviceById<VideoCamera>(this.id); try { const msos = await realDevice.getVideoStreamOptions(); const prebuffered: RequestMediaStreamOptions = msos.find(mso => mso.prebuffer); if (prebuffered) { prebuffered.refresh = false; return realDevice.getVideoStream(prebuffered); } } catch (e) { } ...

注意源码注释:"if this stream is prebuffered, its safe to use the prebuffer to generate an image"(如果该流已预缓冲,用它生成图片是安全的)。这正是文档结论的代码级依据——只有预缓冲开启时,才能稳定地从本地缓冲中取帧生成快照。

路径二:最近事件快照(仅限有事件图片能力的设备)

const hasEventImages = deviceHasEventImages(this.device); if (hasEventImages && this.lastMotionEventId) { const eventId = this.lastMotionEventId; this.lastMotionEventId = undefined; const result = this.provider.authPost(`/devices/${this.nativeId}:executeCommand`, { command: "sdm.devices.commands.CameraEventImage.GenerateImage", params: { eventId }, }).then(response => response.data); this.lastImage = result; }

这条路径依赖设备的sdm.devices.traits.CameraEventImagetrait(见 deviceHasEventImages)。它调用 Google SDM API 的CameraEventImage.GenerateImage命令拉取最近一次事件的云端快照。

路径三:直接失败

throw new Error('snapshot unavailable');

而源码中有一段非常关键的注释(main.ts):

not sure if this works? there is a camera snapshot generate image thing, but it does not exist on the new cameras.

即:新的 Gen 2 摄像头上,CameraEventImage这一"事件快照生成"能力根本不存在(deviceHasEventImages返回 false)。因此路径二失效,唯一可靠的快照来源就是路径一——预缓冲。

HomeKit 侧的快照请求流程

HomeKit 插件在 camera-snapshot.ts 中通过device.takePicture()请求快照;当设备没有Camera接口或takePicture抛错时,会向用户推荐安装 Snapshot Plugin。对 Gen 2 云摄像头而言,未启用预缓冲时takePicture走到路径三抛出snapshot unavailable,HomeKit 界面自然就显示 "Snapshot Unavailable"。

综合起来,文档那句"If prebuffering is enabled, the snapshots will always be available"的本质是:预缓冲让takePicture的第一条路径(本地缓冲取帧)始终可走通,从而绕开 Gen 2 摄像头没有原生快照能力的短板。

五、运动事件、事件快照与 30 秒有效期

虽然 Gen 2 摄像头没有CameraEventImagetrait,但 Google 仍会通过 Cloud Pub/Sub 推送运动与人物事件。在 main.ts 的onRequest(即 Pub/Sub 推送的 HTTP 入口)中,插件监听两类事件:

  • sdm.devices.events.CameraMotion.Motion(运动)
  • sdm.devices.events.CameraPerson.Person(人物)

命中事件后,插件会:

  1. 置位motionDetected(驱动 HomeKit 运动传感器);
  2. 记录lastMotionEventId = eventId;
  3. 事件图片 30 秒后过期(源码注释:"images expire in 30 seconds after publish"),通过setTimeout清除;
  4. 若为人物事件,额外派发ObjectDetection(person类)事件,从而在 Scrypted/HomeKit 中呈现"检测到人物"。

这段逻辑解释了 Gen 1 摄像头文档中"only provide recent event snapshots"的行为:事件快照来自云端、只有事件发生后短暂存在。而 Gen 2 摄像头连这条路径都没有,因此预缓冲成为唯一可靠的快照来源。

六、推荐配置总结与带宽评估

结合 README-camera-v2.md 与源码实现,给出 Gen 2 摄像头的完整配置清单:

项目建议依据
Rebroadcast 插件必须安装(@scrypted/prebuffer-mixin)文档第一条;package.json 插件依赖
预缓冲(Prebuffer)默认关闭;网络带宽充裕时开启文档说明;stream-settings.ts 明确提示云摄像头不建议启用
快照开启预缓冲后始终可用;否则非活动状态显示 "Snapshot Unavailable"文档说明;main.ts 三条取图路径
运动/人物事件由 Cloud Pub/Sub 推送,事件快照云端保留约 30 秒main.ts

如何判断是否值得开启预缓冲

可以从以下几个维度评估你的网络是否"没有带宽问题":

  1. 上行带宽:摄像头流持续推送(Gen 2 通常为 H.264/AAC,码率取决于摄像头配置),确保 24 小时持续拉流不挤占其他业务;
  2. 下行带宽:Scrypted 主机持续接收多路云流,计算所有已开启预缓冲摄像头的码率总和;
  3. 流量计费:若宽带套餐有流量上限,持续拉流会显著增加月流量,需纳入成本考量;
  4. 多摄像头规模:多路 Gen 2 摄像头同时预缓冲时带宽消耗线性叠加,建议从单路开始验证。

预缓冲之外的补充手段

即使不开启预缓冲,以下机制也能部分缓解"无快照、无事件前画面"的体验:

  • Cloud Pub/Sub 推送的实时事件:运动/人物事件本身是实时推送的,不影响事件触发与通知;
  • HomeKit 侧快照兜底:HomeKit 快照失败时会提示安装 Snapshot Plugin(见 camera-snapshot.ts),Snapshot 插件可提供最近一帧缓存;
  • 云摄像头流的 token 刷新机制:预缓冲开启后,由于 Google SDM 的 RTSP/WebRTC 会话有有效期(源码中刷新间隔为 4 分钟,见 main.ts 与 main.ts),Rebroadcast 插件会在refreshAt前约 30 秒自动请求新 token 续流(见 main.ts),确保长时间预缓冲不中断。

结语

Gen 2 摄像头在 Scrypted 中的接入要点可以浓缩为一句话:装上 Rebroadcast 插件,并根据带宽条件决定是否开启预缓冲。预缓冲是"运动前画面 + 始终可用快照"的唯一可靠来源;如果带宽不允许,则要接受事件前画面缺失与 HomeKit 快照不可用的取舍。相关实现细节均可直接查阅 main.ts、README-camera-v1.md 与 prebuffer-mixin 的源码与文档,按需深入。

  • 音视频
  • 后端
  • 物联网
  • 计算机视觉

【免费下载链接】scrypted

Scrypted is a high performance video integration and automation platform

项目地址:https://gitcode.com/gh_mirrors/sc/scrypted
点击查看免费下载

相关推荐

上一篇:GDAL 命令行 Cookbook:栅格与矢量数据处理实战指南
下一篇:Refine v5 + Ant Design TagField 组件完全指南:在管理后台用标签展示字段值

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询