ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Go2RTC+EasyNVR+cpolar:本地存储远程看监控的完整方案

Go2RTC+EasyNVR+cpolar:本地存储远程看监控的完整方案

最近有朋友问我,家里装了监控摄像头,在局域网里看一直很正常,一出差到外地就想远程看一眼店铺情况,结果不是云存储APP提示要充值会员,就是官方P2P服务卡成幻灯片,还有几次干脆连不上。正好我手上一直在维护一个“本地化存储+局域网外访问”的监控改造项目,这次把Go2RTC、EasyNVR和cpolar三个工具组合起来,把录像落在自己的硬盘上,同时通过内网穿透实现在外面也能看实时画面。整套流程跑下来,算是把我长期实验清单里的第761个挑战完整收尾了。

这套方案要解决的核心事情其实就三件:一是浏览器怎么低延迟播放RTSP摄像头的流,二是录像怎么稳定落盘到本地,三是人在异乡怎么安全访问家里或办公室的内网服务。如果你也在折腾自建监控,或者被云存储的会员和上传带宽折磨过,这篇文章应该能帮你省掉不少弯路。我会把方案选型的原因、每一步的部署细节、需要计算的参数、以及我实际踩过的坑都写清楚。

1. 方案选型:为什么是Go2RTC + EasyNVR + cpolar 三件套

1.1 先拆解三个核心需求

监控远程访问这个需求,表面上看只是“出门能看监控”,但拆开来看,里面藏着三个技术难点。

第一个是协议问题。市面上绝大多数网络摄像头虽然都支持RTSP协议,但浏览器默认并不能直接播放RTSP,现代浏览器连插件这条路也基本堵死了。你总不能要求家里长辈在电脑上装一个VLC再输一串rtsp地址去查监控。所以必须有一个中间层,把RTSP转成浏览器原生支持的播放格式,而且延迟要低。这里我选的是Go2RTC,它专门把RTSP转成WebRTC和MSE,局域网内能做到几百毫秒级别的低延迟。

第二个是存储问题。录像必须留在本地硬盘上,不能经过任何第三方云平台。EasyNVR本身就是一套流媒体中间件,它能主动把摄像头RTSP流拉进来,然后做计划录像、视频文件切片、磁盘管理,并对外提供HTTP-FLV、HLS、WebRTC等多种播放地址。用它来做“本地化存储”这一环,比我自己用FFmpeg循环录制再手动清理旧文件要省心得多。

第三个是访问问题。摄像头和流媒体服务在家庭或办公室内网,外部网络直连不了。传统做法是去运营商申请公网IP,然后路由器做端口映射,但现在很多宽带环境不给公网IPv4,或者封了80、443端口,家里IP还会变化。用cpolar这类内网穿透工具,相当于在本地服务与公网之间建立一条加密隧道,外部通过一个临时域名或者固定域名访问到内网。这个方案不依赖公网IP,也不需要在路由器上做端口映射,部署起来最省事。

1.2 各组件分工与边界

很多人容易把Go2RTC和EasyNVR搞混,觉得两个都是流媒体服务器,功能重叠。我实际测试下来,这两者配合比二选一要舒服很多。

Go2RTC的强项在于WebRTC低延迟播放和轻量级部署,它的核心能力是把一路RTSP流转换给浏览器端做实时查看,配置非常简单,几十行YAML就能跑起来。但它本身不是为多路长期录像设计的,虽然新版本也支持录制,但功能密度和专业度比EasyNVR差了不少。

EasyNVR的强项则是设备管理和录像存储。它可以统一接入多个品牌的RTSP摄像头,对每一路流做通道管理,还能设置独立的录像计划,按时间或者按事件录像,录像文件在后台可以直接浏览回放。它也有WebRTC输出,但在公网穿透场景下并不一定好用,后面我会详细解释为什么。

cpolar的角色在最外层。它负责把EasyNVR的管理后台、Go2RTC的播放页面以及流媒体端口映射到公网。我个人的习惯是局域网内优先用Go2RTC的WebRTC看实时画面,追求流畅低延迟;远程访问时则走cpolar隧道,通过EasyNVR的HLS或HTTP-FLV地址看画面,足够满足“人在外面确认一下情况”的需求。

1.3 为什么不做公网端口映射

可能有人会问,直接在路由器上映射8080端口不就行了,为什么还要多套一层cpolar?我试过这个方案,踩过的坑主要有三个。

