web浏览器播放rtsp视频流,海康监控API

概述

这里记录一下如何让前端播放rtsp协议的视频流

​ 项目中调用海康API,生成的视频流(hls、ws、rtmp等)通过PotPlayer播放器都无法播放,说明视频流有问题,唯独rtsp视频流可以播放。

但是浏览器本身是无法播放rtsp视频的,即使是使用videojs、flvjs等工具。

​ 网上的方案都是通过后端基于ffmpeg工具进行转码。那么我的理解是后端Node起到的是中转作用:调用ffmpeg工具对传入的rtsp流进行转码再传给前端

这里记录整个过程与出现的问题解决

准备

需要三部分的准备:

  • ffmpeg工具
  • nodeJS转码
  • 前端播放

ffmpeg安装与配置

  1. 下载ffmpeg https://ffmpeg.org/download.html


  1. 下载并解压完成后

    我这里放在 D:\DevelopSoftware\ffmpeg

  2. 配置环境变量

    我的电脑 => 属性 => 高级系统设置 => 环境变量 => Path => 添加 D:\DevelopSoftware\ffmpeg\bin

  3. 打开cmd输入 ffmpeg 或者 ffmpeg -version

    出现东西就说明OK了

    如果 'ffmpeg' 不是内部或外部命令,也不是可运行的程序或批处理文件, 重启cmd窗口, 还是不行的话网上搜一下吧

本节参考自 ffmpeg安装教程(windows版)

nodejs编写转码服务

先随便建个文件夹

npm i express express-ws fluent-ffmpeg websocket-stream

或者

yarn add express express-ws fluent-ffmpeg websocket-stream

新建 index.js

typescript 复制代码
var express = require('express')
var expressWebSocket = require('express-ws')
var ffmpeg = require('fluent-ffmpeg')
var webSocketStream = require('websocket-stream/stream')
var WebSocket = require('websocket-stream')
var http = require('http')

ffmpeg.setFfmpegPath('ffmpeg')

// config
let rtspServerPort = 2156

function localServer() {
  let app = express()
  app.use(express.static(__dirname))
  expressWebSocket(app, null, {
    perMessageDeflate: true
  })
  // :id是动态参数, 前端调用时传递, 可以去掉
  app.ws('/rtsp/:id/', rtspRequestHandle)
  app.listen(rtspServerPort)
  console.log('express listened on port : ' + rtspServerPort)
}

function rtspRequestHandle(ws, req) {
  console.log('rtsp request handle')
  const stream = webSocketStream(
    ws,
    {
      binary: true,
      browserBufferTimeout: 1000000
    },
    {
      browserBufferTimeout: 1000000
    }
  )

  let url = req.query.url
  console.log('rtsp url:', url)
  console.log('rtsp params:', req.params)
  try {
    ffmpeg(url)
      .addInputOption('-rtsp_transport', 'tcp', '-buffer_size', '102400') // 这里可以添加一些 RTSP 优化的参数
      .on('start', function () {
        console.log(url, 'Stream started.')
      })
      .on('codecData', function () {
        console.log(url, 'Stream codecData.')
        // 摄像机在线处理
      })
      .on('error', function (err) {
        console.log(url, 'An error occured: ', err.message)
      })
      .on('end', function () {
        console.log(url, 'Stream end!')
        // 摄像机断线的处理
      })
      .outputFormat('flv')
      .videoCodec('copy')
      .noAudio()
      .pipe(stream)
  } catch (error) {
    console.log(error)
  }
}

localServer()

运行

node index.js

前端调用转码服务

新建 demo.html

html 复制代码
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script src="https://cdn.bootcdn.net/ajax/libs/flv.js/1.6.2/flv.min.js"></script>
    <!--  <script src="./js/flv.min.js"></script>-->
    <style>
      body,
      center {
        padding: 0;
        margin: 0;
      }

      .v-container {
        width: 640px;
        height: 360px;
        border: solid 1px red;
      }

      video {
        width: 100%;
        height: 100%;
      }
    </style>
  </head>
  <body>
    <div class="v-container">
      <video id="player1" muted autoplay="autoplay" preload="auto" controls="controls"></video>
    </div>

    <script>
      if (flvjs.isSupported()) {
        var videoElement = document.getElementById('player1')
        var flvPlayer = flvjs.createPlayer({
          type: 'flv',
          url: 'ws://localhost:2156/rtsp/111/?url=rtsp://xxx.xxx.xxx:554/openUrl/jmQgiJi'
        })
        flvPlayer.attachMediaElement(videoElement)
        flvPlayer.load()
      }
    </script>
  </body>
