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

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 = 2156function 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.urlconsole.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

<!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

import videojs from 'video.js'
import flvjs from 'flv.js'
import 'video.js/dist/video-js.css'
import 'videojs-flvjs-es6'let myPlayerconst 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()
}
<video ref="videoPlayer" id="videoBox" style="width:100%;height:100%;"></video>

总结

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

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

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

感谢各大佬的文章:

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

ffmpeg安装教程(windows版)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/390889.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++——异常

前言&#xff1a;本篇文章我们来分享C的一个全新内容——异常。 目录 一.异常概念 二.异常的使用 1.异常的抛出和匹配原则 2.在函数调用链中异常栈展开匹配原则 3.异常的重新抛出 三.异常的优缺点 1.优点 2.缺点 结语 一.异常概念 异常是一种处理错误的方式&#xff…

完成QT上位机(八)

一. 正式开始设计界面 这一章节我们将完成QT上位机的设计&#xff0c;如果有同学对QtCreater的使用不太熟悉的&#xff0c;可以参考下面的链接 Qt 快速入门系列教程 Qt 快速入门系列教程 (gitbooks.io)https://wizardforcel.gitbooks.io/qt-beginning/content/ 二. 数据库处…

自动气象站:高度自动化、智能化和精准化

自动气象站&#xff0c;作为科技进步的产物&#xff0c;以其高度的自动化、智能化和精准化特点&#xff0c;极大地提升了气象观测的效率和准确性。它集成了多种高精度传感器&#xff0c;能够全天候、不间断地监测温度、湿度、气压、风速、风向、降水量等关键气象要素&#xff0…

小试牛刀-Telebot区块链游戏机器人(TS升级)

目录 1.编写目的 2.为什么使用TypeScript实现? 3.实现功能 3.1 AI图片生成 3.2 签到 3.3 邀请 3.4 WalletConnect连接 4.功能实现详解 4.1 AI图片生成 4.2 签到 4.3 邀请 4.4 WalletConnect连接 5.功能截图 ​6.问题整理 Welcome to Code Blocks blog 本篇文章主…

【图解秒杀系列】秒杀场景介绍及其相关技术点

【图解秒杀系列】秒杀场景介绍及其相关技术点 秒杀场景介绍秒杀页面的交互秒杀的整套流程 秒杀系统面临的挑战秒杀涉及的技术点 秒杀场景介绍 电商系统的秒杀是一种营销活动&#xff0c;在特定的时间点&#xff0c;以极低的价格&#xff0c;有限的商品数量&#xff0c;吸引大量…

【JavaEE初阶】懒汉模式与饿汉模式及指令重排序问题

目录 &#x1f4d5; 单例模式 &#x1f333; 饿汉模式 &#x1f6a9; 线程安全 &#x1f38d; 懒汉模式 &#x1f6a9; 懒汉模式-单线程版 &#x1f6a9; 懒汉模式-多线程版 &#x1f384; 指令重排序 &#x1f4d5; 单例模式 单例模式是一种经典的设计模式&#xff0c;…

node.js使用NodeMachineID 生成唯一UUID和注意事项

node-machine-id用于获取或生成唯一的机器ID 如何使用 const { machineId, machineIdSync } require(node-machine-id) JSON.stringify(machineIdSync({original: true})) ;方法&#xff1a; machineIdSync 此函数同步获取操作系统本机UUID/GUID&#xff0c;默认情况下进行哈…

视频教程 - 自研Vue3 Tree组件高级功能:虚拟滚动新增节点实现自动滚动

感谢小伙伴们对本套自研vue3 tree组件教程的关注&#xff0c;在前一篇媲美Element Plus JuanTree终极实战&#xff1a;虚拟滚动的功能演示中发现了小bug&#xff0c;特地整理了相关录屏来说明怎么一步步解决bug的&#xff0c;来回馈小伙伴们的支持。 Tree组件高级功能&#xff…

redis面试(四)持久化

什么是持久化&#xff1f; 由于redis是基于内存操作的轻量型数据库&#xff0c;所以如果发生宕机重启这种事情&#xff0c;存储的数据就会直接丢失&#xff0c;如果在里面存储了没有备份的数据&#xff0c;那么确实会对我们的业务造成一定影响。 所以我们要通过持久化的手段&a…

C# OpenCvSharp 打开4K高清摄像头

