WebRTC音视频数据采集 六、第九节 MediaStreamAPI及获取视频约束

论坛 期权论坛 脚本     
已经匿名di用户   2022-5-29 19:20   1249   0

今天我们来重点介绍一些 MediaStream的方法和事件

在这些方法中主要是和Track相关的,此前我们已经介绍过了。

在webrtc中包括了流的概念和轨的概念。在一个媒体流中可以包含很多的媒体轨,音频媒体轨,视频媒体轨。

MediaStream.addTrack()

MediaStream.addTrack()表示向流媒体中加入不同的轨

MediaStream.removeTrack()

将媒体流中不想要的媒体轨移出去

MediaStream.getVideoTracks()

将媒体流中所有的视频的轨,全部拿到,这样就可以根据自身的需要,去获取所需要的视频的媒体轨

MediaStream.getAudioTracks()

将媒体流中所有的音频的轨,全部拿到,这样就可以根据自身的需要,去获取所需要的音频的媒体轨

MediaStream.stop()

将媒体流直接关闭掉,这样它会调每一个媒体轨中的STOP;这样的话,这个流就结束掉了。

除了以上的方法还有一些事件,下面也介绍一下

MediaStream.onaddtrack

就是当我们添加一个媒体轨到媒体流中的时候 ,会触发这个事件,

MediaStream.onremovetrack

删除这个媒体轨

MediaStream.onended

当这个流结束的时候,我们会收到一个流结束的事件,非常简单。

下面我们来实战一下获取视频的约束。

index.html

<html>
  <head>
    <title>捕获音视频数据 WebRTC capture video and audio</title>
  <style>
   .none {
    -webkit-filter: none; 
   }

   .blur {
        /* 特效模糊 */
    -webkit-filter: blur(3px); 
   }

   .grayscale {
        /* 特效灰度 */
    -webkit-filter: grayscale(1);  
   }

   .invert {
        /* 翻转 */
    -webkit-filter: invert(1); 
   }

   .sepia {
        /* 特效褐色 */
    -webkit-filter: sepia(1);
   }

  </style>
  </head>
  <body>
  <div>
   <label>audio Source:</label>
   <select id="audioSource"></select>
  </div>

  <div>
   <label>audio Output:</label>
   <select id="audioOutput"></select>
  </div>

  <div>
   <label>video Source:</label>
   <select id="videoSource"></select>
    </div>
    <!-- 特效选择器 -->
    <div>
   <label>Filter:</label>
   <select id="filter">
    <option value="none">None</option>
    <option value="blur">blur</option>
    <option value="grayscale">Grayscale</option>
    <option value="invert">Invert</option>
    <option value="sepia">sepia</option>
   </select>
  </div>
    <!-- 
      我们创建一个video标签,这个标签就可以显示我们捕获的音视频数据 
      autoplay 表示当我们拿到视频源的时候直接播放
      playsinlin  表示在浏览器页面中播放而不是调用第三方工具
     -->
     <!-- 通过audio标签只获取音频 -->
     <!-- 
       controls  表示将暂停和播放按钮显示出来,否则它虽然播放声音,但是不会显示播放器窗口
       autoplay  默认自动播放
      -->
    <!-- <audio autoplay controls id='audioplayer'></audio> -->
  <table>
   <tr>
    <td><video autoplay playsinline id="player"></video></td>
    <td><video playsinline id="recplayer"></video></td>
    <td><div id='constraints' class='output'></div></td>
   </tr>
   <tr>
    <td><button id="record">Start Record</button></td>
    <td><button id="recplay" disabled>Play</button></td>
    <td><button id="download" disabled>Download</button></td>
   </tr>
  </table>

    <!-- 获取视频帧图片按钮 -->
  <div>
   <button id="snapshot">Take snapshot</button>
    </div>
    <!-- 获取视频帧图片显示在canvas里面 -->
  <div>
   <canvas id="picture"></canvas>
  </div>
    <!-- 引入 adapter.js库 来做 不同浏览器的兼容 -->
    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script src="./js/client.js"></script>
  </body>
</html>

client.js

'use strict'

var audioSource = document.querySelector('select#audioSource');
var audioOutput = document.querySelector('select#audioOutput');
var videoSource = document.querySelector('select#videoSource');
// 获取video标签
// var videoplay = document.querySelector('video#player');
// 获取音频标签
var audioplay = document.querySelector('audio#audioplayer');