第一个是很多宽带根本不分配公网IPv4地址,路由器拿到的是大内网地址,你想映射也没有公网IP可映射。第二是即使有公网IP,运营商对80和443端口管得很严,你映射8080之类的非常规端口,虽然能通,但手机流量网络或者公司网络经常会对非常规端口做限制。第三个是直接暴露端口等于把你的服务裸奔在公网上,扫描工具一分钟能扫几十次,如果流媒体服务本身有漏洞,风险太高。

cpolar这类隧道方案的好处是,本地服务并没有真正暴露在公网上,公网入口是cpolar的边缘节点,本地只主动向边缘节点建立一条反向连接。这样外部访问的人拿到的是cpolar返回的公网域名,请求经过加密隧道转发到本地服务。从安全角度看,比直接在路由器开端口映射要稳妥得多。

2. 第一步:部署EasyNVR并完成本地录像存储

2.1 安装与摄像头接入

EasyNVR部署本身不难,支持Windows和Linux。我这次是在一台X86主机上跑的Linux版本,把压缩包解压到/opt/easynvr目录,直接执行启动脚本,服务起来后默认监听8080端口作为管理后台。第一次进入后台会引导设置管理员账号,这一步不要图省事用简单密码,后面要通过隧道暴露出去,账号密码就是第一道防线。

摄像头接入是整个项目最基础的一步,也是最容易出幺蛾子的一步。在后台的“设备管理”里选择添加通道,填入摄像头名称和RTSP地址。RTSP地址格式要根据摄像头品牌来写,通用格式是这样:

rtsp://用户名:密码@摄像头IP:554/媒体路径

以市面上常见的安防摄像头为例,主码流和子码流的路径往往不同,主码流通常对应101这样的标识,子码流对应102。远程预览如果只看清晰度不敏感的画面,用子码流会省很多带宽。也有部分品牌地址特别长,带username=、channel=这类参数,如果不确定,可以从摄像头厂商的文档或者ONVIF工具里读到。

添加成功后,后台会显示拉流状态。如果状态一直是失败或者离线,我后面会专门讲排查方法,这里先说一句:先把摄像头IP和流媒体服务器IP放在同一个网段,然后把RTSP地址放到VLC播放器里试一遍,VLC能放,EasyNVR就能拉,VLC放不了,先解决摄像头侧的权限和地址问题再继续。

2.2 录像计划与存储策略

EasyNVR的本地录像配置核心在两个地方:存储管理和录像计划。

存储管理里指定录像文件的存放路径。我强烈建议不要用系统盘,单独挂一块存储盘,路径比如/data/record。设置完毕后,后台会显示磁盘剩余空间。录像计划里可以选择全天录像、定时录像或者按事件触发。我这边用的是全天录像加重要时段补录的混合策略,白天营业时段录主码流,夜间无人时段只记录移动侦测触发的事件片段。这样做不是为了省几GB硬盘,而是减少无用录像的写入,延长监控级硬盘寿命。

录像文件默认会自动切片,这个切片长度可以设置。我之前用默认的1小时切片,后来遇到一次意外断电,断电前那个小时的录像文件直接损坏,后半段完全无法回放。后来把切片时长改成了15分钟,即使某一段损坏,损失最多15分钟画面,排查问题也方便很多。这个细节常规文档里不会强调,但实际运维中非常有用。

2.3 磁盘容量测算与计算过程

做录像存储前,一定要先算清楚硬盘要买多大,否则录像计划跑了两天硬盘满了,后面全部白录。

录像文件大小取决于码率。假设一路摄像头主码流是4Mbps,单位换算成字节就是4除以8,等于0.5MB/s。一小时就是0.5乘以3600,约1800MB,再除以1024,大约1.76GB。一天24小时不停录,就是42GB出头。如果装了4路摄像头,连续录7天,总共需要约1.2TB的存储空间。这个量级如果用子码流2Mbps录像,一周4路只需要约600GB。所以我的建议是——

先确定你想要保留多少天的录像,再反推需要的存储容量,最后决定用主码流还是子码流录像。远程预览用子码流,本地存储也用子码流,平时看个大概足够,真要回放高清画面的时候再临时切换码流。

这种思路能让你用最小的硬盘换最长的覆盖周期。磁盘容量计算表可以做一个简单的对照,方便后面扩充摄像头时参考:

码流单路每小时单路每天4路存7天
2Mbps约0.88GB约21GB约588GB
4Mbps约1.76GB约42GB约1.18TB
6Mbps约2.64GB约63GB约1.77TB

