音视频后端物联网计算机视觉【免费下载链接】scryptedScrypted is a high performance video integration and automation platform项目地址https://gitcode.com/gh_mirrors/sc/scrypted点击查看免费下载本文以 Scrypted 仓库中 Amcrest 插件的 AD410 门铃真实事件抓包plugins/amcrest/ad410.md为核心素材逐事件解读 Amcrest 门铃在按键呼叫过程中推送的 multipart 事件流并结合插件源码amcrest-api.ts、main.ts说明这些事件如何被解析、匹配最终驱动 Scrypted 的BinarySensor门铃状态与MotionSensor移动侦测接口帮助你在调试 Amcrest 门铃、对接自定义事件或排查门铃不触发问题时具备完整的协议级认知。AD410 门铃的真实事件流抓包plugins/amcrest/ad410.md 记录了 Amcrest AD410 门铃在一次完整按键呼叫访客按下门铃按钮、无人接听、随后挂断过程中通过 HTTP 长连接推送的原始事件流。这是理解整个 Amcrest 事件协议最直接的样本event --myboundary Content-Type: text/plain Content-Length:41 Code_CallRemoveMask;actionStart;index0 event --myboundary Content-Type: text/plain Content-Length:36 CodeAlarmLocal;actionStart;index0 event --myboundary Content-Type: text/plain Content-Length:148 Code_DoTalkAction_;actionPulse;index0;data{ Action : Invite, CallID : 20220406135211095697192.168.10.20, CallSrcMask : 4 } event --myboundary Content-Type: text/plain Content-Length:68 CodeCallNoAnswered;actionStart;index0;data{ CallID : 4 } event --myboundary Content-Type: text/plain Content-Length:41 CodePhoneCallDetect;actionStart;index0 event --myboundary Content-Type: text/plain Content-Length:41 CodeVideoMotionInfo;actionState;index0 event --myboundary Content-Type: text/plain Content-Length:185 Code_DoTalkAction_;actionPulse;index0;data{ Action : Hangup, CallID : 20220406135211095697192.168.10.20, CallSrcMask : 4, HangupReason : HangupByPhone } event --myboundary Content-Type: text/plain Content-Length:35 CodeAlarmLocal;actionStop;index0 event --myboundary Content-Type: text/plain Content-Length:39 CodeCallNoAnswered;actionStop;index0 event --myboundary Content-Type: text/plain Content-Length:95 CodeVideoMotion;actionStop;index0;data{ Id : [ 0 ], RegionName : [ Region1 ] } event --myboundary Content-Type: text/plain Content-Length:40 CodePhoneCallDetect;actionStop;index0 event --myboundary Content-Type: text/plain Content-Length:40 Code_CallRemoveMask;actionStop;index0分帧格式multipart 边界 头 定长 body抓包中每一帧part的构成非常清晰--myboundarymultipart 流的边界行用于分隔相邻两个事件 part。抓包中边界行前的event前缀是捕获工具/控制台打印的日志前缀不属于流内容本身Content-Type: text/plain该 part 的 MIME 类型声明 body 是纯文本Content-Length:N该 part body 的精确字节数例如Code_CallRemoveMask;actionStart;index0恰好是 41 字节空行头与 body 的分隔bodyCode...;action...;index...;data{...}形式的事件负载其中data字段是可选的 JSON。这个分帧方式与 amcrest-api.ts 中的解析逻辑一一对应插件从 HTTP 响应的content-type头中解析出 boundary源码注释明确指出 Amcrest 可能发送--myboundary或带空格的-- myboundary两种形式再对每个 part 读取头行、按Content-Length读取定长 body。逐事件解读一次完整门铃呼叫的生命周期把 12 个事件按时间序展开就是一次 AD410 门铃呼叫的完整状态机顺序事件语义1Code_CallRemoveMask;actionStart;index0呼叫开始解除掩码门铃内部状态插件忽略2CodeAlarmLocal;actionStart;index0本地报警/响铃开始插件忽略3Code_DoTalkAction_;actionPulse;index0;data{Action:Invite,...}访客按下门铃按钮发起双向对讲邀请关键事件4CodeCallNoAnswered;actionStart;index0;data{CallID:4}呼叫开始被标记为未应答5CodePhoneCallDetect;actionStart;index0检测到电话呼叫门铃被按6CodeVideoMotionInfo;actionState;index0移动侦测状态脉冲访客靠近镜头触发7Code_DoTalkAction_;actionPulse;index0;data{Action:Hangup,...,HangupReason:HangupByPhone}对讲结束由电话侧挂断关键事件8CodeAlarmLocal;actionStop;index0本地报警停止9CodeCallNoAnswered;actionStop;index0未应答状态结束10CodeVideoMotion;actionStop;index0;data{Id:[0],RegionName:[Region1]}移动侦测区域停止RegionName指出触发区域11CodePhoneCallDetect;actionStop;index0电话呼叫检测结束12Code_CallRemoveMask;actionStop;index0呼叫结束掩码恢复几个值得注意的细节CallID的构成20220406135211095697192.168.10.20遵循时间戳序号来源IP的格式Invite 与 Hangup 两个脉冲携带相同CallID可用于配对一次完整呼叫CallSrcMask: 4表示呼叫来源掩码。动作语义action取值为Start进入某状态、Stop离开某状态、Pulse瞬时脉冲常带 JSONdata、State状态上报。index0通道索引0 基。插件会把index 1与设备配置的通道号比较不匹配则丢弃见后文。对照AD110 的门铃事件流仓库中另有 AD110 抓包 可以对照阅读。AD110 的呼叫事件序列更精简NTPAdjustTime;actionPulseNTP 校时脉冲、_DoTalkAction_;actionPulseInvite、CallNoAnswered;actionStart、CallNoAnswered;actionStop、_DoTalkAction_;actionPulseHangup。两者的对比揭示了 Amcrest 不同型号门铃的事件协议差异AD410 会额外推送PhoneCallDetect、AlarmLocal、_CallRemoveMask、VideoMotion/VideoMotionInfo等事件形成完整的呼叫 移动侦测生命周期AD110 的抓包中则没有这些条目或其固件版本未推送AD110 抓包中还混入了[HomeKit]: snapshot requested for reason: 1日志行——这是 Scrypted 控制台输出与原始事件流同一捕获通道产生的混排结果并非 multipart 事件流的一部分阅读此类抓包时需要区分关键的双向对讲事件_DoTalkAction_的 Invite/Hangup 脉冲、CallNoAnswered在两个型号上完全一致这正是插件能够用统一逻辑处理多种门铃的基础。源码级解析listenEvents 如何消费事件流订阅端点与边界解析AmcrestCameraClient.listenEvents() 是整个事件链的入口它向设备发起一个 HTTP 长连接请求http://ip/cgi-bin/eventManager.cgi?actionattachcodes[All]codes[All]表示订阅设备的全部事件码。拿到可读流后解析流程与上面抓包的分帧格式严格对应逐行读取边界common/src/read-stream.ts 的readUntil/readLine按换行切分遇到终止边界--myboundary--跳过读头readAmcrestMessage 持续读取行直到空行。源码注释专门处理了一个 DahuaAmcrest 同源固件的畸形情况——header 与 body 之间缺少换行分隔Content-Length:39后紧跟 body 行此时把不含:的行unshift回流中返回避免误判读 bodycommon/src/rtsp-server.ts 的readBody按解析出的Content-Length精确读取定长数据这保证了data{...}中跨多行的 JSON如抓包里 Invite 脉冲的 148 字节能被完整取出容错兼容解析循环还处理了 Dahua 设备偶发在流中插入完整HTTP/1.1 200 OK响应消息的 bugamcrest-api.ts#L271-L281将其整段跳过并记录日志。事件码表AmcrestEvent 枚举与匹配AmcrestEvent 枚举 定义了插件关心的全部事件码匹配方式是子串包含data.indexOf(event) ! -1。对照 AD410 抓包可以精确看出哪些事件被消费、哪些被静默忽略export enum AmcrestEvent { MotionStart CodeVideoMotion;actionStart, MotionStop CodeVideoMotion;actionStop, MotionInfo CodeVideoMotionInfo;actionState, AudioStart CodeAudioMutation;actionStart, AudioStop CodeAudioMutation;actionStop, TalkInvite Code_DoTalkAction_;actionInvite, TalkHangup Code_DoTalkAction_;actionHangup, TalkPulse Code_DoTalkAction_;actionPulse, AlarmIPCStart CodeAlarmIPC;actionStart, AlarmIPCStop CodeAlarmIPC;actionStop, PhoneCallDetectStart CodePhoneCallDetect;actionStart, PhoneCallDetectStop CodePhoneCallDetect;actionStop, DahuaTalkInvite CodeCallNoAnswered;actionStart, DahuaTalkHangup CodePassiveHungup;actionStart, DahuaCallDeny CodeHungupPhone;actionPulse, DahuaTalkPulse Code_CallNoAnswer_;actionPulse, FaceDetection CodeFaceDetection;actionStart, SmartMotionHuman CodeSmartMotionHuman;actionStart, SmartMotionVehicle CodeVehicle;actionStart, CrossLineDetection CodeCrossLineDetection;actionStart, CrossRegionDetection CodeCrossRegionDetection;actionStart, }以 AD410 抓包为参照被消费的PhoneCallDetect;actionStart/Stop、_DoTalkAction_;actionPulseInvite/Hangup 靠 payload 区分、CallNoAnswered;actionStart、VideoMotionInfo;actionState、VideoMotion;actionStop被忽略的_CallRemoveMask、AlarmLocal、CallNoAnswered;actionStop——它们不在枚举中解析循环对它们不做任何状态变更。这意味着事件协议中相当一部分内部簿记事件对上层是透明的。每个事件 emit 时还会携带从 body 中解析出的index通道索引与dataJSON 负载解析器把 body 按;切分提取index与data两个片段data会被JSON.parse成对象amcrest-api.ts#L297-L319。此外智能检测事件SmartMotionHuman、Vehicle、FaceDetection、CrossLine/CrossRegionDetection会被进一步映射为person/car/face类别并额外 emitsmart事件供ObjectDetector接口输出仓库中 plugins/amcrest/dumps/amcrest-face-detected.json 与 plugins/amcrest/dumps/amcrest-human-detected.json 保留了这类事件的真实 JSON 样本包含BoundingBox、ObjectType、Confidence等字段。事件流如何变成 Scrypted 的传感器状态门铃按键 → BinarySensorAmcrestCamera.listenEvents() 订阅事件流后把事件码翻译为设备状态。处理 AD410 门铃按键的关键分支main.ts#L260-L286else if (event AmcrestEvent.TalkInvite || event AmcrestEvent.PhoneCallDetectStart || event AmcrestEvent.AlarmIPCStart || event AmcrestEvent.DahuaTalkInvite) { ... this.binaryState true; } else if (event AmcrestEvent.TalkHangup || event AmcrestEvent.PhoneCallDetectStop || ... ) { this.binaryState false; } else if (event AmcrestEvent.TalkPulse doorbellType AMCREST_DOORBELL_TYPE) { if (payload.includes(Invite)) { this.binaryState true; } else if (payload.includes(Hangup)) { this.binaryState false; } }把 AD410 抓包代入这段逻辑binaryState的翻转轨迹是_DoTalkAction_Invite 脉冲 →binaryState true访客按下按钮门铃响CallNoAnswered;actionStart、PhoneCallDetect;actionStart→ 再次置true冗余确认_DoTalkAction_Hangup 脉冲HangupReason: HangupByPhone→binaryState falsePhoneCallDetect;actionStop→ 置false。值得注意的是TalkPulse分支对payload完整 body 字符串做includes(Invite)/includes(Hangup)判断——这正是为什么 Invite/Hangup 两个脉冲必须携带 JSONdata字段如果某固件的脉冲不带data该分支不会翻转状态只能依赖PhoneCallDetect的 Start/Stop 兜底。而事件负载中的index会先经过通道过滤main.ts#L231-L236index 1必须等于设备配置的Channel Number OverridertspChannel设置项多通道 NVR 场景下避免串通道。接口暴露上updateDevice() 在设备Doorbell Type设为Amcrest Doorbell时把设备类型置为Doorbell并追加BinarySensor与Intercom接口——这解释了为什么 README 中门铃配置的第一步是SelectTypeisDoorbell只有如此门铃事件才会被映射到二进制传感器而非仅日志。移动侦测20 秒超时而非 Stop 事件AD410 抓包中的VideoMotionInfo;actionState事件 6与VideoMotion;actionStop事件 10的处理体现了插件的防抖设计main.ts#L211-L253MotionStart/SmartMotionHuman/SmartMotionVehicle/CrossLine/RegionDetection→ 立即motionDetected true并重置一个20 秒的motionTimeoutMotionInfo即VideoMotionInfo;actionState脉冲→ 若尚未检测到则补置true同样重置 20 秒计时MotionStop→有意不立即清除状态注释写明use resetMotionTimeout即依赖 20 秒无新事件后自动回落为false。这种事件置位 超时回落的模式避免了固件偶发漏推Start/Stop配对事件时传感器卡死的问题——这也与抓包中VideoMotion;actionStop携带RegionName: [Region1]对应 Amcrest 配置界面第一号运动侦测区域相互印证即使 Stop 到达状态清理仍统一由超时完成。监听器保活listenLoop 的重连与空闲超时事件长连接的健壮性由基类 RtspSmartCamera.listenLoop() 保证监听器创建失败、连接close或error时自动销毁并延时重建rtsp.ts#L183-L191连接后启动 5 分钟空闲看门狗期间没有任何data事件即设备长时间无活动则销毁监听并重建防止半死连接每个事件到达都会刷新空闲计时因此在门铃频繁触发的场景下连接会持续保活。listenEvents内部还会stream.socket.setKeepAlive(true)维持 TCP 保活amcrest-api.ts#L250。调试时可在设备设置中开启debug每个原始事件帧会打印到控制台rtsp.ts#L211-L215——ad410.md 与 ad110.md 这两份文档本身就是这类调试输出的归档样本。实战配置与 AD410 已知怪癖门铃设备的基本配置按 Amcrest 插件 README 的门铃配置要求plugins/amcrest/README.mdType选择Doorbell设备名称下方Username为admin设备初始化时设置的本地管理员账号不是 Amcrest Smart Home 云账号Doorbell Type选择Amcrest Doorbell对应源码中的 AMCREST_DOORBELL_TYPE可选值还有Dahua Doorbell若双向对讲开始时门铃重启/崩溃用 Amcrest Smart Home 应用在 Device Information 中关闭Record Audio选项代价是 SD 卡不再录音。双向对讲的音频通路当事件把binaryState置真后可通过Intercom接口发起对讲。startIntercom() 对 Amcrest 门铃非 Dahua的路径是把媒体转成 FFmpeg 输入用 FFmpeg 重编码为AACadts 封装后以 1024 字节分块 POST 到http://ip/cgi-bin/audio.cgi?actionpostAudiohttptypesinglepartchannel通道号Content-Type为Audio/AACDahua 门铃则走pcm_alaw/Audio/G.711A编码。另外 main.ts#L757 的注释提示ONVIF 双向音频在大多数机型上表现更好但AD110 例外添加设备时插件会自动探测devAudioOutput.cgi并默认选择ONVIF见 checkTwoWayAudio()。AD410 特有的 caps 怪癖configureCodecs() 中有一段针对 AD410 的特殊处理源码注释明确写道ad410 doesnt return a camera number if accessed directly——当直连 AD410不经过 NVR查询编码能力时encode.cgi?actiongetConfigCaps返回的键不带通道编号前缀。解析器因此在caps[0].MainFormat[0]找不到值时回退到caps.MainFormat[0]。如果你在为 AD410 配置码率/分辨率时遇到能力查询异常这是一个已知的设备侧差异而非配置错误。设备信息获取方面插件通过 probe.ts 的magicBox.cgi?actiongetSystemInfo解析deviceType/serialNumber等设备参数来校验凭据与型号main.ts 的 updateDeviceInfo() 还会逐一查询getVendor/getSerialNo/getDeviceType/getSoftwareVersion失败仅记录错误而不阻塞设备使用。小结AD410 的一次门铃呼叫会产生 12 个 multipart 事件帧核心信号是_DoTalkAction_的 Invite/Hangup 脉冲与PhoneCallDetect的 Start/Stop其余_CallRemoveMask、AlarmLocal、CallNoAnswered;actionStop为插件忽略的内部簿记事件事件流由eventManager.cgi?actionattachcodes[All]长连接推送分帧为边界 Content-Type/Content-Length 头 定长 bodydata字段携带跨行 JSON插件通过 AmcrestEvent 枚举 做子串匹配把事件翻译成BinarySensor门铃与MotionSensor20 秒超时回落状态并由 listenLoop 提供重连与空闲看门狗保活配置门铃时需将设备Type设为Doorbell、Doorbell Type设为Amcrest Doorbell并使用设备本地admin凭据调试原始事件帧可开启设备debug设置ad410.md 与 ad110.md 是两份可对照的真实抓包样本。赞分享音视频后端物联网计算机视觉【免费下载链接】scryptedScrypted is a high performance video integration and automation platform项目地址https://gitcode.com/gh_mirrors/sc/scrypted点击查看免费下载相关推荐Scrypted Amcrest 插件实战接入 Amcrest 摄像头、门铃与 NVR 的完整配置指南Scrypted Amcrest 插件实战接入 Amcrest 摄像头、门铃与 NVR 的完整配置指南 本篇技术文章围绕 Scrypted 仓库中的 Amcr音视频后端物联网计算机视觉go2rtc项目中Amcrest AD410门铃双向音频配置指南go2rtc项目中Amcrest AD410门铃双向音频配置指南 背景介绍 在智能家居监控系统中Amcrest AD410门铃是一款基于Dahua技术的流行设音视频后端Mistral-Nemo-Instruct-2407代码生成实战从基础编程到复杂算法实现终极指南Mistral Nemo Instruct 2407代码生成实战从基础编程到复杂算法实现终极指南 Mistral Nemo Instruct 2407 是一款上一篇解锁创意工坊WorkshopDL跨平台工具全解析下一篇LangChain为什么它是构建AI代理的首选框架3个关键优势解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考