WebRTC学习六:MediaStream 常用API介绍

打印 上一主题 下一主题

主题 920|帖子 920|积分 2760

系列文章目录

第一篇 基于SRS 的 WebRTC 情况搭建
第二篇 基于SRS 实现RTSP接入与WebRTC播放
第三篇 centos下基于ZLMediaKit 的WebRTC 情况搭建
第四篇 WebRTC学习一:获取音频和视频设备
第五篇 WebRTC学习二:WebRTC音视频数据采集
第六篇 WebRTC学习三:WebRTC音视频束缚
第七篇 WebRTC学习四:WebRTC常规视觉滤镜
第八篇 WebRTC学习五:从视频中提取图片
第九篇 WebRTC学习六:MediaStream 常用API介绍


  

前言

WebRTC(Web Real-Time Communication)是一个强盛的技能,可以让网页应用程序和网站举行实时音频、视频和数据共享。通过使用 WebRTC,开发者可以实现高质量的音视频通话,构建实时多媒体应用,而无需用户安装任何插件。本文将在前面文章的基础上进一步介绍 WebRTC 中的 MediaStream API,这是一组用于处理音频和视频流的常用方法。我们将深入探讨这些方法的用法,并给出一个简单的示例,帮助大家更好地理解如安在实际应用中运用这些 API。

一、WebRTC MediaStream API 常用方法

1.getUserMedia()

getUserMedia() 方法是 WebRTC 的焦点,用于请求访问用户的音频和视频设备。该方法接受一个束缚对象,指定请求的音频和视频选项。
  1. navigator.mediaDevices.getUserMedia({
  2.     video: true,
  3.     audio: true
  4. }).then(function(stream) {
  5.     // 处理成功获取的媒体流
  6. }).catch(function(error) {
  7.     // 处理错误
  8. });
复制代码
2.MediaStream.getTracks()

通过 getTracks() 方法,可以获取与媒体流相关的全部轨道。此方法返回一个包罗全部轨道的数组。
  1. const tracks = stream.getTracks();
复制代码
3.MediaStream.getAudioTracks()

getAudioTracks() 方法返回音频轨道的数组,便于单独使用或管理音频流。
  1. const audioTracks = stream.getAudioTracks();
复制代码
4.MediaStream.getVideoTracks()

getVideoTracks() 方法返回视频轨道的数组,开发者可以使用该方法来处理视频相关的使用。
  1. const videoTracks = stream.getVideoTracks();
复制代码
5.MediaStream.addTrack()

假如需要将新轨道添加到现有的媒体流,可以使用 addTrack() 方法。
  1. stream.addTrack(newTrack);
复制代码
6.MediaStream.removeTrack()

该方法允许从媒体流中移除指定的轨道。使用时,将要移除的轨道作为参数传入。
  1. stream.removeTrack(track);
复制代码
7.MediaStream.clone()

clone() 方法用于创建媒体流的副本,副本中的轨道是原轨道的副本,方便用于差别的目标。
  1. const clonedStream = stream.clone();
复制代码
8.MediaStream.active

该属性为只读布尔值,指示媒体流是否包罗至少一个活动的轨道。可以用来判断流的状态。
  1. if (stream.active) {
  2.     console.log("Stream is active");
  3. }
复制代码
2.MediaStream.getTracks()

通过 getTracks() 方法,可以获取与媒体流相关的全部轨道。此方法返回一个包罗全部轨道的数组。
  1. const tracks = stream.getTracks();
复制代码
9.事件处理

onactive 和 oninactive 事件可以用于跟踪轨道的活动状态。当轨道变为活动或非活动时,会触发相应的事件。
  1. stream.onactive = function() {
  2.     console.log("At least one track is active");
  3. };
  4. stream.oninactive = function() {
  5.     console.log("All tracks are inactive");
  6. };
复制代码
二、示例

1.html代码

