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版)

相关推荐
放逐者-保持本心,方可放逐几秒前
vue3 中那些常用 靠copy 的内置函数
前端·javascript·vue.js·前端框架
IT古董几秒前
【前端】vue 如何完全销毁一个组件
前端·javascript·vue.js
Henry_Wu0013 分钟前
从swagger直接转 vue的api
前端·javascript·vue.js
SameX12 分钟前
初识 HarmonyOS Next 的分布式管理:设备发现与认证
前端·harmonyos
M_emory_39 分钟前
解决 git clone 出现:Failed to connect to 127.0.0.1 port 1080: Connection refused 错误
前端·vue.js·git
Ciito42 分钟前
vue项目使用eslint+prettier管理项目格式化
前端·javascript·vue.js
成都被卷死的程序员1 小时前
响应式网页设计--html
前端·html
mon_star°2 小时前
将答题成绩排行榜数据通过前端生成excel的方式实现导出下载功能
前端·excel
Zrf21913184552 小时前
前端笔试中oj算法题的解法模版
前端·readline·oj算法
爱编程的鱼3 小时前
Node.js事件循环:解锁异步编程的奥秘
node.js