Web上的MediaRecorder更换stream(录制过程中切换摄像头)

2023-10-29 07:30

本文主要是介绍Web上的MediaRecorder更换stream(录制过程中切换摄像头),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天有个老哥问我,MediaRecorder在录制过程中,能否改变在构造函数中引入的流。

这个我还真没有试过,之前写的H5直播虽然我一直声称在手机端可以选择前置或后置摄像头,但实际上一旦选择了就没法更改了......其实我确实有考虑过解决这个问题,但当时实在是太累(lan)了,最后答辩就给糊弄过去了,难得今天不想干正事,试试。

 

过程

首先直接MediaRecorder.stream=new_stream的想法可以省省,不用猜就知道这里面的stream肯定是个只读属性

一般遇到这种问题我都先去外网上看看有没有什么高见,堆栈溢出上看见这么一个:https://stackoverflow.com/questions/57838283/is-it-possible-to-change-mediarecorders-stream?r=SearchResults

老哥上来就说做不到,emmmmmmmm....但是提问的人问的是track,我觉得可能跟我想的是不一样的,动手试试吧。既然没法修改stream,我直接new一个新的MediaRecorder替换原来的不可以吗?

记得之前看示例的时候有一个是教如何切换使用的设备的(Choose camera, microphone and speaker),里面演示了如何切换设备以及切换后的效果,怎么实现的并不重要,没那么多时间去细细品味,扒下来代码,找到自己以前写的MediaRecorder的代码,拿出作为代码人的骄傲,开始写一个缝合怪。写到饭点,看完API的顺道去看了一下自己的Chrome版本,放那里没管吃饭去了,回来一看Chrome界面不对,自己给我更新了……更新完之后发现最早写的MediaRecorder代码不管用了我日,好在还有另一份使用blob的还可以,得重新写自己的缝合怪了

写完之后大概是这样的:

上面的video标签显示的是当前调用的摄像头的实时图像,下面的video标签播放的是使用MediaRecorder录制的,
点击Record按钮MediaRecorder就会开始工作,stop为结束录制,printstate是测试用的,在控制台打印状态信息

在魔改原来sample代码的过程中,我在设备下拉菜单的事件触发函数里加上了代码,在设备改变之后,new一个新的MediaRecorder替代原来的,将新的设备的stream作为MediaRecorder的参数传入,将其绑定起来。

function gotStream(stream) {//这个函数跟在getUserMedia之后,参数中的stream就是新设备的streamwindow.stream = stream; // make stream available to consolevideoElement.srcObject = stream;//在上面的video标签中显示//缝合怪//初始化MediaRecordervar record_options = {audioBitsPerSecond:128000,videoBitsPerSecond:2500000,mimeType : mimeType_for_test}//创建MediaRecorder//注意MediaRecorder已经在js文件的开头声明mediaRecorder=new MediaRecorder(stream,record_options);//当录制的数据可用时mediaRecorder.ondataavailable=function(e) {//console.log(e.data);if(e.data.size>0){		var reader = new FileReader();var arr = [];arr.push(e.data);var blob = new Blob(arr,{'type':mimeType_for_test});reader.readAsArrayBuffer(e.data);reader.onloadend = function(e){sourcebuffer.appendBuffer(reader.result);sourcebuffer.addEventListener('updateend',function(){});}}}//mediaRecorder.start(timecell);mediaRecorder.onstart = function(e) {console.log('Record onstart');}mediaRecorder.onstop = function(e) {console.log('Record onstop');}//缝合怪的尾巴return navigator.mediaDevices.enumerateDevices();//用于后面的函数更新设备标签
}

诶嘿嘿,不愧是我,轻易地就做到了一般人做不到的事情

但是在实际运行起来就遇到了很操蛋的问题

MediaRecorder无法start

在录制过程中直接用new MediaRecorder替换原来的会导致下面的播放卡住,即便sourcebuffer一直在不停地append但是无法播放,于是我考虑是不是在改变stream之前将录制停止,new完之后再重新开始录制。当我这么做了之后遇到了下面的问题:

于是我分阶段在控制台中打印MediaRecorder,检查它的状态

正常录制过程中
刚刚用new MediaRecorder切换完stream后
切换完过了一段时间之后

