Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在Chrome中为MediaRecorder录制的音频添加预定义长度?_Javascript_Google Chrome_Html5 Audio_Mediarecorder_Recordrtc - Fatal编程技术网

Javascript 如何在Chrome中为MediaRecorder录制的音频添加预定义长度?

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会显示录制

我正在用内置的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 ) 
});