录像计划设置完成后,建议隔几个小时回后台看一次磁盘写入情况,确认文件确实在增长而不是一直为0。很多“录像没文件”的问题,往往不是录像功能坏了,而是存储路径没有写权限。

3. 第二步:部署Go2RTC,把RTSP变成浏览器秒开

3.1 安装与配置文件

Go2RTC的部署非常简单,它有一个可执行文件,扔到服务器上就能跑。我是在Linux环境下用二进制文件启动的,也可以直接用Docker容器方式运行,原理一样。启动后默认在1985端口提供Web控制台和WebRTC信令服务,在8554端口提供RTSP服务。

Go2RTC的核心配置文件是YAML格式。我先创建了一个go2rtc.yaml,把摄像头流逐条加进去:

log: info api: :1985 rtsp: :8554 streams: cam1: - rtsp://admin:你的摄像头密码@192.168.1.64:554/Streaming/Channels/101 cam1-sub: - rtsp://admin:你的摄像头密码@192.168.1.64:554/Streaming/Channels/102

配置文件里每一行都有实际作用。log控制日志输出等级,排查问题时会改到debug。api是Web控制台和WebRTC信令地址。rtsp是RTSP监听端口,这个端口在下一步cpolar穿透时还有用处。streams下面定义的是流名称和来源,cam1是我自己起的名字,浏览器播放时直接用这个名称访问。

启动命令是:

./go2rtc -config go2rtc.yaml

启动日志里如果没有任何报错,说明服务已经起来了。这时候打开局域网地址http://192.168.1.10:1985,就能看到一个Web控制台,点击cam1这一路流,会弹出播放窗口。如果你的电脑和服务器在同一个局域网,这里就应该能看到实时画面了。

3.2 局域网内播放效果与延迟验证

第一次成功播放的画面,延迟表现让我很满意。我从摄像头的手机画面和电脑浏览器画面对比了一下,差距在0.3秒上下,基本可以当作“实时”。这就是WebRTC的优势,它走UDP传输,配合RTCP反馈机制做丢包重传和码率自适应,端到端延迟远远低于传统的HLS播放方式。

Go2RTC还不止支持WebRTC一种播放方式。同一个流地址,在浏览器端它还能切换MSE模式播放,本质是走HTTP传输,虽然延迟比WebRTC略高,但兼容性更好,也能更方便地穿过隧道。这点后面做公网访问时可以作为备选播放方案。

如果局域网内WebRTC已经能播放,说明Go2RTC这一环已经通了。这时候我建议再验证一下RTSP端口是否工作正常——用VLC播放rtsp://192.168.1.10:8554/cam1,能出画面就说明RTSP转发链路也没问题。别看这一步不起眼,后面如果要在手机播放器里直接看流,走的就是这个通道。

3.3 局域网内播放的配置要点

Go2RTC我可以说是越用越顺手,但有几个点新手容易踩坑,这里先提前提一下。

第一个是摄像头编码格式问题。很多摄像头的默认编码是H.265,浏览器对H.265的支持非常差,Go2RTC转给浏览器WebRTC播放时,很可能得到黑屏或者花屏。这不是服务没跑起来,而是编码不兼容。解决办法是登录摄像头管理后台,把编码格式切换成H.264。这一步几乎适用于所有品牌,强烈建议在接入Go2RTC之前就改好。

第二个是音频问题。如果浏览器播放没有声音,先看摄像头音频编码。很多摄像头默认音频编码是AAC或者G.711,Go2RTC对G.711的支持通常没问题,但对某些特殊封装格式可能兼容性不好。排查的时候,先在Go2RTC控制台单独看画面,再开声音,一步步缩小问题范围。

第三个是端口占用。1985端口和8554端口如果已经被其他服务占用,Go2RTC启动会直接报错。如果你在同一台机器上跑了很多服务,请先确认端口没被占用,或者改Go2RTC的端口配置。

4. 第三步:cpolar 内网穿透,实现局域网外访问

4.1 安装并绑定账号

cpolar的客户端会提供一个本地管理面板,默认端口是9200。安装完成后,到官网注册账号拿到authtoken,在客户端里执行绑定操作,把客户端和账号关联起来。这一步相当于告诉cpolar边缘节点,“这台机器是我账号名下的,允许建立隧道”。