对比上面三个可以发现,在刚刚切换完stream之后,MediaRecorder下的stream属性下的active属性值是false,当一段时间过后才会变为true,当其为false时试图调用MediaRecorder.start()就会导致报错。我看到了active下面还有个onactive,诶嘿嘿这个好东西啊,这不就是active变为true时的触发事件吗,赶紧绑定函数,变为true时就启动我的MediaRecorder!

过了好久好久

“onactive还没有被实现.......”,我靠了这帮人为什么这么喜欢挖坑不填啊。被逼无奈,在切换stream后等待,当stream.active的值为true时再start我的MediaRecorder。(这里又被自己蠢到了,代码苦手最近C++写太多了,我直接写了个while(1)里面写了个判断跳出循环,然后直接把页面给卡死了....蠢到自己不自知以为是页面开太多了头铁地又试了一次...)写个setTimeout完事

function tryRestartRecorder(){if(mediaRecorder.stream.active){try{mediaRecorder.start(timecell);}catch(e){}}else{setTimeout(tryRestartRecorder,100);}
}function changestream(){try{mediaRecorder.stop();//防止MediaRecorder还没有初始化}catch(e){}start();//切换stream的函数setTimeout(tryRestartRecorder(),100);
}

这样就成了,切换音频输入输出同理。

 

navigator.mediaDevices.enumerateDevices()不显示设备名称

收尾的时候发现不显示设备名称

这个博客里面提到需要部署到服务器上去才能够获取到设备名称,可能是因为不是https连接导致navigator.mediaDevices.enumerateDevices()函数没有权限

 

Demo

demo地址

这篇关于Web上的MediaRecorder更换stream(录制过程中切换摄像头)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/299156

相关文章

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

Java Web指的是什么

Java Web指的是使用Java技术进行Web开发的一种方式。Java在Web开发领域有着广泛的应用,主要通过Java EE(Enterprise Edition)平台来实现。  主要特点和技术包括: 1. Servlets和JSP:     Servlets 是Java编写的服务器端程序,用于处理客户端请求和生成动态网页内容。     JSP(JavaServer Pages)

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

EasyPlayer.js网页H5 Web js播放器能力合集

最近遇到一个需求,要求做一款播放器,发现能力上跟EasyPlayer.js基本一致,满足要求: 需求 功性能 分类 需求描述 功能 预览 分屏模式 单分屏(单屏/全屏) 多分屏(2*2) 多分屏(3*3) 多分屏(4*4) 播放控制 播放(单个或全部) 暂停(暂停时展示最后一帧画面) 停止(单个或全部) 声音控制(开关/音量调节) 主辅码流切换 辅助功能 屏

9.8javaweb项目总结

1.主界面用户信息显示 登录成功后,将用户信息存储在记录在 localStorage中,然后进入界面之前通过js来渲染主界面 存储用户信息 将用户信息渲染在主界面上,并且头像设置跳转,到个人资料界面 这里数据库中还没有设置相关信息 2.模糊查找 检测输入框是否有变更,有的话调用方法,进行查找 发送检测请求,然后接收的时候设置最多显示四个类似的搜索结果

Solr 使用Facet分组过程中与分词的矛盾解决办法

对于一般查询而言  ,  分词和存储都是必要的  .  比如  CPU  类型  ”Intel  酷睿  2  双核  P7570”,  拆分成  ”Intel”,”  酷睿  ”,”P7570”  这样一些关键字并分别索引  ,  可能提供更好的搜索体验  .  但是如果将  CPU  作为 Facet  字段  ,  最好不进行分词  .  这样就造成了矛盾  ,  解决方法

JavaWeb【day09】--(Mybatis)

1. Mybatis基础操作 学习完mybatis入门后,我们继续学习mybatis基础操作。 1.1 需求 需求说明: 根据资料中提供的《tlias智能学习辅助系统》页面原型及需求,完成员工管理的需求开发。 通过分析以上的页面原型和需求,我们确定了功能列表: 查询 根据主键ID查询 条件查询 新增 更新 删除 根据主键ID删除 根据主键ID批量删除

MyBatis 切换不同的类型数据库方案

下属案例例当前结合SpringBoot 配置进行讲解。 背景: 实现一个工程里面在部署阶段支持切换不同类型数据库支持。 方案一 数据源配置 关键代码(是什么数据库,该怎么配就怎么配) spring:datasource:name: test# 使用druid数据源type: com.alibaba.druid.pool.DruidDataSource# @需要修改 数据库连接及驱动u