【音视频】WebRTC-Web 音视频采集与播放

一、打开摄像头

打开摄像头首先需要有一个htmlvideo标签:

  • id = "local-video",是为了后续的js脚本调用这个对象
  • autoplay是设置打开后自动播放,playsinline则是为了兼容移动端
html 复制代码
 <video id = "local-video" autoplay playsinline></video>

添加<script>脚本标签:

  • 需要定义一个constraints对象,内部需要设置音频和视频的打开情况,比如这里只打开摄像头,则:
js 复制代码
//媒体限制
const constraints = {
	audio:false,
	video:true
};
  • 通过documentquerySelector方法,返回对应标签id的对象,比如这里要得到<video>标签,就传入"#local-video",如果要得到对应的<button>标签对象,则查找"#showVideoBtn"
js 复制代码
const video = document.querySelector("#local-video");
document.querySelector("#showVideoBtn").addEventListener("click",onOpenCamera);
  • 要在点击按钮后,打开摄像头,我们要实现下面三个回调函数:

handleSucess

js 复制代码
function handleSuccess(stream){
	//document是内置全局变量,表示当前HTML文档,这里是选择对应的video对象
	const video = document.querySelector("#local-video"); //#local-video选择对应的id,返回的是引用
	video.srcObject = stream; //把视频流赋值给video对象
}

function handleError(error){
	//console是内置全局变量,表示浏览器端的控制台
	console.error("getUserMedia error:" + error); //控制台打印错误
}

这个函数在打开摄像头成功之后调用,会传入一个stream对象,表示对应的媒体流,我们在这个回调函数中要将媒体流传入上述<video>标签对象,具体的方法是赋值<video>对象的srcObject属性:

js 复制代码
video.srcObject = stream;

handleError

js 复制代码
function handleError(error){
	//console是内置全局变量,表示浏览器端的控制台
	console.error("getUserMedia error:" + error); //控制台打印错误
}

这个函数用于打开摄像头失败之后的回调函数,传入错误信息,我们可以在控制台打印对应的信息:

onOpenCamera

js 复制代码
 function onOpenCamera(e){
		//navigator也是内置全局变量,表示导航对象
		//mediaDevice是对应的媒体设备对象
		//getUserMedia是获取用户媒体的方法,返回一个Promise对象,promise执行成功后调用then函数,失败触发catch函数
		navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);
	}

这个函数在我们按钮点击后触发,是按钮点击的事件回调函数,传入一个事件对象,我们可以在这个事件回调函数内部调用navigator对象的mediaDevices.getUserMedia方法,也就是先获得媒体设备,然后在将我们的媒体限制、回调函数绑定,具体如下:

  • getUserMedia函数返回一个promise对象,这个对象执行完打开摄像头任务后,会调用对应的函数
    • 如果任务成功,调用then里面的回调函数
    • 如果任务错误,调用catch里面的回调函数
js 复制代码
navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);

最后,我们需要将按钮的点击事件回调函数绑定在showVideoBtn

js 复制代码
document.querySelector("#showVideoBtn").addEventListener("click",onOpenCamera);

完整代码如下:

html 复制代码
<!DOCTYPE html>

<html> 
    <body>
        <video id = "local-video" autoplay playsinline></video>
        <button id = "showVideoBtn"> 打开摄像头</button>
        <p>通过getUserMedia获取视频</p>
    </body>

    <script>
        //媒体限制
        const constraints = {
            audio:false,
            video:true
        };
        
        function handleSuccess(stream){
            //document是内置全局变量,表示当前HTML文档,这里是选择对应的video对象
            const video = document.querySelector("#local-video"); //#local-video选择对应的id,返回的是引用
            video.srcObject = stream; //把视频流赋值给video对象
        }

        function handleError(error){
            //console是内置全局变量,表示浏览器端的控制台
            console.error("getUserMedia error:" + error); //控制台打印错误
        }

        function onOpenCamera(e){
            //navigator也是内置全局变量,表示导航对象
            //mediaDevice是对应的媒体设备对象
            //getUserMedia是获取用户媒体的方法,返回一个Promise对象,promise执行成功后调用then函数,失败触发catch函数
            navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);
        }
        
        //绑定按钮的点击事件,点击后调用onOpenCamera函数
        document.querySelector("#showVideoBtn").addEventListener("click",onOpenCamera);
    </script>

