web播放rtsp流视频,使用webrtc毫秒级延迟

目录

一、zlmediakit环境搭建和编译

1)、下载zlmediakit

2)、安装依赖

3)、编译webrtc

4)、启动zlmediakit

二、播放webrtc视频

1)、动态添加拉流代理

2)、播放视频 

三、嵌入到自己的vue项目中。

1)、拷贝demo到自己的vue项目中

2)、mkcert生成证书


背景:需要在web应用中播放摄像头的rtsp流视频,并且延迟需要做到1秒以内。试过网上很多方法,都不能做到1秒内的延迟,可能有这种方案,只是我还没找到。所以我尝试了使用zlmediakit的webrtc功能进行播放。效果不错,视频画面很实时,目前只做了初步尝试,实际应用还需要研究。下面是我的步骤:

 系统:在ubuntu20.04和树莓派的raspberrypi系统都有尝试。

一、zlmediakit环境搭建和编译

1)、下载zlmediakit

#下载代码
git clone https://github.com/ZLMediaKit/ZLMediaKit.git
cd ZLMediaKit
#千万不要忘记执行这句命令
git submodule update --init

2)、安装依赖

  • gcc
#一般系统都会自带gcc,可以使用命令gcc -v 查看版本#如果没有的话使用以下命令安装
sudo apt-get install build-essential
  • cmake
#先查看系统有没有已经安装
cmake --version#没安装就使用以下命令安装
sudo apt-get install cmake
  • openssl
#首先查看是否已经安装
openssl version
#没安装使用以下命令安装
sudo apt-get install libssl-dev

3)、编译webrtc

  • 编译libsrtp
#依次执行以下命令
git clone https://gitee.com/mirrors/cisco-libsrtp.git
cd cisco-libsrtp
./configure --enable-openssl
make -j4
sudo make install
  •  编译Zlmediakit

回到zlmediakit目录下 

#依次执行以下命令
mkdir build
cd build
cmake -DENABLE_WEBRTC=on ../
cmake --build . --target MediaServer

 当进度变成100%就是编译完成了,可以看到目录下多了一个release目录。

4)、启动zlmediakit

cd release/linux/Debug
#通过-h可以了解启动参数
./MediaServer -h
#以守护进程模式启动
./MediaServer -d &

  建议先使用sudo ./MediaServer 启动,可以方便查看日志

这时候zlmediakit已经启动了, 可以在浏览器输入虚拟机地址加上/webrtc访问webrtc播放demo

这时候还不能播放视频,需要将摄像头视频流注册到zlmediakit中,可以使用zlm的restful接口添加拉流代理,下面将有介绍。

二、播放webrtc视频

1)、动态添加拉流代理

在zlm官方文档中,有对restful接口的说明https://github.com/zlmediakit/ZLMediaKit/wiki/MediaServer%E6%94%AF%E6%8C%81%E7%9A%84HTTP-API

我们只需要使用这个动态添加拉流代理的接口即可

首先打开api工具,我这里使用的是apipost,当然还有其他的比如postman、apifox都是可以的。 

输入请求地址,发送的请求是post请求

根据文档中所需要填入的参数,我们这里将几个必选的参数加上,其中secret需要我们在配置文件中查看,打开/ZlmediaKit/release/linux/Debug目录,有一个config.ini文件,使用nano config.ini命令打开,可以看到secret的内容,我们将后面的字符串复制下来

在api工具中,我们在query里填入参数如下:

 secret就是我们刚刚获取的密钥。

vhost就填入运行zlm机器的ip就行。

app是流应用名,可以写live。

stream是流id,我们需要保证每个流id是唯一的,可以使用当前时间的时间戳,时间戳可以在ctool.dev中获取。

url为摄像头rtsp流地址,以海康摄像头为例,流地址组成格式为:rtsp://账号:密码@ip:554/h264/ch1/sub/av_stream,这里使用的是sub子码流,如果想用主码流换成main即可。

填写完成后点击发送,可以看到响应code为0,还响应了一个key,这个key就是我们拼接播放地址所需要的

2)、播放视频 

打开前面那个/webrtc/播放demo界面,将url中的ip和stream的值改成实际的值就可以点击开始播放了。

