WebRTC学习六:MediaStream 常用API介绍

系列文章目录

第一篇 基于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 的核心,用于请求访问用户的音频和视频设备。该方法接受一个约束对象,指定请求的音频和视频选项。

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

2.MediaStream.getTracks()

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

c 复制代码
const tracks = stream.getTracks();

3.MediaStream.getAudioTracks()

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

c 复制代码
const audioTracks = stream.getAudioTracks();

4.MediaStream.getVideoTracks()

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

c 复制代码
const videoTracks = stream.getVideoTracks();

5.MediaStream.addTrack()

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

c 复制代码
stream.addTrack(newTrack);

6.MediaStream.removeTrack()

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

c 复制代码
stream.removeTrack(track);

7.MediaStream.clone()

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

c 复制代码
const clonedStream = stream.clone();

8.MediaStream.active

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

c 复制代码
if (stream.active) {
    console.log("Stream is active");
}

2.MediaStream.getTracks()

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

c 复制代码
const tracks = stream.getTracks();

9.事件处理

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

c 复制代码
stream.onactive = function() {
    console.log("At least one track is active");
};

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

二、示例

1.html代码

index.html文件内容如下:

c 复制代码
<!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文件内容如下:

c 复制代码
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文件内容如下:

c 复制代码
'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 还有其他问题或希望了解更多内容,请随时留言或分享你的看法。

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

相关推荐
数据猎手小k1 小时前
W-Bench:第一个全面的基准测试,对各种图像编辑技术(图像再生、全局编辑、局部编辑和图像到视频生成)评估水印方法的稳健性。
人工智能·深度学习·音视频
Cici_ovo1 小时前
yt-dlp下载视频
音视频
离人不挽4072 小时前
视频编辑的创意工坊,使用视频剪辑软件将视频随机分割成两段并去声进行MP3音频和M3u8文件的生成,让视频制作更高效
音视频
西瓜本瓜@2 小时前
在Android开发中实现静默拍视频
android·java·开发语言·学习·音视频
FreeIPCC4 小时前
开源呼叫中心系统 FreeIPCC:WebRTC 详解
webrtc
EasyNVR6 小时前
NVR小程序接入平台/设备EasyNVR多个NVR同时管理多平台级联与上下级对接的高效应用
大数据·小程序·音视频·监控·视频监控
一只欢喜8 小时前
uniapp的video视频属性打包app后层级过高
uni-app·音视频
罚酒饮得10 小时前
QT如何给视频打时标
开发语言·qt·音视频
LNTON羚通11 小时前
算法定制LiteAIServer视频智能分析平台裸土检测技术实现、应用场景与优势概览
大数据·算法·目标检测·音视频·监控