Javascript 如何在Chrome中为MediaRecorder录制的音频添加预定义长度?
我正在用内置的MediaRecorder替换RecordRTC,以便在Chrome中录制音频。录制的音频随后通过音频api在节目中播放。我无法使audio.duration属性正常工作。上面说 如果视频(音频)流式传输且没有预定义的长度,则返回“Inf”(无限) 对于RecordRTC,我必须使用ffmpeg_asm.js将音频从wav转换为ogg。我猜是RecordRTC设置预定义音频长度的过程中的某个地方。有没有办法使用MediaRecorder设置预定义的长度?这是一个问题 FF会显示录制媒体的持续时间,如果您将录制媒体的Javascript 如何在Chrome中为MediaRecorder录制的音频添加预定义长度?,javascript,google-chrome,html5-audio,mediarecorder,recordrtc,Javascript,Google Chrome,Html5 Audio,Mediarecorder,Recordrtc,我正在用内置的MediaRecorder替换RecordRTC,以便在Chrome中录制音频。录制的音频随后通过音频api在节目中播放。我无法使audio.duration属性正常工作。上面说 如果视频(音频)流式传输且没有预定义的长度,则返回“Inf”(无限) 对于RecordRTC,我必须使用ffmpeg_asm.js将音频从wav转换为ogg。我猜是RecordRTC设置预定义音频长度的过程中的某个地方。有没有办法使用MediaRecorder设置预定义的长度?这是一个问题 FF会显示录制
currentTime
设置为大于其实际持续时间
,则该属性在chrome中可用
var记录器,
chunks=[],
ctx=新的AudioContext(),
aud=document.getElementById('aud');
函数exportAudio(){
var blob=新blob(块);
aud.src=URL.createObjectURL(新Blob(块));
aud.onloadedmetadata=函数(){
//这里应该已经有了
log.textContent='duration:'+aud.duration;
//处理chrome的错误
if(aud.duration==无穷大){
//将其设置为大于实际持续时间
aud.currentTime=1e101;
aud.ontimeupdate=函数(){
this.ontimeupdate=()=>{
返回;
}
log.textContent+='解决方法后:'+aud.duration;
aud.currentTime=0;
}
}
}
}
函数getData(){
var request=new XMLHttpRequest();
request.open('GET','https://upload.wikimedia.org/wikipedia/commons/4/4b/011229beowulf_grendel.ogg",对),;
request.responseType='arraybuffer';
request.onload=解码音频;
request.send();
}
功能解码音频(evt){
var audioData=此响应;
ctx.解码音频数据(音频数据,startRecording);
}
功能启动记录(缓冲区){
var source=ctx.createBufferSource();
source.buffer=缓冲区;
var dest=ctx.createMediaStreamDestination();
source.connect(dest);
记录器=新的MediaRecorder(目标流);
recorder.ondataavailable=saveChunks;
recorder.onstop=导出音频;
source.start(0);
recorder.start();
log.innerHTML='正在录制…'
//记录只有5秒
setTimeout(函数(){
录音机。停止();
}, 5000);
}
函数存储块(evt){
如果(evt.data.size>0){
推送(evt.data);
}
}
//我们需要用户激活
document.getElementById('button').onclick=function(evt){
getData();
这个。删除();
}
开始
感谢@kaido识别错误并提供有效修复
我准备了一个名为npm的包,您可以安装它来获得一个很好的承诺包装函数来完成这些脏活
用法如下:
// Returns Promise<Number>
getBlobDuration(blob).then(function(duration) {
console.log(duration + ' seconds');
});
Chrome中的一个bug于2016年检测到,但今天(2019年3月)仍然存在,这是导致这种行为的根本原因。在某些场景下,
audioElement.duration
将返回无限
Chrome Bug信息和
下面的代码提供了一种解决方法,可以避免该错误。
用法:创建您的音频元素
,并一次性调用此函数,提供您的音频元素
的参考。当返回的promise
解析时,audioElement.duration
属性应包含正确的值。(它还解决了videoElements
的相同问题)
感谢@colxi提供了实际的解决方案,我添加了一些验证步骤(因为该解决方案工作正常,但长音频文件存在问题)
我花了4个小时才让它处理长音频文件,结果证明验证就是解决办法
功能无限(媒体){
返回新承诺((解决、拒绝)=>{
//等待媒体加载元数据
media.onloadedmetadata=()=>{
//更改当前时间以更新ontimeupdate
media.currentTime=Number.MAX\u SAFE\u整数;
//检查其是否为无限NaN或未定义
if(ifNull(媒体)){
media.ontimeupdate=()=>{
//如果不为空,则解析承诺并发送持续时间
如果(!ifNull(媒体)){
//如果不为空,则解析承诺并发送持续时间
解决(媒体持续时间);
}
//检查其是否为无限NaN或未定义//如果第一次更新失败,则第二次实时更新是回退
media.ontimeupdate=()=>{
如果(!ifNull(媒体)){
解决(媒体持续时间);
}
};
};
}否则{
//如果媒体持续时间从不为无穷大,则返回它
解决(媒体持续时间);
}
};
});
}
//检查是否为空
函数ifNull(媒体){
if(media.duration==无穷大| | media.duration==NaN | | media.duration==未定义){
返回true;
}否则{
返回false;
}
}
//用法示例
//在html上获取音频播放器
const AudioPlayer=document.getElementById('audio');
const getInfinity=async()=>{
//等待承诺
等待fixInfinity(音频播放器)。然后(val=>{
//重置音频当前时间
AudioPlayer.currentTime=0;
//日志持续时间
console.log(val)
})
}
预定义长度是什么意思?你能在录音开始时设置一个计时器,然后在适当的时间停止吗?@Tom Chen,当我检查我录制的音频文件时
// yada yada async
const duration = await getBlobDuration(blob)
console.log(duration + ' seconds')
/**
* calculateMediaDuration()
* Force media element duration calculation.
* Returns a promise, that resolves when duration is calculated
**/
function calculateMediaDuration(media){
return new Promise( (resolve,reject)=>{
media.onloadedmetadata = function(){
// set the mediaElement.currentTime to a high value beyond its real duration
media.currentTime = Number.MAX_SAFE_INTEGER;
// listen to time position change
media.ontimeupdate = function(){
media.ontimeupdate = function(){};
// setting player currentTime back to 0 can be buggy too, set it first to .1 sec
media.currentTime = 0.1;
media.currentTime = 0;
// media.duration should now have its correct value, return it...
resolve(media.duration);
}
}
});
}
// USAGE EXAMPLE :
calculateMediaDuration( yourAudioElement ).then( ()=>{
console.log( yourAudioElement.duration )
});