Как нарезать аудио-блоб в определенное время? - PullRequest
0 голосов
/ 05 мая 2018

У меня есть аудио-блоб, и я хочу его нарезать в определенное время. Как мне это сделать в Javascript?

Пример:

sliceAudioBlob( audio_blob, 0, 10000 ); // Time in milliseconds [ start = 0, end = 10000 ]

Примечание: Я понятия не имею, как это сделать, поэтому небольшой намек будет действительно оценены.

Обновление:

Я пытаюсь создать простой аудио-рекордер, но проблема в том, что существуют различия во времени для каждого браузера, некоторые из них добавляют несколько секунд (Firefox), а другие нет (Chrome). Поэтому мне пришла в голову идея кодировать метод, который возвращает только нужный мне фрагмент.

Полный 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>

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Не существует прямого способа нарезать аудио носитель подобным образом, и это потому, что ваш файл состоит не только из звукового сигнала: в нем есть несколько сегментов, с некоторыми заголовками и т. Д., Положение которых не может быть определено просто по длине. Это похоже на то, что вы не можете обрезать изображение в формате 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>
0 голосов
/ 10 мая 2018

В вашей строке:

    <button type="button" onclick="mediaRecorder.start(1000)">Start</button>

mediaRecorder.start получить в качестве параметра временной интервал. Временной интервал указывает размер фрагментов в миллисекундах. Поэтому, чтобы вырезать аудио, вы должны изменить массив чанков, который вы создали на mediaRecorder.ondataavailable

например: Вы передаете 1000 в качестве временного интервала, это означает, что у вас есть срезы в 1 секунду, и вы хотите вырезать первые 2 секунды записи.

Вы просто должны сделать что-то вроде этого:

 mediaRecorder.onstop = function() {
            //Remove first 2 seconds of the audio
            var chunksSliced = chunks.slice(2);

            var audio = document.createElement('audio'),
                // create the audio from the sliced chunk
                audio_blob = new Blob(chunksSliced, {
                    'type' : 'audio/mpeg'
                });
            audio.controls = 'controls';
            audio.autoplay = 'autoplay';
            audio.src = window.URL.createObjectURL( audio_blob );
            document.body.appendChild(audio);
        };

    }

При необходимости вы можете уменьшить размер фрагментов в миллисекундах. Просто введите другой номер в start и нарежьте массив там, где вы хотите.

Чтобы получить более конкретный ответ, вы можете сделать это для audioSlice:

            const TIMESLICE = 1000;
        // @param chunks Array with the audio chunks
        // @param start where to start cutting in seconds
        // @param end where to stop cutting in seconds
        function audioSlice(chunks, start, end) {
            const timeSliceToSeconds = TIMESLICE/1000;

            const startIndex = Math.round(start / timeSliceToSeconds);
            const endIndex = Math.round(end / timeSliceToSeconds);
            if (startIndex < chunks.length && endIndex < chunks.length) {
                return chunks.slice(startIndex, endIndex)
            }
            throw Error('You cannot cut this at those points');
        }

Если вы измените TIMESLICE для своего значения, он подсчитает, в каком месте выполнять обрезку при пропуске в секундах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...