【linux】RK3568(五)云服务器-视频推流

文章目录

1. 公网IP

  • 从公司(外网)访问家里的监控设备,核心难题是:家里的设备通常处于内网,没有独立公网IP
  • 方案一:Tailscale / ZeroTier 组网方案 ⭐ 开发者首选
    本质:基于WireGuard的虚拟组网(Overlay Network),让公司设备"假装"在家里的局域网中。
  • 方案二:FRP 内网穿透 ⭐ 开发者备选方案
    本质:自建反向代理服务器,通过云服务器中转流量。
  • 方案三:P2P云直连(厂商SDK集成) ⭐ 快速出活
    本质:使用摄像头厂商的P2P云服务,通过SDK接入。
  • 方案四:端口映射 + DDNS(公网IP方案)
    本质:直接在路由器上开放摄像头端口,用DDNS解决IP变动。
  • 手机4G网络:是内网还是外网?
    4G网络是运营商级内网(CGNAT),没有独立的公网IP。
  • 4G网络 vs 家宽网络
    手机(10.x.x.x) ─→ 运营商NAT ─→ 公网IP ─→ 互联网
    家宽(192.168.x) ─→ 路由器NAT ─→ 运营商NAT ─→ 公网IP

2.云服务器拥有公网IP

阿里云
  • 配置防火墙-添加规则
    开放一个TCP端口(例如 7000),这是FRP服务端将要监听的端口。授权对象可设置为 0.0.0.0/0

7000:FRP服务端与客户端通信的端口。

8554:你希望外部访问RTSP视频流的端口

FRP

FRP方案成熟可靠吗?

是的,非常成熟可靠。

久经考验:FRP是一个发展多年、广泛使用的开源项目。其设计目标就是为了应对生产环境,性能稳定,适合长期运行。

行业认可:它被评价为"国内最稳的内网穿透开源方案"和"高性能自托管解决方案",很多开发者用它来远程访问NAS或进行远程办公。

性能强劲:FRP采用Go语言开发,支持高并发。在P2P模式下,同运营商网络的延迟可以低至50ms以内。带宽取决于你的云服务器,没有额外限制。

安全可控:FRP支持TLS加密传输、Token认证和IP白名单等多种安全机制。由于所有流量都经过你自己的云服务器,数据安全完全由你掌控。

🤔 为什么需要在本地和云端都安装?

这是由FRP的内网穿透原理决定的,它需要在两个地方各司其职。

云服务器上的 frps (服务端):它就像一个 "接线总机" ,拥有固定的公网"号码"(IP地址)。它的任务是等待来自外网(你的手机)和内网(你家开发板)的连接,并进行"通话"转接。

开发板上的 frpc (客户端):它像一个 "分机" ,主动拨打"总机"frps的号码,并建立一条保持畅通的"热线"(即隧道)。这条"热线"让frps随时能把外网的访问请求转接过来

  • 下载frp
  • 在阿里云服务器上下载(服务端)
c 复制代码
# 下载 amd64 版本
wget https://github.com/fatedier/frp/releases/download/v0.71.0/frp_0.71.0_linux_amd64.tar.gz

# 解压
tar -xzf frp_0.71.0_linux_amd64.tar.gz

# 进入目录
cd frp_0.71.0_linux_amd64

# 查看文件,应该有 frps(服务端)和 frpc(客户端)
ls -l
  • 在开发板上(客户端)

请根据你的开发板架构下载对应版本。若不确认,可在开发板终端执行 uname -m,若显示 aarch64 则下载 arm64 版本

c 复制代码
# 下载 arm64 版本(示例)
wget https://github.com/fatedier/frp/releases/download/v0.71.0/frp_0.71.0_linux_arm64.tar.gz

# 解压
tar -xzf frp_0.71.0_linux_arm64.tar.gz

# 进入目录
cd frp_0.71.0_linux_arm64

3. wget下载

  • 所有GitHub Release的下载链接都有一个固定的标准格式:

https://github.com/用户名/仓库名/releases/download/版本号/文件名

以你的截图为例:

用户名:fatedier

仓库名:frp

版本号:v0.71.0

文件名:frp_0.71.0_linux_amd64.tar.gz

把它们拼起来,就是完整的下载链接:

https://github.com/fatedier/frp/releases/download/v0.71.0/frp_0.71.0_linux_amd64.tar.gz

所以,只要你在页面上看到了文件名,用这个公式就能构造出任何文件的下载地址。

4.配置云-frps 服务端