</html>

Web页面效果如下:

二、打开麦克风

打开麦克风和打开摄像头类似,把对应的<video>标签改为audio标签,然后添加上controls模块,这个模块是添加一些暂停、声音调节等功能

html 复制代码
<audio id = "local-audio" autoplay controls></audio>

还需要要修改对应的媒体限制对象constraints,关闭video,打开audio

js 复制代码
const constraints = {
	video: false,
	audio: true
}

其他部分和打开摄像头保持一致

html 复制代码
<!DOCTYPE html>
<html>
    <body>
        <audio id = "local-audio" autoplay controls></audio>
        <button id = "showAudioBtn"> 打开麦克风</button>
        <p>通过getUserMedia获取音频</p>
    </body>

    <!--类似video部分的js脚本-->
    <script>
        const constraints = {
            video: false,
            audio: true
        }

        function handleSuccess(stream){
            const audio = document.querySelector("#local-audio");
            audio.srcObject = stream;
        }

        function handleError(error){
            console.error("getUserMedia error" + error);
        }

        function onOpenMicrophone(e){
            navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);
        }
        
        showAudioBtn = document.querySelector("#showAudioBtn");
        showAudioBtn.addEventListener("click",onOpenMicrophone);
    </script>

</html>

Web页面效果如下:

三、同时打开摄像头和麦克风

同时打开摄像头和麦克风,和打开摄像头一致,唯一需要修改的就是媒体限制对象constraints,将视频和音频都设置为true

js 复制代码
const constraints = {
	video: true,
	audio: true
}

完整代码如下:

html 复制代码
<!DOCTYPE html>

<html>
    <body>
        <video id = "local-video" autoplay playsinline></video>
        <button id = "showVideoAudioBtn"> 打开摄像头和麦克风</button>
        <p>通过getUserMedia获取摄像头和麦克风</p>
    </body>

    <script>
        const constraints = {
            video: true,
            audio: true
        }
        
        function handleSuccess(stream){
            const video = document.querySelector("#local-video");
            video.srcObject = stream;
        }
        
        function handleError(error){
            console.error("getUserMedia error" + error);
        }
        
        function onOpenVideo_Audio (e){
            navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);
        }

        showVideoBtn = document.querySelector("#showVideoAudioBtn");
        showVideoBtn.addEventListener("click",onOpenVideo_Audio);

    </script>
    </html>

更多资料:https://github.com/0voice

相关推荐
想学后端的前端工程师14 分钟前
【Vue3组合式API实战指南:告别Options API的烦恼】
前端·javascript·vue.js
否子戈24 分钟前
WebCut前端视频编辑UI框架一周开源进度
前端·音视频开发·ui kit
昔人'1 小时前
`corepack` 安装pnpm
前端·pnpm·node·corepack
萌萌哒草头将军1 小时前
pnpm + monorepo 才是 AI 协同开发的最佳方案!🚀🚀🚀
前端·react.js·ai编程
音视频牛哥2 小时前
【深度选型】RTSP超低延迟播放器:自研陷阱与成熟模块的效益分析
音视频·rtsp播放器·低延迟rtsp播放器·linux rtsp播放器·windows rtsp播放器·安卓rtsp播放器·ios rtsp播放器
hboot2 小时前
💪别再迷茫!一份让你彻底掌控 TypeScript 类型系统的终极指南
前端·typescript
GISer_Jing2 小时前
深入拆解Taro框架多端适配原理
前端·javascript·taro
毕设源码-邱学长2 小时前
【开题答辩全过程】以 基于VUE的藏品管理系统的设计与实现为例,包含答辩的问题和答案
前端·javascript·vue.js
用户28907942162713 小时前
Spec-Kit应用指南
前端
酸菜土狗3 小时前
🔥 手写 Vue 自定义指令:实现内容区拖拽调整大小(超实用)
前端