说实话,我第一次接触icam365摄像头视频下载的时候,脑子是懵的,家里装了个icam365的摄像头,想回看几天前猫在客厅捣乱的视频,结果发现官方App只能看实时流,想下载本地存着?没门儿,要么就是云端收费,要么就是导出格式乱码,我心想,这东西肯定有办法搞下来,毕竟是个网络摄像头嘛,数据总得往外发吧?
后来我一琢磨,用Golang写个程序去抓它,为啥选Go?因为它编译出来是个单文件,丢到树莓派或者Nas上就能跑,不用折腾环境,而且Go的网络库特别好用,处理并发也简单,这篇文章我就把这个过程掰开了揉碎了跟你聊聊,带点我踩坑的经验,希望能帮你省点时间。
先搞清楚icam365摄像头是怎么传视频的
每个摄像头厂商都有一套自己的协议,icam365也不例外,我买了摄像头之后连上Wi-Fi,手机App扫一扫就能看到画面,但这画面是通过啥协议到手机上的呢?
我抓了个包看了一下,发现它走的是RTSP(实时流协议),就是那种典型的视频监控协议,摄像头把视频流推送出来,你只要能连上它的RTSP地址,就能用VLC、ffmpeg这类工具拉流,但问题是,icam365把RTSP地址藏得挺深,默认的用户名密码也跟说明书上写的不太一样。
我查了不少资料,包括一些论坛帖子,发现icam365的RTSP地址一般是这样的格式:
rtsp://admin:password@192.168.1.100:554/h264/ch1/main/av_stream
但这里的admin和password,很多时候不是你App里设的那个密码,厂商出厂默认的可能是admin和admin123,或者你第一次激活时设的那个Wi-Fi密码,这就很玄学——有些型号密码就是Wi-Fi密码,有些是独立的设备密码。
这其实是个痛点,你要是连不上RTSP,后面全白搭。
第一步:用Golang扫描局域网,找到摄像头的IP
我写的第一段代码,就是用Go扫描整个局域网段,看看哪些端口是554开放的(RTSP默认端口),这有点粗暴,但很有效。
// 大概的思路是这样的
func scanNetwork() {
for i := 1; i <= 254; i++ {
ip := fmt.Sprintf("192.168.1.%d", i)
go tryRTSP(ip) // 并发扫描,快得很
}
}
但有个坑——摄像头如果不在同一个子网,或者你路由器开了AP隔离,那就扫不到,所以建议先让手机连上摄像头所在的那个Wi-Fi,然后电脑也连同一个路由器,这样IP就在一个段里了。
第二步:尝试连接RTSP,获取视频流
扫到IP之后,我们就用Go的gortsplib库去连它,这是我现在比较推荐的一个库,用法挺直接的。

