本次项目使用Aliplayer 播放器 播放rtmp直播流(户外摄像头的直播流),视频监控是用的阿里云的视频监控。
前端框架:layui
1、使用阿里播放器插件Aliplayer,实现rtmp流的直播播放;
2、实现PTZ云台控制。
3、调用PTZ云台控制接口的时候,公共参数中的签名结果串,是经过计算获得的,签名方式HMAC-SHA1。
播放器的属性接口说明文档
https://help.aliyun.com/document_detail/125572.html?spm=a2c4g.11186623.4.1.131d1c4cC756EZ
视频监控部分接口文档
https://help.aliyun.com/document_detail/109559.html?spm=a2c4g.11186623.6.569.2c187d8aGDFSEd
1、签名串算的时候踩坑了,先下载各sha1算法的插件,调试的时候,对着官方文档的例子先算一下,是否输出正确,如果不正确报错,阿里云也会给返回值,可根据返回结果查看一下哪里的问题。
https://help.aliyun.com/document_detail/109568.html?spm=a2c4g.11186623.2.12.26d9200frMF1JS
2、Aliplayer播放rtmp格式,加载直播流之后画面不动,花了很多时间去查资料。开始以为是因为配置参数写法格式错误,后来发现加引号和不加引号其实都可以。
最后提的阿里工单,解决办法:
给播放器参数加上
rtmpBufferTime: 0, showBuffer: 0,
(rmtp流是纯视频流,没有音频流,参数设置是对于纯视频流的播放兼容参数)
这次是在有参考的情况下还用了这么长时间调试,实在是不应该啊。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <title>Aliplayer在线配置</title> <link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.8.1/skins/default/aliplayer-min.css" /> <script type="text/javascript" charset="utf-8" src="https://g.alicdn.com/de/prismplayer/2.8.1/aliplayer-min.js"></script> <link rel="stylesheet" href="layuiadmin/layui/css/layui.css" media="all"> <style> #set { position: absolute; right: 15px; top: 15px; z-index: 9999 } #control{width: 200px;height: 200px;} #control ul li{width: 33.33%;float: left;margin-bottom: 10px;text-align: center;} .bgcon{ padding: 10px 5px 5px; width: 210px; height: 132px; display: table; background-color: rgba(0,142,240,.1); border-radius: 5px; border: 1px solid rgba(0,142,240,.2); margin-bottom: 10px; } </style> </head> <body> <button class="layui-btn layui-btn-normal" id="set">设置</button> <div class="prism-player" id="player-con"> </div> <div id="control" style="display: none;padding: 10px"> <ul class="bgcon"> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_move(0.5,0.5,0)" onmouseup="stop_move()"><span>↖ </span></button> </li> <li><button type="button" class="layui-btn layui-btn-normal" onmousedown="start_move(0,0.5,0)" onmouseup="stop_move()"><span>↑ </span></button> </li> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_move(-0.5,0.5,0)" onmouseup="stop_move()"><span>↗ </span></button> </li> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_move(0.5,0,0)" onmouseup="stop_move()"><span>← </span></button> </li> <li style="text-align: center;line-height: 38px;position: relative; "> 方向调节 </button> </li> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_move(-0.5,0,0)" onmouseup="stop_move()"><span>→ </span></button> </li> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_move(0.5,-0.5,0)" onmouseup="stop_move()"><span>↙ </span></button> </li> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_move(0,-0.5,0)" onmouseup="stop_move()"><span>↓ </span></button> </li> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_move(-0.5,-0.5,0)" onmouseup="stop_move()"><span>↘ </span></button> </li> </ul> <ul class="bgcon"> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_adjust(0,-0.5)" onmouseup="stop_adjust()"><span>-</span></button> </li> <li style="line-height: 38px;"> 变焦 </li> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_adjust(0,0.5)" onmouseup="stop_adjust()"><span>+</span></button> </li> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_move(0, 0, -0.5)" onmouseup="stop_move()"><span>-</span></button> </li> <li style="line-height: 38px;"> 变倍 </button> </li> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_move(0, 0, 0.5)" onmouseup="stop_move()"><span>+</span></button> </li> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_adjust(-0.5,0)" onmouseup="stop_adjust()"><span>-</span></button> </li> <li style="line-height: 38px;"> 光圈 </li> <li> <button type="button" class="layui-btn layui-btn-normal" onmousedown="start_adjust(0.5,0)" onmouseup="stop_adjust()"><span>+</span></button> </li> </ul> </div> <script src="layuiadmin/layui/layui.js"></script> <script> layui.config({ version: true, //一般用于更新模块缓存,设为 true 即让浏览器不缓存。 base: 'layuiadmin/' //静态资源所在路径 }).extend({ index: 'lib/index' //主入口模块 }).use(['index', 'layer', 'commonUtils', 'request'], function() { var $ = layui.$, commonUtils = layui.commonUtils, request = layui.request, layer = layui.layer; var id = 'xxxx'; //摄像头设备id var AccessKeyId = 'xxx';//阿里云控制台的密钥 var AccessKeySecret = 'xxxx'; var player = null; if (player) { player.dispose(); //销毁 $('#player-con').empty(); } player = new Aliplayer({ id: "player-con", width: "100%", height: "400px", autoplay: true, //自动播放 rePlay: false,//重播视频 isLive: true,//是否直播 useH5Prism: true, //指定使用H5播放器。 useFlashPrism: false, //指定使用Flash播放器 rtmpBufferTime: 0, showBuffer: 0, stashInitialSizeForFlv: 30, //H5播放flv时,初始缓存大小,只在直播下起作用。 source: 'rtmp://....' //rtmp格式的地址 }, function(player) { // player.on("ready", function(e) {}); }); $("#set").click(function() { layer.open({ type: 1, anim: -1, title: 'control', closeBtn: 1, // shade: 0.1, shadeClose: true, content: $('#control'), area: ['240px', '420px'] }) }) //摄像头移动 window.start_move = function(pan, tilt, zoom) { var params = { Action: 'ContinuousMove', Id: id, Pan: pan, Tilt: tilt, Zoom: zoom, Version: '2018-12-12', AccessKeyId: AccessKeyId, Signature: '', SignatureMethod: 'HMAC-SHA1', Timestamp: Timestamp(), SignatureVersion: '1.0', SignatureNonce: commonUtils.UUID(), Format: 'JSON' }; params.Signature = Signature(params); ali_api(params) } //停止转动 window.stop_move = function() { const params = { Action: 'StopMove', Id: id, Pan: true, Tilt: true, Zoom: true, Version: '2018-12-12', AccessKeyId: AccessKeyId, Signature: '', SignatureMethod: 'HMAC-SHA1', Timestamp: Timestamp(), SignatureVersion: '1.0', SignatureNonce: commonUtils.UUID(), Format: 'JSON' }; params.Signature = Signature(params); ali_api(params) } //设置光圈,焦点 window.start_adjust = function(Iris, Focus) { var params = { Action: 'ContinuousAdjust', Id: id, Iris: Iris, Focus: Focus, Version: '2018-12-12', AccessKeyId: AccessKeyId, Signature: '', SignatureMethod: 'HMAC-SHA1', Timestamp: Timestamp(), SignatureVersion: '1.0', SignatureNonce: commonUtils.UUID(), Format: 'JSON' }; params.Signature = Signature(params); ali_api(params) } //停止设置光圈焦点 window.stop_adjust = function() { const params = { Action: 'StopAdjust', Id: id, Iris: true, Focus: true, Version: '2018-12-12', AccessKeyId: AccessKeyId, Signature: '', SignatureMethod: 'HMAC-SHA1', Timestamp: Timestamp(), SignatureVersion: '1.0', SignatureNonce: commonUtils.UUID(), Format: 'JSON' }; params.Signature = Signature(params); ali_api(params) } //发送请求 function ali_api(params) { $.ajax({ url: 'http://vs.cn-qingdao.aliyuncs.com', type: 'GET', async: true, data: params, success: function(res, status, xhr) { }, error: function(jqXHR, textStatus, errorThrown) { layer.msg(errorThrown); } }) } /* 签名结果串 计算。 关于签名的计算方法,参见签名机制。 https://help.aliyun.com/document_detail/109568.html?spm=a2c4g.11186623.2.12.58c1200f7NANPp */ function Signature(params) { var data = []; var keys = Object.keys(params).sort(); for (var i = 0; i < keys.length; i++) { var key = keys[i]; if (key === 'Signature') { continue; } data.push(key + '=' + params[key]); } var CanonicalizedQueryString = escape(data.join('&')); var StringToSign = ('GET&/&' + CanonicalizedQueryString).replace(/:/g, '%3A'); return commonUtils.hmacsha1(AccessKeySecret + '&', StringToSign).toString(); //第一个参数为Key ,第二个参数为 StringToSign } //时间戳 function Timestamp() { var timestamp = (new Date().getTime()) - (60 * 60 * 8 * 1000); var date = new Date(timestamp); return date.getFullYear() + '-' + ('00' + (date.getMonth() + 1)).substr(-2) + '-' + ('00' + date.getDate()).substr(-2) + 'T' + ('00' + date.getHours()).substr(-2) + ':' + ('00' + date.getMinutes()).substr(-2) + ':' + ('00' + date.getSeconds()).substr(-2) + 'Z'; } }); </script> </body>调用的UUID() 随机数的函数
/** * 生成UUID */ random4: function() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); } UUID: function() { return (commonUtils.random4() + commonUtils.random4() + "-" + commonUtils.random4() + "-" + commonUtils.random4() + "-" + commonUtils.random4() + "-" + commonUtils.random4() + commonUtils.random4() + commonUtils.random4()); }