配置云服务器(frps 服务端)

  1. 进入 FRP 目录

    cd ~/frp_0.71.0_linux_amd64

  2. 创建配置文件 frps.toml

    vim frps.toml

  3. 内容

c 复制代码
bindPort = 7000
auth.method = "token"
auth.token = "your_secure_token_here"   # 请修改为一个强密码,例如用命令 openssl rand -hex 16 生成

注意:auth.token 是服务端和客户端互相认证的凭证,务必保持一致。

  1. 启动 frps 服务(前台测试)
    ./frps -c frps.toml
    如果看到类似 start frps success 的日志,说明服务端启动成功。按 Ctrl+C 停止,然后我们设置为后台服务
  2. 设置开机自启(systemd)
c 复制代码
# ─── 复制二进制文件到系统路径 ───
sudo cp frps /usr/local/bin/    # 将 frps(FRP 服务端程序)复制到 /usr/local/bin/,此目录在系统 PATH 中,可直接执行

# ─── 创建配置文件目录 ───
sudo mkdir -p /etc/frp/          # 创建 FRP 配置文件夹 /etc/frp/,-p 表示如果父目录不存在则自动创建

# ─── 复制配置文件到指定目录 ───
sudo cp frps.toml /etc/frp/      # 将 frps.toml(FRP 服务端配置文件)复制到 /etc/frp/ 目录下

# ─── 创建 systemd 服务文件(让 frps 作为系统服务开机自启) ───
sudo vim /etc/systemd/system/frps.service   # 用 vim 编辑器创建 service 文件,路径是 systemd 服务定义的标准位置

# ─── service 文件内容如下 ───
[Unit]                                        # Unit 段:描述服务信息和依赖关系
Description=frp server                        # 服务描述:FRP 服务端
After=network-online.target                   # 在"网络完全就绪"之后才启动此服务
Wants=network-online.target                   # 弱依赖:建议网络就绪后再启动,但不是强制要求

[Service]                                     # Service 段:定义如何运行此服务
Type=simple                                   # 启动类型为 simple(执行 ExecStart 后即认为服务已启动)
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml   # 启动命令:执行 frps,加载 /etc/frp/ 下的配置文件
Restart=on-failure                            # 重启策略:非正常退出时自动重启(进程崩溃或退出码非0)
RestartSec=5s                                 # 重启间隔:等待 5 秒后再重启,防止频繁重启打满 CPU

[Install]                                     # Install 段:定义服务安装/启用的行为
WantedBy=multi-user.target                    # 设置此服务在"多用户模式下"自动启动(即系统正常启动后运行)

# ─── 保存退出后执行以下命令 ───

sudo systemctl daemon-reload                  # 重新加载 systemd 配置,让新创建的 frps.service 生效
sudo systemctl enable --now frps              # enable = 设置开机自启;--now = 立即启动服务,相当于 enable + start 二合一
sudo systemctl status frps                    # 查看服务运行状态,输出中应显示 active (running),表示运行正常

虽然这台云服务器只做监控,但作为中转服务器,它需要7×24小时持续监听,等待你家开发板和手机随时连接。如果只是前台挂着,SSH断开连接进程就会终止,整个远程监控就失效了。

所以,虽然只做监控,但服务需要长期稳定运行,必须后台化。

5. 配置本地-frpc 客户端

  1. 进入 FRP 客户端目录

    cd ~/frp_0.71.0_linux_arm64 # 或你解压的目录

  2. 创建配置文件 frpc.toml

    vim frpc.toml

  3. 内容

c 复制代码
serverAddr = "你的云服务器公网IP"   # 例如 123.123.123.123
serverPort = 7000
auth.token = "your_secure_token_here"   # 与服务器端一致

[[proxies]]
name = "rtsp_stream"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8554          # 开发板上 MediaMTX 的 RTSP 端口
remotePort = 8554         # 云服务器上对外暴露的端口
  1. 启动 frpc 客户端(前台测试)
    ./frpc -c frpc.toml

如果看到 login to server success 和 start proxy success 的日志,说明连接成功。按 Ctrl+C 停止,然后设为后台服务。

6.视频流

数据流向是这样的:

摄像头 → FFmpeg → MediaMTX (RTSP服务器) → frpc (客户端) → 云服务器 → 手机VLC

  1. 运行 MediaMTX

    ./mediamtx

  2. H.264 软编码推流命令

