当前位置: 首页 > article >正文

WebRTC学习六:MediaStream 常用API介绍

系列文章目录

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


文章目录

  • 系列文章目录
  • 前言
  • 一、WebRTC MediaStream API 常用方法
    • 1.getUserMedia()
    • 2.MediaStream.getTracks()
    • 3.MediaStream.getAudioTracks()
    • 4.MediaStream.getVideoTracks()
    • 5.MediaStream.addTrack()
    • 6.MediaStream.removeTrack()
    • 7.MediaStream.clone()
    • 8.MediaStream.active
    • 2.MediaStream.getTracks()
    • 9.事件处理
  • 二、示例
    • 1.html代码
    • 2.css代码
    • 3.js代码
  • 二、演示效果
  • 总结


前言

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


一、WebRTC MediaStream API 常用方法

1.getUserMedia()

getUserMedia() 方法是 WebRTC 的核心,用于请求访问用户的音频和视频设备。该方法接受一个约束对象,指定请求的音频和视频选项。

navigator.mediaDevices.getUserMedia({ 
    video: true, 
    audio: true 
}).then(function(stream) {
    // 处理成功获取的媒体流
}).catch(function(error) {
    // 处理错误
});

2.MediaStream.getTracks()

通过 getTracks() 方法,可以获取与媒体流相关的所有轨道。此方法返回一个包含所有轨道的数组。

const tracks = stream.getTracks();

3.MediaStream.getAudioTracks()

getAudioTracks() 方法返回音频轨道的数组,便于单独操作或管理音频流。

const audioTracks = stream.getAudioTracks();

4.MediaStream.getVideoTracks()

getVideoTracks() 方法返回视频轨道的数组,开发者可以使用该方法来处理视频相关的操作。

const videoTracks = stream.getVideoTracks();

5.MediaStream.addTrack()

如果需要将新轨道添加到现有的媒体流,可以使用 addTrack() 方法。

stream.addTrack(newTrack);

6.MediaStream.removeTrack()

该方法允许从媒体流中移除指定的轨道。使用时,将要移除的轨道作为参数传入。

stream.removeTrack(track);

7.MediaStream.clone()

clone() 方法用于创建媒体流的副本,副本中的轨道是原轨道的副本,方便用于不同的目的。

const clonedStream = stream.clone();

8.MediaStream.active

该属性为只读布尔值,指示媒体流是否包含至少一个活动的轨道。可以用来判断流的状态。

if (stream.active) {
    console.log("Stream is active");
}

2.MediaStream.getTracks()

通过 getTracks() 方法,可以获取与媒体流相关的所有轨道。此方法返回一个包含所有轨道的数组。

const tracks = stream.getTracks();

9.事件处理

onactive 和 oninactive 事件可以用于跟踪轨道的活动状态。当轨道变为活动或非活动时,会触发相应的事件。

stream.onactive = function() {
    console.log("At least one track is active");
};

stream.oninactive = function() {
    console.log("All tracks are inactive");
};

二、示例

1.html代码

index.html文件内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebRTC获取视频约束</title>
    <link rel="stylesheet" href="./css/style.css"> <!-- 引入CSS文件 -->
</head>
<body>
    <div id="controls">
        <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>
    </div>

    <div id="videoContainer">
        <table>
            <tr>
                <td><video autoplay playsinline id="player"></video></td>
                <td><div id="video-tracks" class="Output"></div></td>
                <td><div id="audio-tracks" class="Output"></div></td>
            </tr>
        
        </table>
    </div>
    
    
    <script src="../adapter.js"></script>
    <script src="./js/client.js"></script>
</body>
</html>

2.css代码

style.css文件内容如下:

body {
    display: flex;
    flex-direction: column;
    align-items: center;
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 20px;
}

#controls {
    display: flex;
    justify-content: space-between;
    width: 100%;
    max-width: 800px; /* 设置一个最大宽度 */
    margin-bottom: 20px; /* 控件与视频和画布的间距 */
}

#videoContainer {
    display: flex;
}

#player {
    width: 400px; /* 设置视频宽度 */
    height: auto; /* 自动高度 */
    border: 1px solid #ccc; /* 可选,给视频一个边框 */
}

.Output {
    font-family: Arial, sans-serif;
    font-size: 14px;
    line-height: 1.1;
    padding: 10px;
    border: 1px solid #7c6464;
    border-radius: 5px;
    background-color: #f9f9f9;
}

.Output div {
    margin-bottom: 2px;
}

button {
    margin-top: 10px; /* 按钮与其它元素之间的间距 */
}

select {
    margin-right: 10px; /* 下拉框之间的间距 */
}

.none {
    -webkit-filter:none;
}
.blur {
    -webkit-filter: blur(3px);
}
.grayscale {
    -webkit-filter: grayscale(1);
}
.invert {
    -webkit-filter: invert(1);
}
.sepia {
    -webkit-filter: sepia(1);
}

3.js代码

client.js文件内容如下:

'use strict';

