我有一个音频Blob,我想在特定时间将其切碎。如何在Javascript中进行呢?
示例:
sliceAudioBlob( audio_blob, 0, 10000 ); // Time in milliseconds [ start = 0, end = 10000 ]
更新:
我正在尝试构建一个简单的音频记录器,但是问题是每种浏览器的持续时间有所不同,其中一些会增加几秒钟(Firefox),而其他不会增加几秒钟(Chrome)。因此,我想到了编写仅返回我想要的 slice 的方法的想法。
完整的HTML代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Audio Recorder</title>
<style>
audio{
display: block;
}
</style>
</head>
<body>
<button type="button" onclick="mediaRecorder.start(1000)">Start</button>
<button type="button" onclick="mediaRecorder.stop()">Stop</button>
<script type="text/javascript">
var mediaRecorder = null,
chunks = [],
max_duration = 10000;// in milliseconds.
function onSuccess( stream ) {
mediaRecorder = new MediaRecorder( stream );
mediaRecorder.ondataavailable = function( event ) {
// chunks.length is the number of recorded seconds
// since every chunk is 1 second duration.
if ( chunks.length < max_duration / 1000 ) {
chunks.push( event.data );
} else {
if (mediaRecorder.state === 'recording') {
mediaRecorder.stop();
}
}
}
mediaRecorder.onstop = function() {
var audio = document.createElement('audio'),
audio_blob = new Blob(chunks, {
'type' : 'audio/mpeg'
});
audio.controls = 'controls';
audio.autoplay = 'autoplay';
audio.src = window.URL.createObjectURL( audio_blob );
document.body.appendChild(audio);
};
}
var onError = function(err) {
console.log('Error: ' + err);
}
navigator.mediaDevices.getUserMedia({ audio: true }).then(onSuccess, onError);
</script>
</body>
</html>
最佳答案
没有像这样分割音频媒体的简单方法,这是因为您的文件不仅仅包含声音信号:其中有多个片段,带有一些标题等,不能仅通过byteLength。就像您无法仅通过获取jpeg的x个首字节来裁剪jpeg图像一样。
可能有几种方法可以使用Web Audio API将您的媒体文件转换为AudioBuffer,然后将其转换为slicing this AudioBuffer's raw PCM data,然后再使用正确的新描述符将其打包回媒体文件中,但是我认为您正面临XY问题,如果我正确地获得它,有一种简单的方法可以解决此X问题。
确实,您描述的问题是Chrome或Firefox不会从您的代码中产生10s媒体。
但这是因为您依赖MediaRecorder.start(timeslice)的timelice参数为您提供了完美的时间。
不会的此参数仅应理解为您要提供给浏览器的线索,但它们可能会强加自己的最小时间片,因此不尊重您的参数。 (2.3[Methods].5.4)。
相反,您最好在需要时使用简单的setTimeout
触发记录器的stop()
方法:
start_btn.onclick = function() {
mediaRecorder.start(); // we don't even need timeslice
// now we'll get similar max duration in every browsers
setTimeout(stopRecording, max_duration);
};
stop_btn.onclick = stopRecording;
function stopRecording() {
if (mediaRecorder.state === "recording")
mediaRecorder.stop();
};
Here is a live example using gUM hosted on jsfiddle.
还有一个使用Web Audio API中的静默流的实时代码段,因为StackSnippet的保护在gUM上不能很好地运行...
var start_btn = document.getElementById('start'),
stop_btn = document.getElementById('stop');
var mediaRecorder = null,
chunks = [],
max_duration = 10000; // in milliseconds.
start_btn.onclick = function() {
mediaRecorder.start(); // we don't even need timeslice
// now we'll get similar max duration in every browsers
setTimeout(stopRecording, max_duration);
this.disabled = !(stop_btn.disabled = false);
};
stop_btn.onclick = stopRecording;
function stopRecording() {
if (mediaRecorder.state === "recording")
mediaRecorder.stop();
stop_btn.disabled = true;
};
function onSuccess(stream) {
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = function(event) {
// simply always push here, the stop will be controlled by setTimeout
chunks.push(event.data);
}
mediaRecorder.onstop = function() {
var audio_blob = new Blob(chunks);
var audio = new Audio(URL.createObjectURL(audio_blob));
audio.controls = 'controls';
document.body.appendChild(audio);
// workaround https://crbug.com/642012
audio.currentTime = 1e12;
audio.onseeked = function() {
audio.onseeked = null;
console.log(audio.duration);
audio.currentTime = 0;
audio.play();
}
};
start_btn.disabled = false;
}
var onError = function(err) {
console.log('Error: ' + err);
}
onSuccess(SilentStream());
function SilentStream() {
var ctx = new(window.AudioContext || window.webkitAudioContext),
gain = ctx.createGain(),
dest = ctx.createMediaStreamDestination();
gain.connect(dest);
return dest.stream;
}
<button id="start" disabled>start</button>
<button id="stop" disabled>stop</button>
关于javascript - 如何在特定时间切片音频Blob?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50191365/