c 复制代码
ffmpeg -re -f v4l2 -input_format mjpeg -video_size 1280x720 -framerate 30 -i /dev/video0 \
-c:v libx264 -preset ultrafast -tune zerolatency -crf 25 -b:v 2M -g 60 \
-f rtsp -rtsp_transport tcp rtsp://127.0.0.1:8554/live
  1. 访问公网IP
    手机 VLC 访问 rtsp://88.88.888.88:8554/live
  • 效果:延迟画面2-3秒,但是很流畅

7. 整体数据流向

整体数据流向(理解架构)

摄像头硬件 → FFmpeg (采集+H.264编码) → MediaMTX (本机RTSP服务器) → frpc (FRP客户端) → 公网云服务器 (frps) → 手机VLC (远程拉流)

8.开发板上电启动

所有文件放在 /home/baiwen/video1/

/home/baiwen/video1/

├── mediamtx # MediaMTX 可执行文件

├── mediamtx.yml # MediaMTX 配置文件

├── frp_0.71.0_linux_arm64/ # FRP 客户端目录

│ └── frpc

│ └── frpc.toml

└── start_camera.sh # 开机自启脚本

  1. 编写开机自启脚本 创建 /home/baiwen/video1/start_camera.sh
c 复制代码
#!/bin/bash
# ============================================================
# 开发板摄像头开机自启脚本(通俗易懂版)
# 功能:开机后检测网络 -> 启动 MediaMTX -> 启动 frpc -> 启动 ffmpeg
# 所有日志都会写入 /home/baiwen/video1/camera.log
# ============================================================

# 定义日志文件的路径,所有输出都写到这里
LOG_FILE="/home/baiwen/video1/camera.log"

# 把脚本本身的标准输出和错误输出,都重定向追加到日志文件
# 这样后面所有 echo 打印的内容,都会自动进入 camera.log
exec >> "$LOG_FILE" 2>&1

# 定义一个函数 log,用来打印带时间戳的日志
# 用法:log "要打印的内容"
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}

# 定义一个函数 cleanup,用于在服务被停止时,清理所有子进程
# 这个函数会在脚本收到 SIGTERM 或 SIGINT 信号时被调用
cleanup() {
    log "收到终止信号,正在停止所有服务..."

    # kill 命令:向三个进程发送终止信号
    # 2>/dev/null 表示如果进程不存在,错误信息不打印
    kill $MEDIAMTX_PID $FRPC_PID $FFMPEG_PID 2>/dev/null

    # wait 命令:等待这三个进程完全退出
    wait $MEDIAMTX_PID $FRPC_PID $FFMPEG_PID 2>/dev/null

    log "所有服务已停止。"
    exit 0
}

# trap 命令:告诉脚本,当收到 SIGTERM(systemctl stop 时发送)或 SIGINT(Ctrl+C)时,
# 自动执行 cleanup 函数
trap cleanup SIGTERM SIGINT

# 打印一条启动分隔线,方便在日志中区分每次启动
echo "=========================================="
log "系统启动,开始执行摄像头推流脚本"

# 定义要检测的目标IP(你的阿里云公网IP)
TARGET_IP="47.108.128.94"
log "开始检测网络(目标:$TARGET_IP)..."

# 循环最多 30 次,每次间隔 2 秒,总共等待最多 60 秒
for i in {1..30}
do
    # ping 一次目标IP,-c 1 表示只发一个包,-W 1 表示超时1秒
    # > /dev/null 2>&1 表示丢弃 ping 的所有输出(不打印)
    ping -c 1 -W 1 "$TARGET_IP" > /dev/null 2>&1

    # $? 表示上一条命令的执行结果,0 代表成功
    if [ $? -eq 0 ]; then
        log "网络已连通(尝试 $i 次)"
        break   # 网络通了就跳出循环,不再继续等待
    fi

    # 如果已经试了 30 次还没通,就放弃启动
    if [ $i -eq 30 ]; then
        log "网络超时,退出脚本"
        exit 1
    fi

    # 每次循环末尾等待 2 秒
    sleep 2
done

# ---------- 启动 MediaMTX(RTSP 服务器) ----------
# 进入 video1 目录,如果进不去就记日志并退出
cd /home/baiwen/video1
if [ $? -ne 0 ]; then
    log "无法进入 /home/baiwen/video1 目录"
    exit 1
fi

log "启动 MediaMTX ..."

# 用 & 把 mediamtx 放到后台运行
# 不加 nohup,让它可以作为脚本的子进程被 systemd 管理
./mediamtx &

# $! 表示刚刚放到后台的进程的 PID
MEDIAMTX_PID=$!
log "MediaMTX PID: $MEDIAMTX_PID"