到此web中使用webrtc播放rtsp视频就结束了。下面我将介绍在自己的vue项目中播放的方法。

三、嵌入到自己的vue项目中。

1)、拷贝demo到自己的vue项目中

在release/linux/Debug目录下有一个www目录,进入后有一个webrtc目录,将里卖弄的index.html和ZLMRTCClient.js拷贝出来。

将ZLMRTCClient.js拷贝到自己的vue项目中,在文件的最下方加入

export {ZLMRTCClient
}

创建一个player.vue文件,将index.html文件中的内容拷贝到.vue文件下,根据自己的需求,将一些选项隐藏掉,将值改为固定的即可,文末我会给出我的player.vue完整代码。

因为webrtc是基于https协议的,我们还需要解决证书问题,这里我选用一个开源项目mckert来生成证书。

2)、mkcert生成证书

我这里使用windows本地开发的,所以直接在mkcert官网下载exe文件就可以。

https://github.com/FiloSottile/mkcert/releases

下载后将整个exe文件拖入终端命令行,加上-install,如下图

回车执行安装。

在工程下新建一个keys文件夹,进入到keys文件夹下,再次将exe拖入终端,执行如下命令

这时候keys文件夹下会生成两个文件

我使用的是vite搭建的vue项目,所以我在vite.config.js中配置以下内容

server:{https:{key: 'keys/localhost+1-key.pem',cert: 'keys/localhost+1.pem',}
}

重启系统便可以看到访问地址变成了https开头

这时候便可以在你的项目中播放摄像头rtsp视频流了。

下面是我的player.vue代码,写的比较粗糙,凑合用。我只保留了输入url和开始停止按钮。手动输入正确的url点击开始就可以播放了。

