用webrtc展示FFmpeg + MediaMTX 反向推流跨网段监控视频流

47 阅读5分钟

关于大屏视频监控有四种解决方案:

1.海康威视 优点:实时性强。多画面运行流畅,缺点:会覆盖在DOM最上方无法选中可能会导致样式挤压变形等样式问题

2.[flv视频流]+[nodeServer] 优点:可配置性强 缺点:服务端大流量稳定性不确定

3.rtsp视频流(默认带声音播放) 优点:插件稳定,可网页调试视频流; 缺点:需向后端发送rtsp地址

4.webrtc视频流 优点:可在服务器端配置账户密码生成rtsp安全性高不占用CPU/GPU;纯 IO + 网络开销; 缺点:需服务端配置有启动依赖

背景:WIFI_AP是 AP+AC的局域网10.4.85.X(后面简称:网A)

      WIFI_01是单台设备网卡直连网A后的设备01发出的WIFI(网B)

已实现:连网B,192.168.10.X摄像头画面正常,A-》B 是通的

需求:连网A如何访问摄像头?

优点:将账户密码统一放到服务端,安全性比较高。缺点:对服务器压力会比较到,因为是自推流然后转发自拉读取

目标说明:

本方案用于解决:摄像头位于192.168.10.X子网(网B),而上级网络10.4.85.X(网A)无法直接访问的情况。通过使用 FFmpeg 主动拉取摄像头 RTSP 视频流,再推送至MediaMTX,由B统一对外提供视频访问服务。

一、FFmpeg 下载与配置

1.1 下载地址:www.gyan.dev/ffmpeg/buil…

image.png 1.2、目录结构准备

在 远程连接进入单台设备D 盘创建如下目录:

D:\WIFI_01\ffmpeg

D:\WIFI_01\mediamtx

1.3. 解压后将 bin 目录中的 ffmpeg.exe等 拷贝至 D:\WIFI_01\ffmpeg

image.png

1.4. 管理员 CMD 中执行 ffmpeg -version 验证是否可用

1.5. 创建rtsp_push.bat,写入以下内容,后期开机自启会用到

@echo off
chcp 65001 >nul
title FFmpeg RTSP → MediaMTX

set FFMPEG=D:\WIFI_01\ffmpeg\ffmpeg.exe
set SRC_RTSP=rtsp://admin:密码@192.168.10.98:554/Streaming/Channels/101
set DST_RTSP=rtsp://127.0.0.1:8554/hikcam

:loop
echo [%date% %time%] 启动 FFmpeg...

"%FFMPEG%" ^
-rtsp_transport tcp ^
-i "%SRC_RTSP%" ^
-map 0:v:0 ^
-c:v copy ^
-f rtsp ^
-rtsp_transport tcp ^
"%DST_RTSP%"

echo [%date% %time%] FFmpeg 退出,5 秒后重启
timeout /t 5 >nul
goto loop

1.6 双击 rtsp_push.bat 后会启动FFmpeg开始推流 image.png 到这步 只是把网B推流到网A。还需要配置MediaMTX

二、MediaMTX 下载与配置

2.1. 下载地址:github.com/bluenviron/…

2.2. 下载 Windows amd64 版本(根据自身的系统下载对应版本)

image.png 2.3. 解压至 D:\WIFI_01\mediamtx

image.png

@echo off
REM =========================================
REM MediaMTX 启动脚本(用于 Windows 服务)
REM =========================================

REM 切换到 MediaMTX 目录
cd /d D:\WIFI_01\mediamtx

REM 启动 MediaMTX(指定配置文件)

mediamtx.exe mediamtx.yml
  1. 修改 mediamtx.yml 内容如下:(这里的paths是自定义,例如:hikcam 是推流用的)
paths:

hikcam:

source: publisher

三、启动 MediaMTX

管理员 CMD 执行:

cd D:\WIFI_01\mediamtx

mediamtx.exe

或双击run_mediamtx.bat启动

会看到 8554、8889 端口监听信息表示启动成功

MediaMTX开启了下列五项流媒体服务:
1、侦听8554端口的RTSP服务,对应的流媒体播放地址是rtsp://127.0.0.1:8554/stream ;
2、侦听1935端口的RTMP服务,对应的流媒体播放地址是rtmp://127.0.0.1:1935/stream ;
3、侦听8888端口的HLS服务,对应的流媒体播放地址有两个,其中http://127.0.0.1:8888/stream 可以直接通过浏览器播放(比如Chrome),另一个http://127.0.0.1:8888/stream/index.m3u8 需要用播放器打开。
4、侦听8889端口的WebRTC服务;
5、侦听8890端口的SRT服务;