index.html文件内容如下:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>WebRTC获取视频约束</title>
  7.     <link rel="stylesheet" href="./css/style.css"> <!-- 引入CSS文件 -->
  8. </head>
  9. <body>
  10.     <div id="controls">
  11.         <div>
  12.             <label>Audio Source:</label>
  13.             <select id="audioSource"></select>
  14.         </div>
  15.         <div>
  16.             <label>Audio Output:</label>
  17.             <select id="audioOutput"></select>
  18.         </div>
  19.         <div>
  20.             <label>Video Source:</label>
  21.             <select id="videoSource"></select>
  22.         </div>
  23.         <div>
  24.             <label>Filter:</label>
  25.             <select id="filter">
  26.                 <option value="none">None</option>
  27.                 <option value="blur">Blur</option>
  28.                 <option value="grayscale">Grayscale</option>
  29.                 <option value="invert">Invert</option>
  30.                 <option value="sepia">sepia</option>
  31.             </select>
  32.         </div>
  33.     </div>
  34.     <div id="videoContainer">
  35.         <table>
  36.             <tr>
  37.                 <td><video autoplay playsinline id="player"></video></td>
  38.                 <td><div id="video-tracks" class="Output"></div></td>
  39.                 <td><div id="audio-tracks" class="Output"></div></td>
  40.             </tr>
  41.         
  42.         </table>
  43.     </div>
  44.    
  45.    
  46.     <script src="../adapter.js"></script>
  47.     <script src="./js/client.js"></script>
  48. </body>
  49. </html>
复制代码
2.css代码

style.css文件内容如下:
  1. body {
  2.     display: flex;
  3.     flex-direction: column;
  4.     align-items: center;
  5.     font-family: Arial, sans-serif;
  6.     margin: 0;
  7.     padding: 20px;
  8. }
  9. #controls {
  10.     display: flex;
  11.     justify-content: space-between;
  12.     width: 100%;
  13.     max-width: 800px; /* 设置一个最大宽度 */
  14.     margin-bottom: 20px; /* 控件与视频和画布的间距 */
  15. }
  16. #videoContainer {
  17.     display: flex;
  18. }
  19. #player {
  20.     width: 400px; /* 设置视频宽度 */
  21.     height: auto; /* 自动高度 */
  22.     border: 1px solid #ccc; /* 可选,给视频一个边框 */
  23. }
  24. .Output {
  25.     font-family: Arial, sans-serif;
  26.     font-size: 14px;
  27.     line-height: 1.1;
  28.     padding: 10px;
  29.     border: 1px solid #7c6464;
  30.     border-radius: 5px;
  31.     background-color: #f9f9f9;
  32. }
  33. .Output div {
  34.     margin-bottom: 2px;
  35. }
  36. button {
  37.     margin-top: 10px; /* 按钮与其它元素之间的间距 */
  38. }
  39. select {
  40.     margin-right: 10px; /* 下拉框之间的间距 */
  41. }
  42. .none {
  43.     -webkit-filter:none;
  44. }
  45. .blur {
  46.     -webkit-filter: blur(3px);
  47. }
  48. .grayscale {
  49.     -webkit-filter: grayscale(1);
  50. }
  51. .invert {
  52.     -webkit-filter: invert(1);
  53. }
  54. .sepia {
  55.     -webkit-filter: sepia(1);
  56. }
复制代码
3.js代码

