Caraws / Review-JavaScript

复习js基础
0 stars 0 forks source link

预览监控摄像头 #3

Open Caraws opened 7 years ago

Caraws commented 7 years ago

预览监控摄像头

在预览摄像头监控画面时, 用socket发送RTSP实时视频流. 在浏览器中接收到是一堆bytes, 所以需要转化为blob类型或者base64给canvas渲染出来.

  1. Node端 当时用的是一个个人项目rtsp-ffmpeg 链接, 有空的话可以看看WebRTC
  1. 利用socket.io向浏览器发送视频数据 关键代码:
    
    var rtsp = require('rtsp-ffmpeg');
    // 推流
    var uri = 'rtsp://accout:password@ip:port/h264/ch1/main/av_stream',
    stream = new rtsp.FFMpeg({
    input: uri,
    rate: 10,
    resolution: '320x240',
    quality: 3
    });

var cameraInfo = {} io.on('connection', socket => { console.log('connection') var pipeStream = function(data) { socket.emit('data', data); }; stream.on('data', pipeStream); socket.on('URI', data => { console.log(data); cameraInfo.cameraName = data.cameraName; cameraInfo.groupName = data.groupName; uri = rtsp://${data.userName}:${data.passWord}@${data.ip}:${data.RTSP}/h264/ch1/main/av_stream; stream.input = uri; stream.restart(); socket.emit('CameraInfo', cameraInfo); }) socket.on('disconnect', function() { stream.removeListener('data', pipeStream); }); })


中间将`Node.js`托管到IIS服务器上时会出现跨域的报错, 可能是和后端连接时端口被占, 具体看IIS报什么错. 如果IIS没报错, 还是有跨域的错重装一次`socket.io`基本可以解决.

如果用canvas预览摄像头还是有花屏的情况, 可以将码流切换为子码流`rtsp://accout:password@ip:port/h264/ch1/sub/av_stream`

> 3. 浏览器
基于`Vue.js`, 先引入`socket.io`并建立连接, 然后对视频流数据做处理(展示时不要用`img`标签, 掉帧比较严重).

关键代码: 
```JavaScript
var bytes = new Uint8Array(data);

var blob = new Blob([bytes], {type: 'application/octet-binary'});

var url = URL.createObjectURL(blob);

var img = new Image;

var ctx = this.canvas.getContext("2d");
    img.width = img.width * 0.5;
    img.height = img.height * 0.5;
    img.onload = function() {
         URL.revokeObjectURL(url);
         ctx.drawImage(img, 0, 0,720,560);
    };    
img.src = url;

2017/7/26

Caraws commented 7 years ago

bytes 转 base64

canvas预览摄像头在浏览器做处理时, 也可转为base64(别人的代码). 代码如下:

base64ArrayBuffer(arrayBuffer) {
    var base64    = '';
    var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    var bytes         = new Uint8Array(arrayBuffer);
    var byteLength    = bytes.byteLength;
    var byteRemainder = byteLength % 3;
    var mainLength    = byteLength - byteRemainder;
    var a, b, c, d;
    var chunk;
    // Main loop deals with bytes in chunks of 3
    for (var i = 0; i < mainLength; i = i + 3) {
          // Combine the three bytes into a single integer
          chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
          // Use bitmasks to extract 6-bit segments from the triplet
          a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
          b = (chunk & 258048)   >> 12; // 258048   = (2^6 - 1) << 12
          c = (chunk & 4032)     >>  6; // 4032     = (2^6 - 1) << 6
          d = chunk & 63;               // 63       = 2^6 - 1
          // Convert the raw binary segments to the appropriate ASCII encoding
          base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
     }
     // Deal with the remaining bytes and padding
     if (byteRemainder == 1) {
          chunk = bytes[mainLength];
          a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2
          // Set the 4 least significant bits to zero
          b = (chunk & 3)   << 4; // 3   = 2^2 - 1
          base64 += encodings[a] + encodings[b] + '==';
      } else if (byteRemainder == 2) {
          chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];
          a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
          b = (chunk & 1008)  >>  4; // 1008  = (2^6 - 1) << 4
          // Set the 2 least significant bits to zero
          c = (chunk & 15)    <<  2; // 15    = 2^4 - 1
          base64 += encodings[a] + encodings[b] + encodings[c] + '=';
      }
      return base64;
}

另外可以用 blob 转URL的方法, 上一个issue中已有, 这里就不在阐述.

2017/8/10