Skip to content

Commit

Permalink
恢复audioTrackSet默认设置,降噪和回声消除由浏览器提供默认值,试图减少新版本iOS上录音小和不能录音的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
xiangyuecn committed Jun 10, 2023
1 parent c6f9533 commit b2ba029
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 96 deletions.
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,9 @@ App端建议使用原生插件来录音,没有这些框架缺陷带来的性
浏览器Audio Media[兼容性](https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats#Browser_compatibility)mp3最好,wav还行,其他要么不支持播放,要么不支持编码;因此本库最佳推荐使用mp3、wav格式,代码也是优先照顾这两种格式。


**留意中途来电话**:在移动端录音时,如果录音中途来电话,或者通话过程中打开录音,是不一定能进行录音的;经过简单测试发现,IOS上Safari将暂停返回音频数据,直到通话结束才开始继续有音频数据返回;小米上Chrome不管是来电还是通话中开始录音都能对麦克风输入的声音进行录音;只是简单测试,更多机器和浏览器并未做测试,不过整体上来看来电话或通话中进行录音的可行性并不理想,也不赞成在这种过程中进行录音;但只要通话结束后录音还是会正常进行,影响基本不大。
**留意中途来电话**:在移动端录音时,如果录音中途来电话,或者通话过程中打开录音,是不一定能进行录音的;经过简单测试发现,iOS上Safari将暂停返回音频数据,直到通话结束才开始继续有音频数据返回;小米上Chrome不管是来电还是通话中开始录音都能对麦克风输入的声音进行录音;只是简单测试,更多机器和浏览器并未做测试,不过整体上来看来电话或通话中进行录音的可行性并不理想,也不赞成在这种过程中进行录音;但只要通话结束后录音还是会正常进行,影响基本不大。

**录音时对播放音频的影响**:仅在移动端,如果录音参数中启用了降噪+回声消除,打开录音后,如果同时播放音频,此时播放声音可能会变得很小;PC上 和 禁用降噪+回声消除后 似乎无此影响。
**录音时对播放音频的影响**:仅在移动端,如果录音配置中未禁用降噪+回声消除(浏览器默认开启降噪+回声),打开录音后,如果同时播放音频,此时系统播放音量可能会变得很小;PC上 和 禁用降噪+回声消除后 似乎无此影响,但iOS上如果禁用又可能会导致无法正常录音,详细请阅读配置文档中的`audioTrackSet`参数说明

**移动端锁屏录音**:手机锁屏后浏览器的运行状态是一个玄学,是否能录音不可控;不同手机、甚至同一手机在不同状态下,有可能能录又有可能不能录,且无法检测;可以调用 `navigator.wakeLock` 来阻止手机自动锁屏,不支持的直接简单粗暴的 循环+静音 播放一段视频,来阻止锁屏,就是有点费电,具体实现可参考H5在线测试页面内的`wakeLockClick`方法。

Expand Down Expand Up @@ -527,9 +527,14 @@ set={
//比如:audio、video标签dom节点的captureStream方法(实验特性,不同浏览器支持程度不高)返回的流;WebRTC中的remote流;自己创建的流等
//注意:流内必须至少存在一条音轨(Audio Track),比如audio标签必须等待到可以开始播放后才会有音轨,否则open会失败

//,audioTrackSet:{ deviceId:"",groupId:"", autoGainControl:true, echoCancellation:true, noiseSuppression:true }
//普通麦克风录音时getUserMedia方法的audio配置参数;注意:提供的任何配置值都不一定会生效
//回声消除、降噪开关这两个已默认明确关闭,开启可能会导致移动端表现的很怪异,包括系统播放声音变小,如需开启请测试好后再开启
/*,audioTrackSet:{
deviceId:"",groupId:"" //指定设备的麦克风,通过navigator.mediaDevices.enumerateDevices拉取设备列表,其中kind为audioinput的是麦克风
,noiseSuppression:true //降噪(ANS)开关,不设置时由浏览器控制(一般为默认打开),设为true明确打开,设为false明确关闭
,echoCancellation:true //回声消除(AEC)开关,取值和降噪开关一样
,autoGainControl:true //自动增益(AGC)开关,取值和降噪开关一样
}*/
//普通麦克风录音时getUserMedia方法的audio配置参数;注意:不同浏览器的支持程度不同,提供的任何配置值都不一定会生效
//回声消除、降噪开关这两个参数浏览器一般默认为打开, 注意:移动端打开降噪、回声消除可能会表现的很怪异(包括系统播放音量变小),但iOS上如果关闭又可能导致录音没有声音,如需更改配置请Android和iOS分别配置,并测试好,PC端没有这些问题
//由于麦克风是全局共享的,所以新配置后需要close掉以前的再重新open
//更多参考: https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints

Expand Down
2 changes: 1 addition & 1 deletion assets/demo-ts/dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion assets/demo-vue/dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion assets/demo-vue/dist/recordapp.js

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions assets/npm-home/hash-history.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
[
{
"sha1": "4fa1d9dd106f8d959a505168088d935f98fc620d",
"time": "2023/6/10 22:27:40"
},
{
"sha1": "ef550552c34f40aebd27d186d8608540be998a02",
"time": "2023/2/1 23:06:25"
Expand All @@ -14,9 +18,5 @@
{
"sha1": "40d86b5656875a4f856d652bc3d4839464d8fe2d",
"time": "2022-6-28 09:44:33"
},
{
"sha1": "88b22aab0ee72cd0a07d594cb0e035067f28cb69",
"time": "2022-5-7 23:49:36"
}
]
79 changes: 58 additions & 21 deletions assets/ztext_collab-project_videojs-record.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,47 +11,54 @@
<body>

<audio id="myAudio" class="video-js vjs-default-skin"></audio>
<div class="tipsShow" style="display:none;padding-top:20px">
<button onclick="playerOpen()">打开录音,请求权限</button>
<button onclick="playerClose()">关闭录音,释放资源</button>
<span style="margin-left:20px"></span>
<button onclick="playerStart()">开始录音</button>
<button onclick="playerStop()">结束录音</button>
</div>

<div style="padding:20px 0 200px">
<div class="reclog"></div>

<div>国外的玩意,除了好看就是容易误操作,上面如果是空白,代表:加载很慢↑↑↑↑ (也有可能是他们更新了页面,但这个测试html还未及时同步更新)</div>
<div>显示出录音界面后,点击大麦克风按钮打开录音,再点击左下角圆点按钮开始录音,再点按钮结束录音,录完后点左下角的播放箭头播放</div>
<div class="tipsHide" style="font-size:32px;color:#fa0">加载中... 上面如果是空白,代表:加载很慢↑↑↑↑ (也有可能是他们更新了页面,但这个测试html还未及时同步更新)</div>
<div class="tipsShow" style="display:none">先点击打开录音,再点击开始录音(按钮操作方便些,播放器界面除了好看就是容易误操作)</div>

<div style="padding-top:20px">
这个录出来的音频格式完全不可控,可能是webm、wav;但可以注入代码强制修改,录音时日志里面显示的“Using recorderType: xxx”决定了录音类型,替换GetRecorderType函数即可:
这个录出来的音频格式完全不可控,可能是webm、wav;但可以注入代码强制修改,录音时日志里面显示的“Initialized recorderType: xxx”决定了录音类型,替换GetRecorderType函数即可:
<div style="padding-top:10px">wav:<button onclick="setRecType(1)">改为StereoAudioRecorder录制wav,底层使用ScriptProcessor</button></div>
<div style="padding-top:10px">webm:<button onclick="setRecType(2)">改为MediaStreamRecorder录制webm,底层使用MediaRecorder</button></div>
<div style="padding-top:10px">未知:<button onclick="setRecType(0)">还原GetRecorderType,录音格式不可控</button></div>
</div>
<script>
var setRecType=function(type){
if(!window.GetRecorderType){
if(!window.GetRecorderType__org){
reclog("还没有加载完成,请稍后设置",1);
return;
}
if(!window.GetRecorderType__){
window.GetRecorderType__=GetRecorderType;
}
if(type==1){
GetRecorderType=function(){
recorderType="ScriptProcessor-StereoAudioRecorder";
return StereoAudioRecorder
}
reclog("将使用ScriptProcessor录制wav格式");
reclog("强制使用ScriptProcessor录制wav格式","#0cb");
}else if(type==2){
GetRecorderType=function(){
recorderType="MediaRecorder-MediaStreamRecorder";
return MediaStreamRecorder
}
reclog("将使用MediaRecorder录制webm格式");
reclog("强制使用MediaRecorder录制webm格式","#0cb");
}else{
GetRecorderType=window.GetRecorderType__;
reclog("已还原GetRecorderType,录制格式不确定");
reclog("已还原GetRecorderType,录制格式不确定","#0cb");
}
};
var recorderType="";
var initRecorderType=function(){
$(".tipsHide").hide();
$(".tipsShow").show();
if(window.GetRecorderType__org)return;
window.GetRecorderType__org=GetRecorderType;
window.GetRecorderType__=GetRecorderType=function(){
var val=GetRecorderType__org.apply(null, arguments);
Expand All @@ -63,16 +70,32 @@
recorderType="MediaRecorder-MediaStreamRecorder";
}
return val;
}
};
setRecType(1);
};
</script>

<div style="padding:20px 0">原始测试地址:<a href="https://collab-project.github.io/videojs-record/demo/audio-only.html">https://collab-project.github.io/videojs-record/demo/audio-only.html</a></div>
var playerOpen=function(){
player.record().getDevice();
};
var playerClose=function(){
player.record().stopDevice();
reclog("已关闭录音");
};
var playerStart=function(){
player.record().start();
};
var playerStop=function(){
player.record().stop();
};
</script>

<hr>

<div>
【测试方法】:使用上面的录音功能进行测试看看能否正常录音。
<div style="font-size:32px;color:#0a0">
【测试方法】:使用上面的录音功能进行测试看看能否正常录音,播放听听录音内容是否正常。可以多关闭打开几次录音进行测试,在不同设备上进行测试(iOS重灾区)。
<div style="color:#fa0">如果ScriptProcessor模式下的录音有问题,请点击“改为MediaStreamRecorder录制webm,底层使用MediaRecorder”按钮,重新录音测试。</div>
</div>

<br><br>
【附带测试】:
Expand All @@ -92,6 +115,15 @@
Audio对录音的影响测试(<a href="https://github.com/xiangyuecn/Recorder/issues/34">issues#34</a>);IOS Safari如果未开始过录音并且播放了音乐,然后后续录音将会有问题;再现方法(<a href="ztest_apple_developer_forums_getusermedia.html">test apple developer forums</a>):刷新页面后首先先播放音乐,然后开始测试录音,会发现波形显示掉帧或者保持直线。另测试浏览器对音频的支持情况。
</div>


<hr>

<div style="padding:20px 0">
<div>原始测试地址:<a href="https://collab-project.github.io/videojs-record/demo/audio-only.html" target="_blank">https://collab-project.github.io/videojs-record/demo/audio-only.html</a></div>
<div>GitHub:<a href="https://github.com/collab-project/videojs-record" target="_blank">https://github.com/collab-project/videojs-record</a></div>
</div>


<script>
function reclog(s,color){
var now=new Date();
Expand Down Expand Up @@ -208,8 +240,8 @@
var options = {
controls: true,
bigPlayButton: false,
width: 600,
height: 300,
width: 320,
height: 180,
plugins: {
wavesurfer: {
backend: 'WebAudio',
Expand All @@ -235,7 +267,7 @@
record: {
audio: true,
video: false,
maxLength: 20,
maxLength: 10*60*60,
displayMilliseconds: true,
debug: true
}
Expand All @@ -254,17 +286,24 @@
', wavesurfer.js ' + WaveSurfer.VERSION + ' and recordrtc ' +
RecordRTC.version;
videojs.log(msg);
initRecorderType();
});

// error handling
player.on('deviceError', function() {
console.log('device error:', player.deviceErrorCode);
reclog("deviceError: "+player.deviceErrorCode,1);
});

player.on('error', function(element, error) {
console.error(error);
reclog("error: "+(error&&error.message||error),1);
});

player.on('deviceReady', function() {
console.log('deviceReady');
reclog("deviceReady 已打开录音",2);
});
// user clicked the record button and started recording
player.on('startRecord', function() {
console.log('started recording!');
Expand All @@ -280,14 +319,12 @@
var blob=player.recordedData;
var name=blob.name
if(/webm$/i.test(name)){
reclog("已通过MediaRecorder录制了一个webm文件 "+blob.size+"字节",2);
reclog("已通过MediaRecorder录制了一个webm文件 "+blob.size+"字节,点播放器左下角的播放箭头播放",2);
}
if(/wav$/i.test(name)){
reclog("已通过ScriptProcessor录制了一个wav文件 "+blob.size+"字节",2);
reclog("已通过ScriptProcessor录制了一个wav文件 "+blob.size+"字节,点播放器左下角的播放箭头播放",2);
}
});

initRecorderType();
</script>

</body>
Expand Down
2 changes: 1 addition & 1 deletion dist/recorder-core.js

Large diffs are not rendered by default.

51 changes: 20 additions & 31 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@

<script>
//兼容环境
var PageLM="2023-02-01 21:37";
var PageLM="2023-06-10 21:23";

function RandomKey(){
return "randomkey"+(RandomKey.idx++);
Expand Down Expand Up @@ -336,18 +336,20 @@
<div>
<span class="lb">noiseSuppression :</span>
<select class="trackSet_noise">
<option value="">不设置</option>
<option value="1">true</option>
<option value="2" selected>false</option>
<option value="2">false</option>
</select>
降噪配置开关(默认禁用)
降噪(ANS)配置开关
</div>
<div>
<span class="lb">echoCancellation :</span>
<select class="trackSet_aec">
<option value="">不设置</option>
<option value="1">true</option>
<option value="2" selected>false</option>
<option value="2">false</option>
</select>
回声消除配置开关(默认禁用)
回声消除(AEC)配置开关
</div>
<div>
<span class="lb">autoGainControl :</span>
Expand All @@ -356,11 +358,11 @@
<option value="1">true</option>
<option value="2">false</option>
</select>
自动增益配置开关
自动增益(AGC)配置开关
</div>
<div>
<span style="color:#f60">以上参数设置后需重新打开录音</span>;均为set中的audioTrackSet高级配置,会直接传递给浏览器的getUserMedia方法,不同浏览器的支持程度不同,并不一定会生效;
<span style="color:#aaa">移动端打开降噪、回声消除可能会表现的很怪异(包括系统播放声音变小),所以默认禁用,使用原声录制(高音甜、中音准、低音沉,总之一句话就是通透),如需降噪、回声消除请测试好后再开启</span>
<span style="color:#f60">以上参数设置后需重新打开录音</span>;均为set中的audioTrackSet高级配置,会直接传递给浏览器的getUserMedia方法,不同浏览器的支持程度不同,并不一定会生效,这些参数浏览器一般默认为打开
<span style="color:#aaa">移动端打开降噪、回声消除可能会表现的很怪异(包括系统播放音量变小),但iOS上如果关闭又可能导致录音没有声音,如需更改配置请Android和iOS分别配置,并测试好</span>
</div>
</div>

Expand Down Expand Up @@ -437,15 +439,6 @@
</label>
<div><a href="https://github.com/xiangyuecn/Recorder/issues/51">issues#51</a>如果没有进行补偿,录音时设备偶尔出现很卡的情况下(CPU被其他程序大量占用),浏览器采集到的音频是断断续续的,导致10秒的录音可能就只返回了5秒的数据量,这个时候最终编码得到的音频时长明显变短,播放时的效果就像快放一样。未禁用时会在卡顿时自动补偿静默音频,消除了快放效果,但由于丢失的音频已被静默数据代替,听起来就是数据本身的断断续续的效果。在设备不卡时录音没有此问题。</div>

<div style="margin-top:12px;">
<span class="lb">临时调试选项 :</span>
<div><label>
<input type="checkbox" class="debugSet_D220626">
Recorder._D220626=true:ScriptProcessor立即退出回调,试图减少对浏览器录音的影响,有可能减少杂音,效果有待测试
</label></div>
<div><span style="color:#f60">以上参数设置后需重新打开录音</span>;这些参数仅供调试用,未来会被删除。</div>
</div>

<div style="margin-top:12px;">
<span class="lb">Destroy :</span>
<button onclick="callDestroy()">调用Recorder.Destroy()</button>
Expand Down Expand Up @@ -557,7 +550,7 @@
</pre>

<span class="lb">问题自检 :</span> 录音时注意观察灰色区域是否有绿色音量跳动,没有绿色跳动说明Recorder没有获取到声音数据。如果测试发现mp3没有声音,可以试一下wav格式,如果wav格式有声音,说明内置lamejs mp3编码器有问题。如果都没有,下载下来播放看看有没有。下载下来也没有声音可以反馈一下。
<div style="padding-top:20px">
<div style="padding-top:20px;font-size:26px;color:#fa0">
如果浏览器不能正常录音,并且不确定是不是这个库的问题,可以到 <a href="https://xiangyuecn.gitee.io/recorder/assets/ztext_collab-project_videojs-record.html">assets/ztext_collab-project_videojs-record.html</a> 试一下。
</div>
</div>
Expand Down Expand Up @@ -614,18 +607,12 @@
reclog("已启用AudioWorklet"+(enableWebM?"(同时启用了MediaRecorder,AudioWorklet只会在MediaRecorder未生效时采用)":"")+","+workletTips,"#f60");
}

var debugSet_D220626=$(".debugSet_D220626")[0].checked;
Recorder._D220626=debugSet_D220626;
if(debugSet_D220626){
reclog("已启用临时调试选项:Recorder._D220626=true","#f60");
};

var audioTrackSet=null;
var trackSet_device=$(".trackSet_device").val();
var trackSet_noise=$(".trackSet_noise").val();
var trackSet_aec=$(".trackSet_aec").val();
var trackSet_gain=$(".trackSet_gain").val();
if(trackSet_device || trackSet_noise==1 || trackSet_aec==1 || trackSet_gain){
if(trackSet_device || trackSet_noise || trackSet_aec || trackSet_gain){
audioTrackSet={};
if(trackSet_device){
var device=DeviceList[+trackSet_device];
Expand Down Expand Up @@ -764,20 +751,22 @@
var DeviceList=[];
var trackSetQueryDeviceList=function(click){
var end=function(list,err){
DeviceList=list;
if(click){
console.log("DeviceList: ", JSON.parse(JSON.stringify(DeviceList)));
}

DeviceList=list; var list2=[];
var opts=['<option value="">'+(list.length?'不设置':err)+'</option>'];
for(var i=0;i<list.length;i++){
var o=list[i];
if(o.deviceId && o.kind=="audioinput"){
list2.push(o);
var name=o.label||((i+1)+"# 无名称,可能是因为从来没有打开过录音");
opts.push('<option value="'+i+'">'+name+'</option>');
}
}
$(".trackSet_device").html(opts.join(" "))
$(".trackSet_device").html(opts.join(" "));

if(click){
console.log("DeviceList: ", JSON.parse(JSON.stringify(list)));
reclog("已重新拉取到"+list2.length+"个设备,可切换要使用的麦克风",2);
}
};
if(navigator.mediaDevices && navigator.mediaDevices.enumerateDevices){
navigator.mediaDevices.enumerateDevices().then(end)["catch"](function(e){
Expand Down
2 changes: 1 addition & 1 deletion recorder.mp3.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion recorder.wav.min.js

Large diffs are not rendered by default.

Loading

0 comments on commit b2ba029

Please sign in to comment.