# 等待 2 秒,让 MediaMTX 完成端口绑定
sleep 2

# ---------- 启动 frpc(FRP 客户端) ----------
# 进入 frp 目录
cd /home/baiwen/video1/frp_0.71.0_linux_arm64
if [ $? -ne 0 ]; then
    log "找不到 /home/baiwen/video1/frp_0.71.0_linux_arm64 目录"
    exit 1
fi

log "启动 FRP 客户端 ..."

# 后台启动 frpc,并把它的输出也写到同一个日志文件
./frpc -c frpc.toml &

FRPC_PID=$!
log "FRP 客户端 PID: $FRPC_PID"

# 等待 3 秒,让 frpc 和云服务器建立连接
sleep 3

# ---------- 启动 ffmpeg(视频推流) ----------
# 回到 video1 目录
cd /home/baiwen/video1

log "启动 FFmpeg 视频推流 ..."

# 后台启动 ffmpeg,参数说明:
# -re                  : 按实时速度读取摄像头
# -f v4l2              : 使用 V4L2 驱动
# -input_format mjpeg  : 输入格式为 MJPEG
# -video_size 1280x720 : 分辨率 720P
# -framerate 30        : 帧率 30 fps
# -i /dev/video0       : 摄像头设备
# -c:v libx264         : 使用 H.264 软件编码
# -preset ultrafast    : 编码速度优先(降低 CPU 占用)
# -tune zerolatency    : 零延迟调优
# -crf 25              : 画质因子,数字越大画质越低
# -b:v 2M              : 目标码率 2 Mbps
# -g 60                : 每 60 帧一个关键帧(2秒)
# -f rtsp              : 输出为 RTSP
# -rtsp_transport tcp  : 强制使用 TCP 传输
# 最后是推流地址
ffmpeg -re -f v4l2 -input_format mjpeg -video_size 1280x720 -framerate 30 \
    -i /dev/video0 \
    -c:v libx264 -preset ultrafast -tune zerolatency -crf 25 -b:v 2M -g 60 \
    -f rtsp -rtsp_transport tcp rtsp://127.0.0.1:8554/live &

FFMPEG_PID=$!
log "FFmpeg PID: $FFMPEG_PID"

log "所有服务已启动,进入守护等待状态..."
echo "=========================================="

# ---------- 关键:让脚本保持运行 ----------
# wait 命令不带参数,会一直等待所有后台子进程
# 这样脚本不会退出,systemd 就会认为服务还在运行,
# 不会把 MediaMTX、frpc、ffmpeg 这些子进程干掉
wait
  1. 赋予执行权限
    chmod +x /home/baiwen/video1/start_camera.sh
  • 转换 Windows 换行符(如果从 Windows 复制)
    sed -i 's/\r$//' /home/baiwen/video1/start_camera.sh
  1. 设置 systemd 服务
    创建 /etc/systemd/system/camera.service
  • sudo vim /etc/systemd/system/camera.service
c 复制代码
[Unit]
Description=Camera Auto Streaming Service
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=baiwen
ExecStart=/home/baiwen/video1/start_camera.sh
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
  1. 启用开机自启
    sudo systemctl daemon-reload
    sudo systemctl enable camera.service
    sudo systemctl start camera.service # 立即启动测试
  • 查看日志
    所有日志集中在 /home/baiwen/video1/camera.log
  1. 在手机 VLC 中打开网络串流实时查看
相关推荐
赵民勇1 小时前
resolvectl命令详解
linux·运维
新时代牛马1 小时前
Linux 日志管理:journald、rsyslog 与 logrotate
linux·运维·服务器
资深电气设计1 小时前
技术解析:ABB变频器ACH580/ACS180在CDU循环泵系统的应用技术框架
linux·运维·服务器
自律最差的编程狗1 小时前
Ubuntu下Docker部署Ollama 轻量模型
linux·ubuntu·docker
新时代牛马1 小时前
Linux 网络配置:iproute2、DNS 与连通性排障
linux·服务器·网络
新时代牛马1 小时前
Linux systemd 服务管理:从unit 文件到systemctl 启停与排障
linux·服务器·网络
光电笑映2 小时前
Linux 线程同步与互斥:锁的本质、条件变量与信号量的底层原理
linux·运维·服务器·开发语言·c++
kaoa0003 小时前
Linux入门攻坚——89、Hadoop-1-架构及概念
大数据·linux·hadoop·分布式
茶马古道的搬运工3 小时前
Linux-Ubantu-贴士-SSH 免密登录与端口修改
linux