绑定完成后,本地管理面板里就能可视化创建隧道了,也能直接用命令行创建临时隧道。我个人更喜欢在管理面板里配置,因为多条隧道、固定域名、认证信息都可以集中管理,重启机器后隧道还能自动恢复。命令行更适合临时测试,一条命令立即映射一个端口,用来快速验证内网访问是否通。

4.2 创建隧道:映射EasyNVR后台与Go2RTC播放页

隧道怎么创建,取决于你想在外网访问什么。我的目标是两个:一是EasyNVR的管理后台和HLS播放地址,二是Go2RTC的播放控制台。所以我创建了两条HTTP隧道,一条指向本机的8080端口,一条指向本机的1985端口。

创建隧道时,本地地址要填127.0.0.1:8080和127.0.0.1:1985,因为客户端和流媒体服务在同一台机器上,走回环地址最安全,不会把服务暴露到局域网其他设备。隧道创建成功后,面板会显示一个分配的域名,类似xxxxxx.cpolar.cn这样的格式。这个域名就是你在公网访问的入口。

映射完成后,我第一时间用手机流量访问了EasyNVR后台。手机端4G网络环境,输入公网域名,可以打开登录页面,输入账号密码后能看到设备列表和录像列表,说明管理后台通了。然后访问Go2RTC的播放页,也一样能打开。

这里要特别注意一个区别:管理后台能打开,不等于视频流就能正常播放。视频流走的是流媒体端口,和Web页面走的端口不是一回事。公网能不能流畅播放,还取决于带宽和协议选择,下面详细说。

4.3 公网访问测试与播放协议选择

公网访问验证时,我还是先走了EasyNVR的HLS播放地址,因为HLS本质是HTTP请求一段段小的视频切片,走cpolar的HTTPS隧道非常稳。在手机流量环境下,HLS地址播放出来的画面延迟大约在3到5秒,对我来说完全能接受,毕竟出门看监控只需要知道“现在店里有没有人”,不需要精准对时。

如果你觉得HLS延迟还是有点高,可以试试Go2RTC的MSE播放模式。它也是走HTTP协议,但切片间隔更短,延迟通常可以压到1秒左右。实测在cpolar隧道环境下,只要上行带宽足够,MSE模式的表现比HLS更接近实时。

反倒是WebRTC在公网隧道下很容易出问题。原因我在后面常见问题里会详细讲,这里先记住一个结论:局域网内优先WebRTC,公网穿透时优先HLS或者MSE,不要硬磕WebRTC。

4.4 安全加固和访问限制

隧道能把内网服务暴露出去,安全就必须跟着做。我在这套环境里做了四层加固,层层独立,即使某一层被突破也不会裸奔。

第一层是流媒体服务本身的账号密码。EasyNVR和Go2RTC后台都设置了高强度密码,不用默认密码。第二层是摄像头独立密码,RTSP地址里的密码不要跟摄像头的管理员密码混用,有条件就给摄像头单独开一个子账号,只给拉流权限。第三层是https,cpolar隧道默认支持HTTPS访问,我全程使用HTTPS,避免账号密码在传输过程中被截获。第四层是不要随意分享隧道地址,尤其是带端口和路径的完整地址,发到群里或者朋友圈等于把监控大门钥匙交出去。

提醒:如果你只是临时测试远程访问,用完后建议把隧道暂停掉。长时间挂着隧道,虽然cpolar边缘节点有一层防护,但流媒体服务本身的暴露面毕竟变大了。我在非使用时段,习惯把隧道关停,需要时再一键开启。

5. 常见问题速查表与避坑技巧

5.1 常见故障排查速查表

这套组合踩过的坑我整理成了一张表,遇到问题先对照排查,能省很多时间:

现象可能原因处理方法
EasyNVR添加摄像头拉流失败RTSP地址错误、账号密码错误、摄像头IP不通先在VLC里验证RTSP地址,再填到EasyNVR
Go2RTC画面黑屏或花屏摄像头为H.265编码,浏览器解码不支持摄像头后台切换编码为H.264
WebRTC局域网正常,公网画面不出来WebRTC走UDP端口,隧道只转发了TCP改用HLS或MSE播放,或自建中继服务
cpolar隧道显示在线但访问超时本地对应端口没有监听检查流媒体服务是否在运行,端口是否被改
录像文件持续增长但回放为空录像文件索引损坏检查系统时间是否正确,尝试重建索引
远程画面频繁卡顿上行带宽不足改为子码流播放,降低分辨率或码率
免费隧道域名每次重启都变免费套餐不固定随机域名每次启动后重新查看新地址,或升级固定域名