//div
var divConstraints = document.querySelector('div#constraints');

//filter 特效选择
var filtersSelect = document.querySelector('select#filter');

//picture 获取视频帧图片相关的元素
var snapshot = document.querySelector('button#snapshot');
var picture = document.querySelector('canvas#picture');
picture.width = 640;
picture.height = 480;

// deviceInfos是设备信息的数组
function gotDevices(deviceInfos){
  // 遍历设备信息数组, 函数里面也有个参数是每一项的deviceinfo, 这样我们就拿到每个设备的信息了
 deviceInfos.forEach(function(deviceinfo){
    // 创建每一项
  var option = document.createElement('option');
  option.text = deviceinfo.label;
  option.value = deviceinfo.deviceId;
 
  if(deviceinfo.kind === 'audioinput'){ // 音频输入
   audioSource.appendChild(option);
  }else if(deviceinfo.kind === 'audiooutput'){ // 音频输出
   audioOutput.appendChild(option);
  }else if(deviceinfo.kind === 'videoinput'){ // 视频输入
   videoSource.appendChild(option);
  }
 })
}

// 获取到流做什么, 在gotMediaStream方面里面我们要传人一个参数,也就是流,
// 这个流里面实际上包含了音频轨和视频轨,因为我们通过constraints设置了要采集视频和音频
// 我们直接吧这个流赋值给HTML中赋值的video标签
// 当时拿到这个流了,说明用户已经同意去访问音视频设备了
function gotMediaStream(stream){  
   // audioplay.srcObject = stream;
  videoplay.srcObject = stream; // 指定数据源来自stream,这样视频标签采集到这个数据之后就可以将视频和音频播放出来
  // 通过stream来获取到视频的track 这样我们就将所有的视频流中的track都获取到了,这里我们只取列表中的第一个
  var videoTrack = stream.getVideoTracks()[0];
  // 拿到track之后我们就能调用Track的方法
  var videoConstraints = videoTrack.getSettings(); // 这样就可以拿到所有video的约束
  // 将这个对象转化成json格式
  // 第一个是videoConstraints, 第二个为空, 第三个表示缩进2格
 divConstraints.textContent = JSON.stringify(videoConstraints, null, 2);

  // 当我们采集到音视频的数据之后,我们返回一个Promise
  return navigator.mediaDevices.enumerateDevices();
}

function handleError(err){
 console.log('getUserMedia error:', err);
}
function start() {
// 判断浏览器是否支持
if(!navigator.mediaDevices ||
  !navigator.mediaDevices.getUserMedia){
  console.log('getUserMedia is not supported!');
}else{
  // 获取到deviceId
  var deviceId = videoSource.value; 
  // 这里是约束参数,正常情况下我们只需要是否使用视频是否使用音频
  // 对于视频就可以按我们刚才所说的做一些限制
  var constraints = { // 表示同时采集视频金和音频
    video : {
      width: 640, // 宽带
      height: 480,  // 高度
      frameRate:15, // 帧率
      facingMode: 'enviroment', //  设置为后置摄像头
      deviceId : deviceId ? deviceId : undefined // 如果deviceId不为空直接设置值,如果为空就是undefined
    }, 
    audio : true // 将声音获取设为true
  }
  //  从指定的设备中去采集数据
  navigator.mediaDevices.getUserMedia(constraints)
    .then(gotMediaStream)  // 使用Promise串联的方式,获取流成功了
    .then(gotDevices)
    .catch(handleError);
}
}

start();

// 当我选择摄像头的时候,他可以触发一个事件,
// 当我调用start之后我要改变constraints
videoSource.onchange = start;

// 选择特效的方法
filtersSelect.onchange = function(){
 videoplay.className = filtersSelect.value;
}

// 点击按钮获取视频帧图片
snapshot.onclick = function() {
  picture.className = filtersSelect.value;
  // 调用canvas API获取上下文,图片是二维的,所以2d,这样我们就拿到它的上下文了
  // 调用drawImage绘制图片,第一个参数就是视频,我们这里是videoplay,
  // 第二和第三个参数是起始点 0,0
  // 第四个和第五个参数表示图片的高度和宽度
 picture.getContext('2d').drawImage(videoplay, 0, 0, picture.width, picture.height);
}

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP