实践教程:基于RV1126与ZeroTier的RTSP摄像头内网穿透与远程访问

一、 项目背景与目标 🎯

我手上有一块RV1126的开发板,外接了一个SunplusIT SPCA2688 USB摄像头。我的目标是搭建一个可以从任何地方远程访问的实时监控系统。

初始本地推流实现(详细教程请参考RV1126平台(Buildroot Linux)+ SunplusIT SPCA2688 USB摄像头 RTSP推流全流程复盘与问题解决记录-优快云博客

首先,我在开发板上成功实现了局域网内的RTSP推流。我使用的是 MediaMTX 作为RTSP服务器,并用 FFmpeg 来捕获摄像头数据、进行编码,然后推送到MediaMTX

我将所有命令都写在了一个脚本 rtsp_usb_camera_test.sh 中,方便一键启动。脚本内容如下

#!/bin/sh

# 启动 MediaMTX RTSP 服务器,并在后台运行
/mediamtx_v1.13.0_linux_armv7/mediamtx &

# 等待3秒,确保服务器已完全启动
sleep 3

# 使用 FFmpeg 从v4l2设备捕获视频,用libx264软编码,并推送到本机的RTSP服务器
ffmpeg -f v4l2 -input_format mjpeg -video_size 640x480 -framerate 15 -i /dev/video45 \
-c:v libx264 -preset ultrafast -tune zerolatency \
-f rtsp -rtsp_transport tcp rtsp://127.0.0.1:8554/live/main_stream

在开发板上运行这个脚本后,我可以在同一个WiFi下的电脑或手机上,用VLC播放器打开地址 rtsp://192.168.1.16:8554/live/main_stream 来观看实时监控画面。

这一切在家里用起来很方便,但我萌生了一个新想法:我希望能随时随地,无论是在公司、在路上还是在朋友家,都能看到这个摄像头的画面。

我的核心目标是:

  1. 实现公网远程访问。

  2. 方案必须是永久免费的。

  3. 要足够稳定可靠。

二、 方案选择:为什么是ZeroTier

经过一番了解,我发现有几种主流方案,比如“公网IP+DDNS+端口转发”、“FRP内网穿透”等。但这些方案要么依赖运营商提供公网IP,要么需要自己有一台云服务器,都有些门槛。

最终,我选择了 ZeroTier。它的理念深深吸引了我:创建一个“虚拟的局域网”,把我所有的设备(开发板、手机、电脑)都连接到这个虚拟网络里。设备之间就像真的在同一个路由器下一样,可以通过虚拟IP直接通信。最关键的是,它的免费套餐对于个人使用来说完全足够,而且安全性很高,不需要把任何端口暴露在公网上。

三、 实施过程:一步步实现远程访问

我的计划很清晰:给开发板和我的手机都装上ZeroTier客户端,让它们“手拉手”,然后通过虚拟IP访问视频流。

  1. 注册和创建网络:先去ZeroTier官网 my.zerotier.com 注册了一个账号,过程很简单。登录后,我点击“Create A Network”,系统立刻为我生成了一个16位的网络ID(Network ID),这个ID就是我虚拟局域网的唯一门牌号。

  2. 手机入网ZeroTier | Download我在手机上下载了ZeroTier One的App,输入网络ID,轻松加入了网络。并且在my.zerotier.com官网后台的“Members”列表里,给我的手机勾选了“Auth?”,批准了它的加入。手机很快就获得了一个10.144.x.x开头的虚拟IP。电脑入网也是同理,在这里ZeroTier | Download下载电脑版的,安装之后打开,然后选择join New Network,把上面第一步生成的网络ID输入进去

  3. 在开发板上安装客户端:这是挑战的开始。我的RV1126是Buildroot制作的精简Linux系统,没有apt-get,连curl命令都没有。官方提供的一键安装脚本完全用不了。

  4. 攻克安装难关:我最终采用了最原始也最可靠的方法:

    • 在电脑上Index of /dist/debian/bullseye/下载了ZeroTier的.deb安装包(armhf架构,兼容rv1126的armv7l架构开发板)。

    • 在我的Ubuntu虚拟机里,用dpkg-deb -x命令解压这个.deb包,解压后,可以看到解压目录下的usr/sbin目录下的zerotier-one和zerotier-cli这两个最核心的可执行文件

    • zerotier-one和zerotier-cli文件从Ubuntu虚拟机传输到开发板。我使用的是 adb push 命令,这个方式对于连接了USB的开发板来说非常方便。adb push zerotier-cli /root

  5. 启动服务与最终连接:为了避免每次都手动敲大量命令,我编写了一个Shell脚本,命名为push_stream_to_internet.sh,将所有在开发板上需要执行的命令都整合了进去。这个脚本帮我完成了移动文件、设置权限、创建开机自启服务、启动服务、并最终加入网络的所有操作。下面是这个脚本的完整内容:

    #!/bin/sh
    
    # --- 欢迎信息 ---
    echo "============================================="
    echo "===   ZeroTier 智能安装与启动脚本 v2.0   ==="
    echo "============================================="
    echo ""
    
    # ----------------------------------------------------------------------
    # 关键改动:增加端口健康检查与自动清理功能
    # ----------------------------------------------------------------------
    echo "--- 步骤 1/6: 健康检查:清理端口 9993 ---"
    PID_TO_KILL=$(netstat -lnp | grep ':9993' | awk '{print $7}' | sed 's/\/.*//')
    
    if [ -n "$PID_TO_KILL" ]; then
        echo "警告:端口 9993 已被进程 PID: $PID_TO_KILL 占用。正在强制终止..."
        kill -9 "$PID_TO_KILL"
        sleep 2
        echo "✅ 旧进程已清理。"
    else
        echo "✅ 端口 9993 状态正常。"
    fi
    # ----------------------------------------------------------------------
    
    # --- 文件检查与准备 ---
    echo "--- 步骤 2/6: 检查 ZeroTier 执行文件 ---"
    if [ ! -f "/usr/bin/zerotier-one" ]; then
        echo "在 /usr/bin/ 未找到zerotier-one,正在从源位置拷贝..."
        if [ -f "/mediamtx_v1.13.0_linux_armv7/zerotier-one" ]; then
            cp "/mediamtx_v1.13.0_linux_armv7/zerotier-one" "/usr/bin/zerotier-one"
        else
            echo "错误:在 /mediamtx_v1.13.0_linux_armv7 目录下也未找到 'zerotier-one' 文件!"
            exit 1
        fi
    fi
    echo "✅ 执行文件准备就绪。"
    
    
    # --- 获取 Network ID ---
    echo "--- 步骤 3/6: 配置 Network ID ---"
    echo "请输入您的16位 ZeroTier Network ID,然后按回车:"
    read NETWORK_ID
    if [ -z "$NETWORK_ID" ]; then
        echo "错误:Network ID 不能为空!"
        exit 1
    fi
    
    # --- 安装与配置 ---
    echo "--- 步骤 4/6: 设置权限与目录 ---"
    chmod +x /usr/bin/zerotier-one
    mkdir -p /var/lib/zerotier-one
    echo "✅ 完成"
    
    echo "--- 步骤 5/6: 创建开机自启服务 ---"
    cat > /etc/init.d/S99zerotier << EOF
    #!/bin/sh
    start() {
        echo "Starting ZeroTier One..."
        /usr/bin/zerotier-one -d
    }
    stop() {
        echo "Stopping ZeroTier One..."
        PID=\$(ps | grep '[z]erotier-one' | awk '{print \$1}')
        if [ ! -z "\$PID" ]; then kill \$PID; fi
    }
    case "\$1" in
        start) start ;;
        stop) stop ;;
        restart) stop; start ;;
        *) echo "Usage: \$0 {start|stop|restart}"; exit 1 ;;
    esac
    exit 0
    EOF
    chmod +x /etc/init.d/S99zerotier
    echo "✅ 完成"
    
    # --- 启动服务 ---
    echo "--- 步骤 6/6: 启动服务并加入网络 ---"
    /etc/init.d/S99zerotier start
    sleep 3
    zerotier-cli join "$NETWORK_ID"
    echo "✅ '加入网络' 请求已发送!"
    echo ""
    
    # --- 最终提示 ---
    echo "======================================================"
    echo "🎉 恭喜!脚本执行完毕!"
    echo "🚨【 最后一步,非常重要!】🚨"
    echo "请立即登录 ZeroTier 官网后台 (my.zerotier.com),"
    echo "找到这台新设备,并把它前面的复选框打勾授权!"
    echo "======================================================"

    6.最终测试:在经历了一系列问题的排查后,我在开发板上运行zerotier-cli listnetworks,终于看到了梦寐以求的虚拟IP!然后,我在手机VLC里,输入了 rtsp://<开发板的虚拟IP>:8554/live/main_stream,看到了清晰的画面。成功!

