目录
一、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点击开始就可以播放了。
Your browser is too old which doesn't support HTML5 video.
url:
开始(start) 停止(stop) 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 = 720 let w = 1280 player = 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/connectionState console.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 = 720 let w = 1280 if (!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 = null var remote = document.getElementById('video') if (remote) { remote.srcObject = null remote.load() } } } .play-content{ background-color: black; border: red 1px solid; width: 100%; height: 100%; color: white; }
- 编译Zlmediakit
- 编译libsrtp
- openssl
- cmake