网页录制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);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qianbo_insist

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值