四、 遇到的问题与解决方案(踩坑全记录)🚧

这段旅程并非一帆风顺,我遇到了大大小小9个问题。正是解决了这些问题,才让我对嵌入式Linux和网络知识有了更深刻的理解。

问题1:开发板系统太精简,无法自动安装
  • 现象: 在开发板上想用apt-getcurl一键安装ZeroTier,结果提示command not found

  • 原因分析: 我的RV1126是Buildroot构建的,为了追求极致的性能和最小的体积,系统里没有包含这些包管理器和下载工具。

  • 解决方案: 手动部署。最终采用的方法是:在电脑上下载适配ARM架构的.deb包,在Ubuntu虚拟机中用dpkg-deb -x命令解压,从中提取出zerotier-onezerotier-cli这两个最核心的可执行文件,再通过adb push命令传输到开发板上。

问题2:在官网和GitHub上找不到预编译包
  • 现象: 按照一些教程去ZeroTier官网或GitHub Releases页面下载,发现 .tar.gz 格式的通用二进制文件都消失了,只有源代码。

  • 原因分析: ZeroTier官方调整了发布策略,不再提供显式的通用二进制包下载,这给非主流发行版的用户带来了困难。

  • 解决方案: 曲线救国。既然找不到通用包,我就去找特定发行版(Debian)的包。我从下面的地址下载了armhf架构的.deb包,这成为了后续提取文件的基础。

    下载地址: https://download.zerotier.com/dist/debian/bullseye/zerotier-one_1.12.2_armhf.deb

