网页录制gb28181录像
Posted qianbo_insist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网页录制gb28181录像相关的知识,希望对你有一定的参考价值。
网页编解码
网页已经可以编解码h264,h265 等等常规编码,我们可以使用网页来进行gb28181的录像和解码以及形成文件,当然以前也可以,不过现在更为简便。需求来自于客户端不再进行更新,而使用网页版本来制作gb28181的本地录像(非服务器录像),同时创建链接可以下载,格式位webm。
以下将使用两种方式来存储录像,1 是重新编码,可以叠加数据,2 是不重新编码,我们的格式是flv ,将flv demux后直接存储
方式1 使用VideoTrackReader 和MediaStreamTrackProcessor
VideoTrackReader 根据文档已经deprecated,现在比较新的chrome版本应该使用MediaStreamTrackProcessor,并且有些函数已经过时,已经变成全局函数,比如createImageBitmap,不再属于videoFrame的内部函数,取而代之请使用全局createImageBitmap。不过还是给出一段VideoTrackReader的代码
// VideoTrackReader is deprecated; use MediaStreamTrackProcessor instead.
function startReader(stream)
if (videoTrackReader)
console.warn('VideoTrackReader ALREADY exist');
return;
const track = stream.getVideoTracks()[0];
videoTrackReader = new VideoTrackReader(track);
videoTrackReader.start(async (videoFrame) =>
if (keepAnimation)
// 注意videoFrame的createImageBitmap也已经过时
const imageBitmap = await videoFrame.createImageBitmap();
drawCanvasBitmap(imageBitmap);
imageBitmap.close();
videoFrame.destroy();
);
使用
function startProcessor(stream)
if (processor)
console.warn('MediaStreamTrackProcessor ALREADY exist');
return;
const track = stream.getVideoTracks()[0];
processor = new MediaStreamTrackProcessor(track);
writable = new WritableStream(
start()
console.log('Writable start');
,
async write(videoFrame)
const imageBitmap =await createImageBitmap(videoFrame);
drawCanvasBitmap(imageBitmap);
imageBitmap.close();
if (videoFrame.close)
videoFrame.close();
else
videoFrame.destroy();
,
// stop()
// console.log('Writable stop');
// ,
close()
console.log('Writable close');
,
abort(reason)
console.log('Writable abort:', reason);
,
)
processor.readable
.pipeTo(writable);
测试
可以使用getUserMedia 来做测试,假定视频已经在网页上播放,制作一个界面
async function startVideo()
const constraints = video: true, audio: false ;
const stream = await navigator.mediaDevices.getUserMedia(constraints)
.catch(err =>
console.error('Media ERROR:', err);
return;
);
video.srcObject = stream;
await video.play().catch(err => console.error('media ERROR:', err));
async function stopVideo()
if (video.srcObject)
video.pause();
stopMediaStream(video.srcObject);
video.srcObject = null;
点击开始录像以后,允许摄像头进行采集,如果没有摄像头,可以使用canvas,随手画上一段动画就行,下面给出一个示例
async function startDrawing()
const cnv = document.getElementById("src");
const ctx = cnv.getContext("2d", alpha: false );
ctx.fillStyle = "white";
const width = cnv;
const height = cnv;
const cx = width / 2;
const cy = height / 2;
const r = Math.min(width, height) / 5;
var drawtime = 0;
const drawOneFrame = function drawOneFrame(time)
//const angle = Math.PI * 2 * (time / 5000);
//const scale = 1 + 0.3 * Math.sin(Math.PI * 2 * (time / 7000));
ctx.save();
ctx.fillRect(0, 0, width, height);
ctx.translate(cx, cy);
//ctx.rotate(angle);
//ctx.scale(scale, scale);
ctx.font = "30px Verdana";
ctx.fillStyle = "black";
const text = "this is " +drawtime++;
const size = ctx.measureText(text).width;
ctx.fillText(text, -size / 2, 0);
ctx.restore();
window.requestAnimationFrame(drawOneFrame);
;
以上使用不断变化的数字来代替gb28181 的播放,如上图所示。下面为播放中的界面。
录像呈现,默认为h264
方式2
使用接收的videoFrame去存储,比如我们是flv方式,那就是demux flv以后,装载成videoFrame,然后解码展现,可以将数据直接存储,这样可以省却编码,那么方式1的优势是什么呢?在里面可以直接叠加数据,比如AI 目标框和文字。原理和方式1 无大的差别,读者自己可以实践。demax后,可以使用EncodedVideoChunk来包装接收到的flv数据,变成了videoFrame, 然后进行pipe,如下面代码所示:
function inputChunk(data, pts, iskey)
console.log(data, pts, iskey)
const chunk = new EncodedVideoChunk(
timestamp: pts,
type: iskey ? 'key' : 'delta',
data: data
);
decoder.decode(chunk);
以上是关于网页录制gb28181录像的主要内容,如果未能解决你的问题,请参考以下文章
数字硬盘录像机接入GB28181流媒体服务(LiveGBS)设备录像实时查询
GB28181实现摄像头网页无插件直播回放过程中设备状态分析
LiveGBS通过GB28181协议接入海康大华华为等各厂家硬盘录像机NVR 或者带存储的摄像头实现WEB直播及录像查询回放