<template><div class="play-content"><div><video id="video" controls autoplay style="text-align: left;width: 60%;">Your browser is too old which doesn't support HTML5 video.</video></div><div><p><label for="streamUrl">url:</label><inputtype="text"style="co"v-model="PlayUrl"id="streamUrl"/></p><button @click="start()">开始(start)</button><button @click="stop()">停止(stop)</button></div></div>
</template><script setup>
import {ZLMRTCClient} from '../../utils/ZLMRTCClient'
import {ref}from 'vue'var player = null
var recvOnly = false
var resArr = []var ishttps = 'https:' == document.location.protocol ? true : false
var isLocal = 'file:' == document.location.protocol ? true : false
var url =document.location.protocol +'//' +window.location.host +'/index/api/webrtc?app=live&stream=test&type=play'
if (!ishttps && !isLocal) {alert('本demo需要在https的网站访问 ,如果你要推流的话(this demo must access in site of https if you want push stream)')
}
if (isLocal) {url = 'http://127.0.0.1' + '/index/api/webrtc?app=live&stream=test&type=play'
}
// document.getElementById('streamUrl').value = url
const PlayUrl = ref(url)const start_play = () => {let h = 720let w = 1280player = new ZLMRTCClient.Endpoint({element: document.getElementById('video'), // video 标签debug: true, // 是否打印日志zlmsdpUrl: document.getElementById('streamUrl').value, //流地址simulcast: false,useCamera: true,audioEnable: true,videoEnable: true,recvOnly: recvOnly,resolution: { w: w, h: h },usedatachannel: false})player.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR, function (e) {// ICE 协商出错console.log('ICE 协商出错')})player.on(ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS, function (e) {//获取到了远端流,可以播放console.log('播放成功', e.streams)})player.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, function (e) {// offer anwser 交换失败console.log('offer anwser 交换失败', e)stop()})player.on(ZLMRTCClient.Events.CAPTURE_STREAM_FAILED, function (s) {// 获取本地流失败console.log('获取本地流失败')})player.on(ZLMRTCClient.Events.WEBRTC_ON_CONNECTION_STATE_CHANGE, function (state) {// RTC 状态变化 ,详情参考 https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/connectionStateconsole.log('当前状态==>', state)})player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_OPEN, function (event) {console.log('rtc datachannel 打开 :', event)})// player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_MSG, function (event) {//   console.log('rtc datachannel 消息 :', event.data)//   document.getElementById('msgrecv').value = event.data// })player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_ERR, function (event) {console.log('rtc datachannel 错误 :', event)})player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_CLOSE, function (event) {console.log('rtc datachannel 关闭 :', event)})
}const start = () => {stop()let h = 720let w = 1280if (!recvOnly) {ZLMRTCClient.isSupportResolution(w, h).then((e) => {start_play()}).catch((e) => {alert('not support resolution')})} else {start_play()}
}
const stop = () => {if (player) {player.close()player = nullvar remote = document.getElementById('video')if (remote) {remote.srcObject = nullremote.load()}}
}
</script><style scoped>
.play-content{background-color: black;border: red 1px solid;width: 100%;height: 100%;color: white;
}
</style>

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

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

相关文章

shell shell脚本编写常用命令 语法 shell 脚本工具推荐

shell 脚本 计算机语言 Shebang 定义解释器 主要定义&#xff0c;您的脚本是用什么语言写的 #!/usr/bin/python //定义这是一个python语言#!/bin/bash //定义这是一个shell语言 echo SHELL我们执行的 linux 命令的时候&#xff0c;其实是使用 /bin/bash 这个二进制文…

鸿蒙应用开发 应用内字体大小调节

1 数据管理概述 在移动互联网蓬勃发展的今天&#xff0c;移动应用给我们生活带来了极大的便利&#xff0c;这些便利的本质在于数据的互联互通。因此在应用的开发中数据存储占据了非常重要的位置&#xff0c;HarmonyOS 应用开发也不例外。 本文将为您介绍 HarmonyOS 提供的数据…

stm32 HAL库 4096线ABZ编码器

[TOC]目录 ABZ编码器 4096线 买的是这个 AB相代表计数方向&#xff0c;Z代表过零点 cubemx配置 定时器Encoder 也可以选上DMA 中断 Z相GPIO中断 找一个空闲管脚 打开对应中断 代码 不用DMA int main(void) {short Enc_cnt 0;HAL_TIM_Encoder_Start_IT(&ht…

DrGraph原理示教 - OpenCV 4 功能 - 单通道图

通道 OpenCV的核心处理对象是Mat&#xff0c;大体是一个二维数组&#xff0c;加上了各种功能函数。 很多的图像处理&#xff0c;会在单通道或二值化的基础上进行&#xff0c;比如连通域、目标识别等。这里的通道就是channels。 不同的图像处理算法可能对通道数有特定的要求。例…

HTML5+CSS3+JS小实例:过年3D烟花秀

实例:过年3D烟花秀 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><…

#前后端分离# 头条发布系统

头条业务简介 用户功能 注册功能登录功能jwt实现 新闻 新闻的分页浏览通过标题关键字搜索新闻查看新闻详情新闻的修改和删除 预览界面 开源上线 https://gitcode.net/NVG_Haru/NodeJS_5161447 数据库设计 数据库脚本 CREATE DATABASE sm_db;USE sm_db;SET NAMES utf8mb4…

半导体行业-SECS/GEM协议 JAVA与SECS/GEM通信 什么是配方?springboot集成SECS通信协议 配方管理S7FX

Java与SECS基础通信 Java实现SECS指令S2F17获取时间 Java实现SECS指令 S10F3 终端单个显示例子 Java实现SECS指令 S7FX配方管理 Java实现SECS指令 S5F1报警/取消报警上传 实例源码及DEMO请查阅 JAVA开发SECS快速入门资料&#xff0c;SECS S7F19 什么是半导体配方&…

初识javaWeb

一、JavaWeb是什么&#xff1f; 1、概念 javaWeb指的是使用java语言进行互联网领域项目开发的技术栈——进行web项目开发所需的技术的集合。 -Web前端——在浏览器中用户可以看到的网页 -Web后端——为前端提供数据的程序 2、Web项目 java语言是可以进行多种类型的项目开发&a…

网大为卸任腾讯CXO;Midjourney 1 月训练视频模型;2023年马斯克赚了7700亿

投融资 • 2023 年大型科技公司在生成式 AI 初创企业上的投资远超风险投资集团• 恒信东方与无锡政府合作成立布局 MR/XR 技术及 3D 数字资产 AIGC 产业投资基金• 新公司法完善注册资本认缴登记制度• 网大为卸任腾讯CXO&#xff0c;曾促成南非MIH的投资• 宁波蔚孚科技完成数…

【VS】NETSDK1045 当前 .NET SDK 不支持将 .NET 6.0 设置为目标。

问题描述 报错 NETSDK1045 严重性代码说明项目文件行禁止显示状态错误NETSDK1045当前 .NET SDK 不支持将 .NET 6.0 设置为目标。请将 .NET 5.0 或更低版本设置为目标&#xff0c;或使用支持 .NET 6.0 的 .NET SDK 版本。RCSoftDrawMicrosoft.NET.TargetFrameworkInference.ta…

年度总结|存储随笔2023年度最受欢迎文章榜单TOP15-part2

TOP11&#xff1a;PCIe在狂飙&#xff0c;SAS存储之路还有多远&#xff1f; 随着科技的飞速发展&#xff0c;固态硬盘&#xff08;SSD&#xff09;已经成为现代计算机系统中不可或缺的一部分。它以其出色的性能和可靠性&#xff0c;改变了我们对于存储设备的期待。当前业内SSD广…

Java(算术,自增自减,赋值,关系,逻辑,三元)运算符,运算符的优先级,隐式转换,强制转换,字符串的+。

文章目录 1.运算符和表达式运算符&#xff1a;表达式&#xff1a; 2.算术运算符练习&#xff1a;数值拆分 3.隐式转换概念&#xff1a;简单记忆&#xff1a;两种提升规则&#xff1a;取值范围从小到大的关系&#xff1a; 4.隐式转换的练习案例一&#xff1a;案例二&#xff1a;…

Python中如何使用_new_实现单例模式

单例模式是一个经典设计模式&#xff0c;简要的说&#xff0c;一个类的单例模式就是它只能被实例化一次&#xff0c;实例变量在第一次实例化时就已经固定。 在Python中常见的单例模式有None&#xff0c;这就是一个很典型的设计&#xff0c;通常使用 if xxx is None或者if xxx …

【Linux Shell学习笔记】Linux Shell的位置参数与函数

一、位置参数 位置参数&#xff0c;也被称之为位置变量&#xff0c;通过位置参数&#xff0c;可以在执行程序的时候&#xff0c;向程序传递数据 1.1 shell接收参数的方法 1.2 向shell传递参数的方法 二、函数 2.1 函数基础 2.1.1 函数简介 函数本质上就是一个代码块&#xf…

微信小程序开发系列-07组件

微信小程序开发系列目录 《微信小程序开发系列-01创建一个最小的小程序项目》《微信小程序开发系列-02注册小程序》《微信小程序开发系列-03全局配置中的“window”和“tabBar”》《微信小程序开发系列-04获取用户图像和昵称》《微信小程序开发系列-05登录小程序》《微信小程序…

碎花连衣裙 I 森系女孩的衣橱

宛如来到了春天&#xff0c;身穿碎花连衣裙的少女 在充满阳光&#xff0c;树叶葱郁的森林里 自由快乐地穿梭&#xff0c;感受着春天的美好 感受着幸福而快乐的童年&#xff01;

10 款顶级的免费U盘数据恢复软件(2024 年 更新)

你曾经遇到过U盘无法访问的情况吗&#xff1f;现在我们教你如何恢复数据。 在信息时代&#xff0c;数据丢失往往会造成巨大的困扰。而USB闪存驱动器作为我们常用的数据存储设备&#xff0c;其重要性不言而喻。但是&#xff0c;U盘也可能会出现各种问题&#xff0c;如无法访问、…

conftest.py 配置

章节目录&#xff1a; 一、概述二、场景说明三、代码示例3.1 最外层3.2 商品模块测试3.3 订单模块测试3.4 用户模块测试3.5 执行结果 四、关于 conftest.py 配置 fixture五、结束语 一、概述 “conftest.py” 是 pytest 测试框架中的一个特殊的配置文件&#xff0c;它能够为整个…

分布式技术之缓存技术

文章目录 什么是分布式缓存&#xff1f;分布式缓存原理Redis 分布缓存原理Memcached 分布式缓存原理对比分析 在计算机领域的各个方面&#xff0c;缓存都非常重要&#xff0c;是提升访问性能的一个重要技术。为什么这么说呢&#xff1f;从单个计算机的体系结构来看&#xff0c;…