问题3:解压.deb包时,提示符号链接创建失败
  • 现象: 在Ubuntu虚拟机里解压.deb包时,报错tar: ... Cannot create symlink: Operation not supported

  • 原因分析: 我当时偷懒,直接在Windows和Ubuntu的共享文件夹(VMware的hgfs)里进行解压。Windows的NTFS文件系统原生不支持Linux的符号链接(symlink),导致解压失败。

  • 解决方案: 更换工作目录。将.deb文件从共享文件夹复制到Ubuntu自己的主目录(~/)下,这里的ext4文件系统完美支持所有Linux特性,再执行解压命令,问题解决。

问题4:启动服务时,报错端口9993被占用
  • 现象: 运行启动命令后,报fatal error: cannot bind to local control interface port 9993。但用ps命令又可能看不到zerotier-one进程。

  • 原因分析: 这是个“假死”现象。很可能是之前的进程异常崩溃,但它占用的网络端口没有被内核及时释放,成了一个“僵尸端口”。

  • 解决方案: 精准定位并强行终止。使用netstat -anp | grep 9993命令,它能无视进程状态,直接查出是哪个进程ID(PID)占用了该端口。然后使用kill -9 <PID>命令,将这个“幽灵”进程彻底杀死,从而释放端口。

问题5:启动服务时,报错找不到TUN/TAP设备
  • 现象: 解决了端口问题后,又出现新错误could not open TUN/TAP device: No such file or directory

  • 原因分析: 这是个更底层的系统问题。意味着我的Linux内核在编译时,就没有包含“虚拟网卡”(TUN)这个功能。ZeroTier依赖此功能才能工作。

  • 解决方案: 重新编译内核。我回到了Buildroot开发环境,执行make linux-menuconfig,进入内核配置菜单。按照路径Device Drivers -> Network device support,找到了Universal TUN/TAP device driver support选项,并将其设置为y<*>,直接编译进内核),然后重新make生成新固件并烧录。

