之前的rtsp转webrtc的方案存在如下缺陷:1.只支持h264;2.受限于webrtc的理解难度以及搭建turn/stun的p2p服务等问题,对于局域网下的业务需求来说有些杀猪用牛刀的意思;3.ios不支持webrtc。
基于以上原因,我又找到了一些其它的方案进行了测试,目前看jsmpeg的方案更加适合我们的需求,而且普通压缩大小为135kb,gzip方式压缩后仅仅42kb,在嵌入式场景下也可以使用。只是转码服务需要ffmpeg,在不进程裁剪开发的情况下,需要在设备或者PC或者局域网路由器设备等上安装的该插件服务会比较大。
官网:https://jsmpeg.com/
https://blog.csdn.net/a843334549/article/details/120697574
https://segmentfault.com/a/1190000040622805
https://juejin.cn/post/7057406701565116452
https://github.com/vCloudSail/jsmpeg-player
https://studygolang.com/articles/25474
根据这个架构我们的想法是jsmpeg客户端使用前端开发,该客户端唯一比较大的就是jsmpeg.js,不压缩也就100k多一点,压缩后更小,这样就可以放到很多设备中了,甚至很多嵌入式设备都都可以,然后我们将http、websocket服务端使用后端语言来开发,比如node.js、Java、Go、c++等,ffmpeg转码这里快速开发可以直接用ffmpeg,要再裁剪的话可以自己用C再开发一下,我们只需要转H264/H265到mpeg1,AAC到mp2,然后将对应的音视频格式的流通过websocket分发到jsmpeg客户端就可以了。
本来想自己开发的,结果随便搜了一下,已经有人用go的gin框架写了,互联网和开源拯救了大家,直接参考一下:https://studygolang.com/articles/25474
代码我整体看了一下,也跑了一下,修改了三个部分:
case <-time.After( 60 * time.Second):
_, _ = stdin.Write([] byte ( "q" ))
err := cmd.Wait()
if err != nil {
util.Log().Error( "Run ffmpeg err %v" , err.Error())
}
util.Log().Debug("FFmpeg cmd: ./ffmpeg %v", strings.Join(params, " "))
cmd := exec.Command("./ffmpeg", params...)
DOCTYPE html>
<html>
<head>
<title>JSMpeg Stream Clienttitle>
<style type="text/css">
html, body {
text-align: center;
}
style>
head>
<body>
<canvas id="video-canvas">canvas>
<canvas id="video-canvas1">canvas>
<script type="text/javascript" src="jsmpeg.min.js">script>
<script type="text/javascript">
var request = new XMLHttpRequest();
var url = "http://127.0.0.1:3000/stream/play"; //接口url
request.open("POST", url, true);
request.setRequestHeader("Content-type", "application/json");
request.send('{"url": "rtsp://192.168.31.204/main_stream"}'); //传入的数据,不同摄像头修改这里的rtsp地址即可
request.onreadystatechange = function(){
//若响应完成且请求成功
if(request.readyState === 4 && request.status === 200){
//do something, e.g. request.responseText
console.log("response:"+request.responseText)
const resObj = JSON.parse(request.responseText);
if (resObj['data']) {
if (resObj['data']['path']) {
console.log("ws path:"+resObj['data']['path'])
var canvas1 = document.getElementById('video-canvas1');
// var url = 'ws://127.0.0.1:3000/stream/live/test';
var wsUrl = 'ws://127.0.0.1:3000'+resObj['data']['path']
console.log("ws url:"+wsUrl)
var player = new JSMpeg.Player(wsUrl, {canvas: canvas1});
}
}
}
}
script>
body>
html>
这里还有一个坑点,留给大家去探索吧:长时间运行后如果推流的rtsp服务存在断流的话就没有画面了,这个没有webrtc服务的容错机制,需要自行判断处理,否则长时间跑之后画面就没了。
此外,http接口还可以增加ptz、preset等接口,这个仍然可以使用onvif协议来处理。
编译Go代码很方便,但是我这里建议使用go1.18,go1.19在Windows下使用“./”会报错,必须使用“.\”,这个需要注意,然后就go build
即可生成可执行程序了。
之后修改html中的request.send中的rtsp的地址后访问该html即可看到效果了:
很多时候,共同讨论才能更快的进步,开源让Linux成长的很快,不管是家电还是汽车、手机等等,生活中很多东西都可以见到Linux,而固步自封的结果大家也已经看到不少了。