const audioSource = document.querySelector('select#audioSource');
const audioOutput = document.querySelector('select#audioOutput');
const videoSource = document.querySelector('select#videoSource');
const filterSelect = document.querySelector('select#filter');

const snapshot = document.querySelector('button#snapshot');
const picture = document.querySelector('canvas#picture');

const videoplay = document.querySelector('video#player');
// const audioplay = document.querySelector('audio#audioplayer');
var videoTrackConstraints = document.querySelector('div#video-tracks');
var audioTrackContainer = document.querySelector('div#audio-tracks');
    

// 获取设备列表
function gotDevices(deviceInfos) {
    deviceInfos.forEach(deviceInfo => {
        const option = document.createElement('option');
        option.text = deviceInfo.label;
        option.value = deviceInfo.deviceId;

        switch (deviceInfo.kind) {
            case "audioinput":
                audioSource.appendChild(option);
                break;
            case "audiooutput":
                audioOutput.appendChild(option);
                break;
            case "videoinput":
                videoSource.appendChild(option);
                break;
        }
    });
}

// 获取媒体流
function gotMediaStream(stream) {
     videoplay.srcObject = stream;
    var videoTracks = stream.getVideoTracks()[0];
    var videoConstraints = videoTracks.getSettings();
    // 将 JSON 对象转换为 HTML 字符串
    let constraintsHTML = '';
    constraintsHTML = '<h2>视频轨道</h2>';
    for (const [key, value] of Object.entries(videoConstraints)) {
        constraintsHTML += `<div><strong>${key}:</strong> ${value}</div>`;
    }
    
    // 插入到 div 元素中
    videoTrackConstraints.innerHTML = constraintsHTML;

    // 显示音频轨道信息
    const audioTracks = stream.getAudioTracks()[0];
    var audioConstraints = audioTracks.getSettings();
    let audioconstraintsHTML = '';
    audioconstraintsHTML= '<h2>音频轨道</h2>';
    
    for (const [key, value] of Object.entries(audioConstraints)) {
        audioconstraintsHTML += `<div><strong>${key}:</strong> ${value}</div>`;
    }
    audioTrackContainer.innerHTML = audioconstraintsHTML;

    return navigator.mediaDevices.enumerateDevices();
}

// 处理错误
function handleError(err) {
    console.error('getUserMedia error:', err);
}

// 启动媒体流
function start() {
    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        console.error('getUserMedia is not supported!');
        return;
    }

    const constraints = {
        video: {
            width: 640,
            height: 480,
            frameRate: 30,
            facingMode: "environment",
            deviceId: videoSource.value ? { exact: videoSource.value } : undefined, // 确保使用确切的设备ID
        },
        
        audio: {
            noiseSuppression: true,
            echoCancellation: true
        }
    };

    navigator.mediaDevices.getUserMedia(constraints)
        .then(gotMediaStream)
        .then(gotDevices)
        .catch(handleError);
}

// 滤镜选择更改事件
filterSelect.onchange = function () {
    videoplay.className = filterSelect.value;
};


// 初始化
start();
videoSource.onchange = start;

二、演示效果

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

在这里插入图片描述


总结

WebRTC 的 MediaStream API 提供了一系列强大而灵活的方法,可以轻松访问和管理用户的音频与视频流。通过使用这些 API,开发者能够构建高质量的实时通信应用。本文介绍的常用 API 及其用法,结合示例代码,希望能帮助大家更好地理解如何使用这些接口。

如果你对 WebRTC 还有其他问题或希望了解更多内容,请随时留言或分享你的看法。

你好,我是阿灿,慢慢理解世界,慢慢更新自己。


http://www.kler.cn/a/372549.html

相关文章:

  • 开发中的拓展属性:增强功能与灵活性
  • LeetCode算法(链表)
  • Vue3入门--[vue/compiler-sfc] Unexpected token, expected “,“ (18:0)
  • 字符串-05-字符串合并处理
  • 合并排序算法(C语言版)
  • pyinstaller -F main.py的使用--打包python可执行文件
  • 深度学习之激活函数
  • vue3(setup) keep-alive 列表页跳转详情缓存,跳转其它更新
  • unity 中使用zeroMq和Mqtt 进行通讯
  • layui xm-select
  • HTML入门教程14:HTML图像
  • NewStarCTF2024-Week4-Web-WP
  • 关于微信小程序启用组件按需注入
  • openGauss开源数据库实战十
  • 详解:模板设计模式
  • Linux多机器文件分发
  • 时间序列分类任务---tsfresh库
  • 基于Spring Boot+Vue的健身房管理系统(协同过滤算法、功能非常多)
  • C++初阶(八)--内存管理
  • Spark RDD
  • C# CSV工具类,读取csv文件、将数据导出为csv文件格式,用DataGridView表格控件显示
  • 批量删除redis数据
  • N9300-S16语音芯片:提升电梯播报体验,实现导航声音播报提示
  • Spring Boot 创建项目详细介绍
  • list ------ 是一个带头双向循环的列表
  • 从0到1,解读安卓ASO优化!