问题6:加入网络后,无法获取虚拟IP
  • 现象: 在开发板上执行zerotier-cli join <nwid>后返回200 join OK,但listnetworks命令的结果一直只有表头,没有任何网络信息。

    # 解决前
    [root@ATK-DLRV1126:~]# zerotier-cli listnetworks
    200 listnetworks <nwid> <name> <mac> <status> <type> <dev> <ZT assigned ips>
  • 原因分析: 设备发出“敲门”请求后,我作为“房主”,没有在ZeroTier官网后台批准它进门。

问题7:远程视频画面花屏、卡顿严重
  • 现象: 手机在4G网络下终于能看到画面了,但画质极差,满屏的马赛克和色块,根本无法正常观看。用zerotier-cli peers诊断,看到了RELAY状态

    # 解决前
    [root@ATK-DLRV1126:/]# zerotier-cli peers
    200 peers
    <ztaddr>     <ver>  <role> <lat> <link>   <lastTX> <lastRX> <path>
    0678ebc45f -      LEAF     -1 RELAY
    ...
  • 原因分析: 我的手机和开发板之间的连接模式是RELAY(中继),而不是DIRECT(直连)。数据通过服务器中转,延迟和带宽都极差,无法承载视频流。

  • 解决方案: 优化网络,打通直连路径。我登录到开发板连接的路由器(天翼网关)后台,在“高级设置” -> “端口映射”功能里,为开发板的局域网IP(192.168.1.16)添加了一条规则,将UDP协议的9993端口转发出去。

    • 虚拟服务名称: ZeroTier

    • 局域网IP: 192.168.1.16

    • 服务协议: UDP

    • 内部端口: 9993

    • 外部端口: 9993

      # 解决后
      [root@ATK-DLRV1126:/]# zerotier-cli peers
      200 peers
      <ztaddr>     <ver>  <role> <lat> <link>   <lastTX> <lastRX> <path>
      632ea29085 1.14.2 LEAF    265 DIRECT   4459     13116    35.209.122.2/28655
      ...
问题8:手机使用移动数据时无法连接ZeroTier
  • 现象: 手机关掉WiFi用流量,ZeroTier App的连接开关打不开,并提示Not on Wi-Fi...

  • 原因分析: ZeroTier App为了防止误耗用户流量,默认设置只在Wi-Fi下工作。

  • 解决方案: 修改App设置。在ZeroTier App的设置(右上角三个点)里,找到Use Mobile Data(允许使用移动数据)选项,并将其开启。

问题9:远程播放时,局域网无法同时观看
  • 现象: 当手机通过ZeroTier观看视频时,局域网内的另一台电脑用VLC就无法打开视频流了。

  • 原因分析: 性能瓶颈。我的ffmpeg命令使用的是CPU进行软件编码(libx264),这本身就消耗了大量CPU资源。当MediaMTX服务器需要同时服务两条视频流(一条给ZeroTier,一条给局域网)时,开发板的CPU和网络I/O不堪重负,导致无法响应新的连接请求。

  • 解决方案: 承认性能极限。对于RV1126这样的嵌入式设备,同时进行实时编码和多路网络分发是一项沉重的任务。这个问题暂时作为性能极限来接受。后续优化的方向可以是利用硬件编码来解放CPU,或者降低视频流的码率和分辨率。