一、前言 整了个1200w像素的usb摄像头&#xff0c;使用 OpenCvSharp读取&#xff0c;读取和设置分辨率代码耗时居然10几秒&#xff0c;查询资料发现&#xff0c;必须对VideoCapture进行设置&#xff0c;使用DSHOW模式打开&#xff0c;并且设置分辨率代码下必须增加 指定MJPG编码…

pip‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

重新设置一下环境变量。 注意&#xff0c;这里后面没有斜杠 我之前就是因为环境变量中&#xff0c;这两行最后都有斜杠&#xff0c;导致提示pip‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

红旗E-QM5起火,一汽红旗否认车辆质量问题

近日&#xff0c;据媒体报道&#xff0c;7月31日下午&#xff0c;长春一辆一汽红旗E-QM5发生起火事故。 一汽红旗方面则表示&#xff1a;“现场勘查和初步调查表明&#xff0c;该事件并非因车辆自身质量问题导致自燃。疑似车辆在行驶过程中与路面井盖发生碰撞导致动力电池受损&…

计算机网络-基于PIM-DM+IGMP的组播实验配置

前面我们将IGMP协议和PIM-DM协议理论知识都学完了&#xff0c;现在开始进入实践&#xff0c;毕竟只有完成实践是最好的检验方式。IGMP是用于感知组播组成员&#xff0c;而PIM-DM是用于在域内构建组播分发树的的协议&#xff0c;本次实验使用这两项技术进行分析与实践。 一、拓扑…

upload-labs漏洞靶场~文件上传漏洞

寻找测试网站的文件上传的模块&#xff0c;常见&#xff1a;头像上传&#xff0c;修改上传&#xff0c;文件编辑器中文件上传&#xff0c;图片上传、媒体上传等&#xff0c;通过抓包上传恶意的文件进行测试&#xff0c;上传后缀名 asp php aspx 等的动态语言脚本&#xff0c;查…

电脑新加的硬盘如何分区?新加硬盘分区选MBR还是GPT

最近有网友问我,电脑新加的硬盘如何分区?电脑新加的硬盘分区选MBR还是GPT要看引导模式采用uefi还是传统的legacy模式&#xff0c;如果采用的是uefi引导模式&#xff0c;分区类型对应的就是gpt分区(guid)&#xff0c;如果引导模式采用的是legacy&#xff0c;对应的分区类型为mb…

Spring Boot集成sse实现chatgpt流式交互

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 什么是sse&#xff1f; SSE可以指代两种不同的概念&#xff1a;一是指“服务器发送事件”(Server-Sent Events)&#xff0c;另一种是指英特尔的“因特网数据流单指令序列扩展”(Streaming SIMD Extensions)。…

循环结构(三)——do-while语句

目录 &#x1f341;引言 &#x1f341;一、语句格式 &#x1f680;格式1 &#x1f680;格式2 &#x1f341;二、语句执行过程 &#x1f341;三、实例 &#x1f680;【例1】 &#x1f680;【例2】 &#x1f680;【例3】 &#x1f341;总结 &#x1f341;备注 &am…

Unity获取Animator动画播放完成事件

整理了一些在日常经验中处理动画播放完成事件的方法 方法: 1.Dotween配合异步实现 2.状态机计时方法实现 3.原生动画行为方法实现 方法一&#xff1a;Dotween异步方法 using UnityEngine; using System.Threading.Tasks; using DG.Tweening;public class PlayerAnimAsync : M…

Java——多线程(6/9):线程池、处理Runnable、Callable任务(认识线程池-线程池的工作原理,ThreadPoolExecutor构造器)

目录 认识线程池 介绍 线程池的工作原理 如何创建线程池 介绍 ThreadPoolExecutor构造器 代码实例 线程池的注意事项 线程池处理Runnable任务 ExecutorService的常用方法 代码实例 新任务拒绝策略 线程池处理Callable任务 ExecutorService的常用方法 代码实例…

如何从智联招聘网站快速抓取职位详情?两大技巧揭秘

摘要&#xff1a; 本文将揭秘如何利用Python爬虫技术&#xff0c;高效且合法地从智联招聘网站抓取职位详情信息。通过实战示例&#xff0c;展现两大核心技巧&#xff0c;助你在大数据时代抢占先机&#xff0c;为你的市场分析、人才研究提供强大支持。 一、引言&#xff1a;数据…