Не существует прямого способа нарезать аудио носитель подобным образом, и это потому, что ваш файл состоит не только из звукового сигнала: в нем есть несколько сегментов, с некоторыми заголовками и т. Д., Положение которых не может быть определено просто по длине. Это похоже на то, что вы не можете обрезать изображение в формате jpeg, просто получив его x первых байтов.
Могут быть способы использования API-интерфейса Web Audio для преобразования медиафайла в AudioBuffer , а затем нарезки необработанных PCM-данных AudioBuffer , как вы хотите, прежде чем упаковать их обратно в файл мультимедиа с новыми правильными дескрипторами, но я думаю, что вы столкнулись с проблемой XY, и если я правильно понял, есть простой способ исправить эту проблему X.
Действительно, проблема, которую вы описываете, заключается в том, что Chrome или Firefox не создают носитель 10 с из вашего кода.
Но это потому, что вы полагаетесь на аргумент timeslice , равный MediaRecorder.start (timeslice) , чтобы получить куски идеального времени.
Не будет Этот аргумент следует понимать только как подсказку , которую вы даете браузеру, но они вполне могут навязать свой минимальный временной интервал и, следовательно, не уважать ваш аргумент. ( 2.3 [Методы] .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();
};
Вот живой пример использования gUM, размещенного на 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>