client, err := gortsplib.Dial("rtsp://admin:admin123@192.168.1.100:554/h264/ch1/main/av_stream")
if err != nil {
// 密码不对,换一种试
}
这里我又踩了个坑:icam365不同固件版本的RTSP路径不一样,有的型号是/h264/ch1/main/av_stream,有的只是/live,还有的是/stream1,我最后写了个自动探测的逻辑:先试最常见的几条路径,每一条都尝试连接一下,能连上就记录下来,这样做的好处是,以后就算摄像头固件升级了,我的程序还能自适应。
用列表来总结一下我试过的常见路径:
/h264/ch1/main/av_stream/h264/ch2/sub/av_stream/live/stream1/ch0_0.h264/videoMain
没有一个万能钥匙,所以我才建议大家用Go写个自动探测循环,跑一遍就完事了。
第三步:拉流并保存为视频文件
连上RTSP之后,下一步就是下载了,理想情况下,我们直接把视频流写到本地文件里,但RTSP传的是原始流,不是直接能播放的MP4,你需要转封装。
我试过用Go直接写TS(MPEG-TS)格式,这样大部分播放器都能认,不过后来发现,直接用ffmpeg从Go里调用更省事,但我不想依赖外部程序,于是找了mpegts这个Go库,自己写了个简单的封装:
要保存为MP4的话,还需要处理关键帧,否则视频时间轴会乱,拖进度条的时候会花屏。
我最终的做法是:
- 先把视频流切成一个个小片段,每个大概10秒
- 每个片段作为独立的TS文件存下来
- 这样即使程序中途崩了,前面的片段还在
- 最后再用一个合并函数把这些片段拼起来
这个方法有点笨,但稳定。不追求优雅,追求能跑,我觉得这算是费曼写作法里说的那种“讲得够具体”了。
第四步:处理密码和认证问题
聊到这儿,必须说一下icam365的鉴权机制,它支持两种认证方式:Basic和Digest,Basic是明文传输密码,Digest是哈希后的,Go的gortsplib默认支持Digest,这倒省事。
但问题来了:密码我不知道。
有些用户会重置摄像头,这时候密码会变回默认的,我查了一下icam365的文档,大致有这么几种情况:
| 情况 | 默认用户名 | 默认密码 |
|---|---|---|
| 新出厂 | admin | admin123 |
| 通过App设置过 | admin | App设置的密码 |
| 重置后 | admin | 空密码(无密码) |
| 部分型号 | admin | Wi-Fi密码 |
说实话这个表是我自己统计出来的,官方没给全,所以我在程序里加了个密码字典,挨个试,一般试到第三个就能连上了,如果你运气不好,可能得试完所有。
第五步:把下载过程封装成一个仪表盘
既然写了程序,就得方便用,我最后用Go写了个小型HTTP服务器,跑在树莓派上,打开浏览器,就能看到摄像头列表和下载进度,如果你对前端不熟,可以用embed把静态页面打包进Go二进制文件里,这样部署就是单文件。
界面很简单:
- 自动扫描局域网摄像头
- 显示每个摄像头的型号、IP、是否在线
- 点击“下载”按钮,选择时间范围,开始拉流
- 进度条走完,文件就出现在
/download目录下
有朋友问我,为啥不用现成的工具?其实是因为定制化需求,比如我只想下载凌晨3点到4点的视频,或者只想下载有人移动时的片段,这些逻辑都可以在Go程序里写死。
踩过的坑,列个清单给你
不多说了,直接写下来:
- RTSP路径猜不到 —— 只能写循环去试
- 密码不对 —— 默认密码不是你想的那样,多准备几个备用
- 视频流断流 —— 无线摄像头信号不好时,会断流,要加重连机制
- 时间戳不准确 —— 摄像头时间没同步,加NTP同步程序
- 文件过大 —— 长时间录制会撑满硬盘,加自动分割+删除策略
- Go版本问题 —— 有些库只支持Go 1.18以上,老系统编译不过
代码之外的事
其实真正把这件事跑起来,不光是写代码。
我还得把摄像头放在合适的位置,保证Wi-Fi信号稳定,有一次因为摄像头的电源线太短,我只能把它放在路由器旁边,结果画面很清晰,但猫根本不往那儿走,后来挪了个位置,画面稍微模糊了点,但是能拍到猫了。
这就是现实——技术有时候不是最难的那一环,最难的是搞清楚你到底想要什么。
你要的是高清全彩视频?还是拍到猫有没有偷吃?这两种需求,程序策略不一样。
高清全彩意味着码率大,硬盘容易爆,偷拍猫的话,可以用移动侦测,只在有动静的时候录,这些逻辑我都在Go程序里加了配置开关,想调哪个调哪个。
最后说点实在的
我这套东西前后写了大概两个星期,修修补补的,有时候晚上加个班,调试一个bug,眼睛都花了,但最终跑起来的那一刻,看到视频文件安安稳稳地躺在硬盘里,还是挺高兴的。
你如果是技术爱好者,可以自己照着这个思路写一写,如果只是想下个视频,那直接找个现成的工具可能更快,但如果你想完全掌控自己的数据,不想依赖云端或者第三方,那自己用Golang写个下载器,是个靠谱的选择。
反正我家的icam365摄像头,现在每天自动录,定期删旧的,永远不会漏掉猫的“犯罪现场”,这大概就是技术带来的那种小确幸吧。
本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://www.uss1.cn/nba/1877.html
评论列表(4条)
我是be365的签约作者“kyadmin”!
希望本篇文章《用Golang搞定icam365摄像头视频下载,这事儿其实没那么玄乎》能对你有所帮助!
本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名
本文概览:说实话,我第一次接触icam365摄像头视频下载的时候,脑子是懵的,家里装了个icam365的摄像头,想回看几天前猫在客厅捣乱的视频,结...