image.png

四、访问方式验证

这个地址的拼接规则是:rtsp://IP:8554/paths

可得出:

网B本机:rtsp://127.0.0.1:8554/hikcam

网A其他设备:rtsp://10.4.85.X:8554/hikcam

可通过VSPlayer播放器验证rtsp视频流是否推送正常

image.png image.png image.png

五,通过webtrc在vue实时展示视频画面(可用生成后的 地址解析视频流,不会暴露账户密码。)

5.1 新建 index.vue

<template>
    <div class="screen">
      <CameraPlayer
        v-for="cam in camerList"
        :key="cam.title"
        :title="cam.title"
        :path="cam.path"
        :server="cam.server"
      />
    </div>
  </template>
  
  <script>
  import CameraPlayer from './CameraPlayer.vue'
  
  export default {
    components: { CameraPlayer },
    data() {
      return {
        camerList: [
          {
            title: '1# 机器人',
            path: 'hikcam',
            server: 'http://10.4.85.x1:8889'
          },
          {
            title: '2# 机器人',
            path: 'hikcam',
            server: 'http://10.4.85.x2:8889'
          }
        ]
      }
    }
  }
  </script>
  
  <style scoped>
  .screen {
    width: 100vw;
    height: 100vh;
    background: #0b0f14;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    padding: 12px;
  }
  </style>
  

5.2 新建 CameraPlayer.vue

<template>
  <div class="camera-box" ref="box" @click="toggleFullscreen">
    <div class="title">{{ title }}</div>
    <video ref="video" autoplay playsinline muted></video>
  </div>
</template>

<script>
export default {
  props: {
    path: { type: String, required: true },
    title: { type: String, default: '' },
    server: { type: String, required: true }
  },
  mounted() {
    this.start()
  },
  beforeDestroy() {
    if (this.pc) {
      this.pc.close()
      this.pc = null
    }
  },
  methods: {
    async start() {
      try {
        const pc = new RTCPeerConnection()
        this.pc = pc

        pc.ontrack = e => {
          this.$refs.video.srcObject = e.streams[0]
        }

        pc.addTransceiver('video', { direction: 'recvonly' })

        const offer = await pc.createOffer()
        await pc.setLocalDescription(offer)

        const res = await fetch(
          `${this.server}/${this.path}/whep`,
          {
            method: 'POST',
            headers: { 'Content-Type': 'application/sdp' },
            body: offer.sdp
          }
        )

        if (!res.ok) {
          throw new Error(`WHEP failed: ${this.path}`)
        }

        const answer = await res.text()
        await pc.setRemoteDescription({
          type: 'answer',
          sdp: answer
        })
      } catch (err) {
        console.error(this.path, err)
      }
    },
    toggleFullscreen() {
      const el = this.$refs.box

      if (!document.fullscreenElement) {
        el.requestFullscreen?.()
      } else {
        document.exitFullscreen?.()
      }
    }
  }
}
</script>

<style scoped>
.camera-box {
  background: #000;
  border-radius: 6px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* 固定标题高度 */
.title {
  height: 36px;
  line-height: 36px;
  padding: 0 10px;
  font-size: 14px;
  color: #fff;
  background: #141a22;
  flex-shrink: 0;
}

video {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: contain;
  background: #000;
}
</style>

打开后可以正常读取监控实时画面

image.png

六、Windows 防火墙放行(一般不用配置这一步,除非防火墙拦截)

管理员 CMD 执行:

netsh advfirewall firewall add rule name='MediaMTX RTSP' dir=in action=allow protocol=TCP localport=8554

netsh advfirewall firewall add rule name='MediaMTX HTTP' dir=in action=allow protocol=TCP localport=8888

七、常见问题说明

7.1. 无法拉流:检查摄像头 IP、账号密码及网络是否正常

7.2. 本机可看外部不可看:检查 Windows 防火墙端口放行情况

7.3. 推流不稳定:可将 -c copy 改为 H264 转码方式提高稳定性

gitee资源下载 | 摄像头IP搜索工具| 浏览器插件