client.js文件内容如下:
  1. 'use strict';
  2. const audioSource = document.querySelector('select#audioSource');
  3. const audioOutput = document.querySelector('select#audioOutput');
  4. const videoSource = document.querySelector('select#videoSource');
  5. const filterSelect = document.querySelector('select#filter');
  6. const snapshot = document.querySelector('button#snapshot');
  7. const picture = document.querySelector('canvas#picture');
  8. const videoplay = document.querySelector('video#player');
  9. // const audioplay = document.querySelector('audio#audioplayer');
  10. var videoTrackConstraints = document.querySelector('div#video-tracks');
  11. var audioTrackContainer = document.querySelector('div#audio-tracks');
  12.    
  13. // 获取设备列表
  14. function gotDevices(deviceInfos) {
  15.     deviceInfos.forEach(deviceInfo => {
  16.         const option = document.createElement('option');
  17.         option.text = deviceInfo.label;
  18.         option.value = deviceInfo.deviceId;
  19.         switch (deviceInfo.kind) {
  20.             case "audioinput":
  21.                 audioSource.appendChild(option);
  22.                 break;
  23.             case "audiooutput":
  24.                 audioOutput.appendChild(option);
  25.                 break;
  26.             case "videoinput":
  27.                 videoSource.appendChild(option);
  28.                 break;
  29.         }
  30.     });
  31. }
  32. // 获取媒体流
  33. function gotMediaStream(stream) {
  34.      videoplay.srcObject = stream;
  35.     var videoTracks = stream.getVideoTracks()[0];
  36.     var videoConstraints = videoTracks.getSettings();
  37.     // 将 JSON 对象转换为 HTML 字符串
  38.     let constraintsHTML = '';
  39.     constraintsHTML = '<h2>视频轨道</h2>';
  40.     for (const [key, value] of Object.entries(videoConstraints)) {
  41.         constraintsHTML += `<div><strong>${key}:</strong> ${value}</div>`;
  42.     }
  43.    
  44.     // 插入到 div 元素中
  45.     videoTrackConstraints.innerHTML = constraintsHTML;
  46.     // 显示音频轨道信息
  47.     const audioTracks = stream.getAudioTracks()[0];
  48.     var audioConstraints = audioTracks.getSettings();
  49.     let audioconstraintsHTML = '';
  50.     audioconstraintsHTML= '<h2>音频轨道</h2>';
  51.    
  52.     for (const [key, value] of Object.entries(audioConstraints)) {
  53.         audioconstraintsHTML += `<div><strong>${key}:</strong> ${value}</div>`;
  54.     }
  55.     audioTrackContainer.innerHTML = audioconstraintsHTML;
  56.     return navigator.mediaDevices.enumerateDevices();
  57. }
  58. // 处理错误
  59. function handleError(err) {
  60.     console.error('getUserMedia error:', err);
  61. }
  62. // 启动媒体流
  63. function start() {
  64.     if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
  65.         console.error('getUserMedia is not supported!');
  66.         return;
  67.     }
  68.     const constraints = {
  69.         video: {
  70.             width: 640,
  71.             height: 480,
  72.             frameRate: 30,
  73.             facingMode: "environment",
  74.             deviceId: videoSource.value ? { exact: videoSource.value } : undefined, // 确保使用确切的设备ID
  75.         },
  76.         
  77.         audio: {
  78.             noiseSuppression: true,
  79.             echoCancellation: true
  80.         }
  81.     };
  82.     navigator.mediaDevices.getUserMedia(constraints)
  83.         .then(gotMediaStream)
  84.         .then(gotDevices)
  85.         .catch(handleError);
  86. }
  87. // 滤镜选择更改事件
  88. filterSelect.onchange = function () {
  89.     videoplay.className = filterSelect.value;
  90. };
  91. // 初始化
  92. start();
  93. videoSource.onchange = start;
复制代码
二、演示效果

在欣赏器中打开 index.html 文件,运行成功的话可以看到左边是视频画面,中间是获取的视频轨道信息,右边是音频轨道信息,下图是我的欣赏器上显示的效果。


总结

WebRTC 的 MediaStream API 提供了一系列强盛而灵活的方法,可以轻松访问和管理用户的音频与视频流。通过使用这些 API,开发者可以大概构建高质量的实时通讯应用。本文介绍的常用 API 及其用法,结合示例代码,希望能帮助大家更好地理解如何使用这些接口。
假如你对 WebRTC 另有其他题目或希望相识更多内容,请随时留言或分享你的看法。
   你好,我是阿灿,慢慢理解世界,慢慢更新自己。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

莫张周刘王

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表