</html>

这两节源自 rtsp视频服务 基于node+ffmpeg 转换为 flv 视频服务

videojs + flvjs使用

yarn add video.js flv.js videojs-flvjs-es6

typescript 复制代码
import videojs from 'video.js'
import flvjs from 'flv.js'
import 'video.js/dist/video-js.css'
import 'videojs-flvjs-es6'

let myPlayer

const initVideo = (videoUrl) => {
  // videojs初始化
  myPlayer = videojs(
    document.querySelector('#videoBox'),   // video元素, vue2或vue3推荐使用ref方式
    {
      // poster: '//vjs.zencdn.net/v/oceans.png',
      autoplay: 'muted', //自动播放
      controls: true, //用户可以与之交互的控件
      loop: true, //视频一结束就重新开始
      muted: true, //默认情况下将使所有音频静音
      // aspectRatio: '16:9', //显示比率
      techOrder: ['html5', 'flvjs'], // 兼容顺序
      flvjs: {
        mediaDataSource: {
          cors: true,
          withCredentials: false,
        },
      },
      controlBar: {
        remainingTimeDisplay: {
          displayNegative: false,
        },
      },
      playbackRates: [0.5, 1, 1.5, 2],
    },
    function onPlayerReady() {
      this.on('play', function () {
        console.log('视频开始播放')
      })
      this.on('pause', function () {
        console.log('视频暂停播放')
      })
      this.on('error', function () {
        console.log('加载错误')
        isError.value = true
      })
    }
  )

  // 播放
  myPlayer.reset()
  myPlayer.src({
    src: 'ws://localhost:2156/rtsp/?url=' + videoUrl,
    type: 'video/x-flv',
  })
  // myPlayer.load('ws://localhost:2156/rtsp/1/?url=rtsp://xxxx:554/openUrl/rMYr6w0')
  myPlayer.play()
}
html 复制代码
<video ref="videoPlayer" id="videoBox" style="width:100%;height:100%;"></video>

总结

海康平台支持多种协议的视频流,如果流无法播放,可能是设备配置或者分辨率或者... 出了问题!!

这种事情当然是让后端去处理咯,是跟厂商联调还是怎么着,关我前端啥事儿!!!把精力用到更有意义的地方才是正解,例如像我一样水一篇文章, Nice!

当然,尽量直接使用海康平台API返回的流,转码始终是下策。

感谢各大佬的文章:

rtsp视频服务 基于node+ffmpeg 转换为 flv 视频服务

ffmpeg安装教程(windows版)

相关推荐
程序员黑豆5 小时前
Java类型推断完全指南:从var到菱形运算符,掌握使用限制与最佳实践
java·前端·ai编程
To_OC6 小时前
踩了个 TS 的坑之后,我终于把 type 和 interface 掰明白了
前端·react.js·typescript
GreenTea6 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
浮生望6 小时前
前端API工程化:用 Mock 数据与 Axios 配置实现独立于后端的并行开发
前端
万少7 小时前
给 DeepSeek Harness 装个"应用商店":一条命令,595 个插件随你逛
前端·javascript·后端
波波0077 小时前
C# 15 重磅新特性: 带标签 break 与 continue:重新定义嵌套循环控制流
服务器·前端·c#
Brown.alexis8 小时前
es6知识点1-自备使用
前端·ecmascript·es6
小爬的老粉丝9 小时前
JavaScript 纯前端预览 WPS:先识别容器,再路由解析器
前端·javascript·wps
计算机魔术师9 小时前
新兴多智能体系统的模式与问题
前端
用户0595401744610 小时前
AI Agent 上下文污染踩坑实录:用 pytest + Redis 揪出 3 类记忆串号 bug,排查 6 小时
前端·css