Tom*_*hen 13 javascript google-chrome html5-audio mediarecorder recordrtc
我正在使用内置的MediaRecorder替换RecordRTC,以便在Chrome中录制音频.然后在带有音频api的程序中播放录制的音频.我无法使audio.duration属性工作.它说
如果视频(音频)是流式传输且没有预定义长度,则返回"Inf"(无限).
使用RecordRTC,我不得不使用ffmpeg_asm.js将音频从wav转换为ogg.我的猜测是在RecordRTC设置预定义音频长度的过程中的某个地方.有没有办法使用MediaRecorder设置预定义的长度?
Kai*_*ido 27
这是一个铬虫.
FF确实暴露了录制媒体的持续时间,如果您currentTime将录制的媒体设置为超过其实际值duration,则该属性可用于Chrome ...
var recorder,
chunks = [],
ctx = new AudioContext(),
aud = document.getElementById('aud');
function exportAudio() {
var blob = new Blob(chunks, {
type: 'audio/ogg'
});
aud.src = URL.createObjectURL(new Blob(chunks));
aud.onloadedmetadata = function() {
// it should already be available here
log.textContent = ' duration: ' + aud.duration;
// handle chrome's bug
if (aud.duration === Infinity) {
// set it to bigger than the actual duration
aud.currentTime = 1e101;
aud.ontimeupdate = function() {
this.ontimeupdate = () => {
return;
}
log.textContent += ' after workaround: ' + aud.duration;
aud.currentTime = 0;
}
}
}
}
function getData() {
var request = new XMLHttpRequest();
request.open('GET', 'https://upload.wikimedia.org/wikipedia/commons/4/4b/011229beowulf_grendel.ogg', true);
request.responseType = 'arraybuffer';
request.onload = decodeAudio;
request.send();
}
function decodeAudio(evt) {
var audioData = this.response;
ctx.decodeAudioData(audioData, startRecording);
}
function startRecording(buffer) {
var source = ctx.createBufferSource();
source.buffer = buffer;
var dest = ctx.createMediaStreamDestination();
source.connect(dest);
recorder = new MediaRecorder(dest.stream);
recorder.ondataavailable = saveChunks;
recorder.onstop = exportAudio;
source.start(0);
recorder.start();
log.innerHTML = 'recording...'
// record only 5 seconds
setTimeout(function() {
recorder.stop();
}, 5000);
}
function saveChunks(evt) {
if (evt.data.size > 0) {
chunks.push(evt.data);
}
}
getData();Run Code Online (Sandbox Code Playgroud)
<audio id="aud" controls></audio><span id="log"></span>Run Code Online (Sandbox Code Playgroud)
因此,这里的建议是明确错误报告,以便铬的团队需要一些时间来解决它,即使这个解决方法可以做到这一点......
Chrome 中的一个错误于 2016 年检测到,但至今(2019 年 3 月)仍然存在,是此行为背后的根本原因。特定场景下audioElement.duration会返回Infinity。
以下代码提供了避免该错误的解决方法。
用法:创建您的audioElement,并一次调用此函数,提供您的audioElement. 当返回promise解析时,audioElement.duration属性应该包含正确的值。(它也解决了同样的问题videoElements)
/**
* 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 )
});
Run Code Online (Sandbox Code Playgroud)
感谢 @Kaiido 识别错误并提供工作修复。
我准备了一个名为get-blob-duration的 npm 包,你可以安装它以获得一个很好的 Promise 包装函数来完成这些脏活。
用法如下:
// Returns Promise<Number>
getBlobDuration(blob).then(function(duration) {
console.log(duration + ' seconds');
});
Run Code Online (Sandbox Code Playgroud)
或者 ECMAScript 6:
// yada yada async
const duration = await getBlobDuration(blob)
console.log(duration + ' seconds')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4616 次 |
| 最近记录: |