五、如何在远端查看开发板上接的摄像头的视频流

1.开发板已经在运行推流程序,一直在采集摄像头画面同时往外推流

2.执行push_stream_to_internet.sh脚本,保证开发板已经加入到Network ID,前面步骤已经介绍过

3.手机端打开zeroTier One软件,保持NETwork ID为加入状态,如下图所示

此时相当于你的手机和开发板已经加入了同一个虚拟局域网内(可以把NETwork ID理解成网关)

3.用手机端查看视频方法:打开vlc软件,打开串流,输入地址 rtsp://为开发板分配的虚拟地址:推流端口号/live/main_stream

然后就可以看到开发板连接摄像头采集到的视频画面:

4.用电脑查看视频方法:打开vlc软件,打开网络串流,输入地址 rtsp://为开发板分配的虚拟地址:推流端口号/live/main_stream,即可正常观看,效果图如下:

六、流程梳理与原理总结

流程总结:摄像头 -> FFmpeg -> MediaMTX -> ZeroTier虚拟网卡 -> 互联网加密隧道 -> 手机的ZeroTier虚拟网卡 -> VLC播放器

  • 摄像头: 硬件设备,负责捕捉现实世界的动态画面,并将其转换成原始的数字视频信号。

  • FFmpeg: 一款强大的视频处理工具,在这里它扮演“编码和推送”的角色,将摄像头的原始信号实时编码成高效的H.264网络视频格式,然后主动推送到MediaMTX服务器。

  • MediaMTX: 一个轻量级的流媒体服务器,在这里它作为“分发中心”,接收来自FFmpeg的视频流,并按照RTSP协议,准备好随时将它分发给前来请求的播放器。

  • ZeroTier虚拟网卡 (开发板端): 这是数据的“加密打包站”,它将MediaMTX准备好的视频流数据进行加密和封装,准备通过ZeroTier的私人网络发出去。

  • 互联网加密隧道: 这是ZeroTier建立的“私人高速公路”,视频数据包在这条点对点的加密通道中,安全、直接地从您家里的网络穿梭到您手机所在的网络。

  • 手机的ZeroTier虚拟网卡: 这是数据的“解密接收站”,它接收从隧道传来的加密数据包,将其解密还原成原始的视频流数据,然后交给手机的操作系统。

  • VLC播放器: 最终的“电视机”,它向开发板的ZeroTier虚拟IP地址发起播放请求,接收到解密后的视频流数据,并将其解码、呈现在您的手机屏幕上。

这套方案的原理是:首先在开发板上用 FFmpegMediaMTX 搭建一个本地RTSP“电视台”,然后通过 ZeroTier 建立一个跨越互联网的加密虚拟局-域网,最后让您的手机VLC通过分配到的虚拟IP地址,直接“收看”这个电视台的节目,从而实现安全、免费的远程监控。

七:心得体会

经历了上述所有挑战后,我终于实现了最初的目标。现在,无论我身在何处,只要手机有网络,就能随时打开VLC,输入 rtsp://为开发板分配的虚拟地址:推流端口号/live/main_stream,看到RV1126上的摄像头采集到的实时画面。

这套推流方案有以下优点:

  • 高度安全 :无需在路由器上暴露任何公网端口,所有视频流都经过端到端加密,只有您授权的设备才能访问,从根本上杜绝了被攻击的风险。

  • 零成本运行 : 核心软件(ZeroTier, FFmpeg等)完全免费,没有商业摄像头常见的云存储或月度订阅费用,实现了永久的免费远程访问。

  • 数据主权与灵活性 : 完全控制自己的视频数据,它不会上传到任何第三方服务器。同时,整套系统不受任何厂商限制,您可以自由更换硬件、软件和定制功能。

  • 强大的网络适应性 : 无需公网IP,无论您家里的网络环境多么复杂,也无论您的手机在任何地方(4G、5G、Wi-Fi),都可以通过一个固定的虚拟IP地址稳定连接。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值