头图

WebRTC网页录制音视频教程

导语:最近研究了一下网页录制音视频的原理以及实现,现在就目前的实现方法做一个总结。

目录

  • 相关API
  • 方法介绍
  • 实战演练

相关API

要实现这个功能就涉及到两个js api。

方法介绍

getUserMedia

通过getUserMedia这个接口来获取设备的摄像头和麦克风,返回一个Promise对象。

语法var stream = navigator.mediaDevices.getUserMedia(constraints);

constraints包括一下几种写法:

  • 请求音视频
const constraints = {
    audio: true,
    video: true
}
  • 请求特定的设备视频分辨率
const constraints = {
    audio: true,
    video: {
        width: { 
            min: 1280 
        },
        height: { 
            min: 720 
        }
    }
}
  • 使用前摄像头(默认)
const constraints = {
    audio: true,
    video: {
        facingMode: "user"
    }
}
  • 强制使用后置摄像头
const constraints = {
    audio: true,
    video: {
        facingMode: {
            exact: "environment"
        }
    }
}

例如:

const constraints = {
    audio: true,
    video: {
        width: 1280,
        height: 720
    }
};

async function createMedia() {
    try {
        let stream = await navigator.mediaDevices.getUserMedia(constraints);
        var video = document.querySelector('video');
        video.srcObject = stream;
        video.onloadedmetadata = function (e) {
            video.play();
        };
    } catch (error) {
        console.log(`getUserMedia: ${error}`);
    }
}

createMedia();

当然了这个stream还有一些方法可以使用,比如

  • addTrack 给流添加一个新轨道
  • getAudioTracks包含流中所有的音轨
  • getVideoTracks 于媒体流中包含的每个视频轨道
  • getTracks 此流的中的所有对象

MediaRecorder

这个就是录制流的一个方法。

  • start 开始录制
  • stop 结束录制
  • onstop 监听结束事件
  • ondataavailable 实时流数据

语法var mediaRecorder = new MediaRecorder(stream[, options]);

例如

// stream就是上面获取的音视频流
let options = {
    audioBitsPerSecond : 128000,
    videoBitsPerSecond : 2500000,
}
let mediaRecorder = new MediaRecorder(stream, options);

// 实时的录制流数据
mediaRecorder.ondataavailable = function (e) {  
    console.log(e.data);
}

// 监听停止录制事件并生成播放地址
mediaRecorder.onstop = function () {
    let blob = new Blob(chunks, {'type': mediaRecorder.mimeType});
    let url = window.URL.createObjectURL(blob);
    console.log(url);
}

实战演练

  • 页面结构部分
<audio controls src=""></audio>
<video controls src="" style="width: 100%;"></video>
<button id="start">开始音频</button>
<button id="stop">结束音频</button>
<button id="play">播放音频</button>
<button id="startVideo">开始视频</button>
<button id="stopVideo">结束视频</button>
<button id="playVideo">播放视频</button>
  • js部分

获取元素添加事件

// 获取按钮
let audioStart = document.querySelector('#start');
let audioStop = document.querySelector('#stop');
let audioPlay = document.querySelector('#play');
let startVideo = document.querySelector('#startVideo');
let stopVideo = document.querySelector('#stopVideo');
let playVideo = document.querySelector('#playVideo');

// 音频操作
audioStart.onclick = function () {  
    start('audio');
}

audioStop.onclick = function () {  
    stop('audio');
}

audioPlay.onclick = function () {  
    document.querySelector('audio').play();
}

// 视频操作
startVideo.onclick = function () {  
    start('video');
}

stopVideo.onclick = function () {  
    stop('video');
}

playVideo.onclick = function () {  
    document.querySelector('video').play();
}

开始录制

// 开始录制
function start (type) {
    let option = type == 'audio' ? {
        audio: true
    } : {
        video: true,
    }
    createMedia(type, option);
}

停止录制

// 停止录制
function stop (type) {
    mediaRecorder.stop();
}

function stopSet (type) {  
    if (type == 'audio') {
        stream.getAudioTracks()[0].stop();
        stream = null;
    } else {
        stream.getVideoTracks()[0].stop();
    }
    stream = null;
    mediaRecorder = null;
    chunks = [];
    meida = null;
}

通用方法

// 全局参数
let stream = null,mediaRecorder = null,chunks = [], media = null;
async function createMedia (type, option) {  
    try {
        // 获取媒体流
        stream = await navigator.mediaDevices.getUserMedia(option);
        media = document.querySelector(type);
        if (type === 'video') {
            media.srcObject = stream;
        }
        console.log(type, stream);

        // 录制流
        let options = {
            audioBitsPerSecond : 128000,
            videoBitsPerSecond : 2500000,
        }
        mediaRecorder = new MediaRecorder(stream, options);
        console.log(type, mediaRecorder);

        mediaRecorder.ondataavailable = function (e) {  
            chunks.push(e.data);
        }

        mediaRecorder.start();

        // 停止录制
        mediaRecorder.onstop = function () {
            let blob = new Blob(chunks, {'type': mediaRecorder.mimeType});
            let url = window.URL.createObjectURL(blob);
            if (type === 'video') {
                media.srcObject = null;
            }
            media.src = url;
            stopSet(type);
        }

    } catch (error) {
        console.log('getUserMedia: ', error);
    }
}

看下效果

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

想要体验的可以打开这个音视频录制,手机上使用更佳。

好了,今天的教程就介绍到这里,拜拜!

Talk is cheap, show me the code.

54 声望
2 粉丝
0 条评论
推荐阅读
测速工具使用心得体会
导语:之前写过一个测速小工具,使用的是speedtest-cli提供的api方法,当然除了这个还有其他的测速工具,今天就这个测速工具来说一下使用体验和感受。

MarkGuan阅读 632

封面图
Linux下编译WebRTC(Linux和Android版本)
随着新冠疫情的影响,这两年音视频的需求呈爆发式增长。在音视频领域中,WebRTC可以说是一个绕不开宝库,包括了音视频采集、编解码、传输、渲染的全过程。本文主要记录下在Linux平台上编译WebRTC Linux和Android...

吴尼玛阅读 3.3k评论 2

我用ChatGPT做WebRTC音视频性能优化,主打一个高效
随着GPT-4的发布,AI的风越吹越旺。GPT-4可以回答问题,可以写作,甚至可以基于一张草图生成html代码搭建一个网站。即构社区的一位开发者@倪同学就基于目前在研究的WebRTC QOS技术点对GPT-3.5跟GPT-4进行一场实验...

即构开发者阅读 329

WebRTC中的NAT穿透
我们知道,WebRTC会按照内网、P2P、中转的顺序来尝试连接。在大部分的情况下,实际是使用P2P或者中转的。这里P2P的场景主要使用的技术就是NAT穿透。

吴尼玛阅读 282

WebRTC 真实IP泄露防范
很多人可能误以为使用代理就可以完全隐藏我们的真实IP地址,但实际并不总是这样。事实上,有大量文章指出,WebRTC存在安全风险,而WebRTC安全风险的可怕之处在于,即使你使用VPN代理上网,仍然可能会暴露自己的真...

初始安全阅读 197

Talk is cheap, show me the code.

54 声望
2 粉丝
宣传栏