5.2 WebRTC公网花屏与UDP隧道问题

这是整套方案里最经典的一个坑,值得单独拎出来讲。WebRTC的信令走HTTP,所以cpolar隧道可以正常转发;但WebRTC的媒体数据走UDP,而大多数内网穿透隧道只转发TCP流量,UDP端口并没有被映射出来。结果就是:网页能打开、信令能协商、播放按钮能点,但画面永远卡在加载中,或者黑屏几秒后报错。

这个问题的本质不在Go2RTC,也不在cpolar,而是WebRTC这种协议跟“无公网IP环境”天然冲突。我在局域网内用WebRTC毫无压力,但一到公网穿透环境就变成了这幅景象。遇到这种情况,不要怀疑自己的配置,切换到HLS或者MSE就能立竿见影——前提是你要在服务器配置里把这两种输出模式打开。

如果你确实需要公网环境下的低延迟WebRTC播放,也不是完全不能做,需要在公网侧搭一台具备公网IP的STUN/TURN中继服务器,让WebRTC媒体流量通过中继转发。这个方案对网络基础设施要求较高,普通家用场景我一般不推荐,性价比远不如HLS。

5.3 摄像头H.265编码带来的兼容性大坑

前面提到过H.265编码问题,这里再展开一点。很多新款摄像头出厂默认H.265,因为同等清晰度下H.265比H.264更省带宽,摄像头厂商自己也喜欢用。但这对Go2RTC来说是个麻烦,WebRTC规范里至今没有统一支持H.265,Chrome、Firefox都不原生解码,只有部分Safari版本能解。

所以接入Go2RTC之前,我习惯了先做一步“编码体检”:登录摄像头后台,把视频编码改为H.264,分辨率按需设置,码率设成可变码率。这个操作不仅解决了Go2RTC的兼容问题,也能让EasyNVR的HLS输出更稳定。如果你在浏览器端看到黑屏、花屏、只有声音没有画面,十有八九就是编码问题。

5.4 免费隧道域名漂移问题

cpolar免费套餐分配的随机域名,在一定条件下是会变化的,尤其是重启客户端或者隧道重新创建之后。我一开始没注意这个特点,把隧道地址收藏到了手机浏览器书签,结果第二天打开发现打不开了,还以为服务崩了,折腾半天才发现是域名变了。

解决方案有两个,最简单的就是每次远程访问前,先通过cpolar管理面板查看最新的隧道地址。如果你希望有一个固定的访问入口,那需要根据官方套餐配置一个固定二级域名。固定域名的好处不只是方便记忆,你还可以在本地流媒体后台的二维码、摄像机说明书里长期印上这个链接,不用三天两头通知家人改地址。

5.5 存储空间与上行带宽的平衡

远程访问的流畅程度,最终取决于上行带宽,跟家里下行网速关系不大。普通家庭宽带上行通常只有20Mbps到50Mbps,如果你远程一直用主码流(4Mbps)播放,再叠加录像写入和局域网内其他设备占用,卡顿几乎必然发生。

我的经验是远程预览和存储分开走两个码流:摄像头主码流提供给EasyNVR录像和局域网大屏播放,子码流提供给远程查看。子码流通常只有512Kbps到1Mbps,手机流量下播放非常顺滑。这个思路跟安防行业里“主码流存储、子码流预览”的经典做法一致,放到自建方案里同样适用。

写在最后的实操心得

这套Go2RTC + EasyNVR + cpolar 的组合,我前后迭代过好几个版本,踩过H.265黑屏的坑,也吃过WebRTC公网UDP不通的亏。现在整套环境已经稳定跑了几周,本地录像每天按时落盘,远程访问通过HLS和MSE模式也能随时看到实时画面。我个人的体会是,做这类自建监控方案,不要追求每个环节都用同一套协议,而是要让每个工具做它最擅长的事:EasyNVR管录像,Go2RTC管低延迟,cpolar管隧道。

如果你后续想扩展,还有一个很实用的方向:把录像目录挂载到NAS上,或者用独立监控级硬盘做循环存储,这样可以覆盖更长的回放周期。至于隧道这一层,等需求稳定了可以再去研究固定域名和访问限流,把安全加固做得更细一点。至少目前这套方案,已经完美解决了我“录像必须存在自己硬盘上,人在外面也能看”这两个核心要求。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进