Как передать вывод Howler.masterGain в mediaRecorder - PullRequest
2 голосов
/ 11 февраля 2020

Я пытаюсь записать составной выход Web-Audio-API от Howler (набор звуков и звуковых спрайтов, программно объединенных).

До сих пор я пытался подключить контекст Howler.masterGain к createMediaStreamDestination Узел, но событие MediaRecorder.ondataavailable запускается только один раз и без данных.

Вот пример с подключенной версией здесь: https://jsfiddle.net/chadananda/kvzrsx5t/86/

const audioURL = 'https://cdn.glitch.com/02dcea11-9bd2-4462-ac38-eeb6a5ad9530%2F331_full_beautiful-minds_0171_preview.mp3?1522829295082'

// connect MediaStreamDestination to Howler.masterGain
Howler.mute(false) // to initialize Howler internals  
let mediaDest = Howler.ctx.createMediaStreamDestination()
// first disconnect
Howler.masterGain.disconnect() 
// then reconnect to our new destination?
Howler.masterGain.connect(mediaDest)  


// set up media recorder to record output
let audioChunks = []
let mediaRecorder = new MediaRecorder(mediaDest.stream, {mimeType: 'audio/webm'})
mediaRecorder.onstart = (event) => { console.log('Started recording Howl output...') }
mediaRecorder.ondataavailable = (e) => { if (e.data.size) audioChunks.push(e.data) }
mediaRecorder.onstop = (event) => {
  console.log('Completed Recording', audioChunks) // why is this returning empty?
    // let buffer = new Blob(chunks)  
    // let audioPlayer = document.createElement("AUDIO")
    // audioPlayer.src = window.URL.createObjectURL(buffer)
    // audioPlayer.play()
}

// example of recording one sound looping for 3 seconds
let sound = new Howl({ html5: false, src: audioURL })
// start sound and recording
sound.play(); mediaRecorder.start()  
// stop in a few seconds 
setTimeout( ()=>{ mediaRecorder.stop(); sound.stop() }, 5000)

Ответы [ 2 ]

0 голосов
/ 19 февраля 2020

Проблема в том, что Howler.masterGain меняется после создания экземпляра Howl:

const audioURL = 'https://cdn.glitch.com/02dcea11-9bd2-4462-ac38-eeb6a5ad9530%2F331_full_beautiful-minds_0171_preview.mp3?1522829295082';
const masterGain = Howler.masterGain;
const sound = new Howl({ html5: false, src: audioURL });
sound.play();

console.log( masterGain === Howler.masterGain ); // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.1.3/howler.min.js"></script>

Таким образом, тот, который вы подключаете к узлу MediaStreamDestination, не тот, куда будут передаваться аудиоданные, и, следовательно, он записывает только тишину.

Я действительно не знаю эту библиотеку, поэтому я не могу сказать, почему она так себя ведет или есть ли способ заставить ее вести себя по-другому, но простой обходной путь - инициализировать ваш поток и создать ваш рекордер только после Вы инициализировали свой экземпляр Howl:

onclick = e => { onclick = null; msg.remove();

const audioURL = 'https://cdn.glitch.com/02dcea11-9bd2-4462-ac38-eeb6a5ad9530%2F331_full_beautiful-minds_0171_preview.mp3?1522829295082'

Howler.mute(false) // to initialize Howler internals  

// first initiate your Howl instance
const sound = new Howl( { html5: false, src: audioURL } );
sound.play();
// now intitiate your MediaStreamDestination

const mediaDest = Howler.ctx.createMediaStreamDestination();
Howler.masterGain.connect( mediaDest );

// set up media recorder to record output
const audioChunks = []
const mediaRecorder = new MediaRecorder( mediaDest.stream, { mimeType: 'audio/webm' } );

mediaRecorder.onstart = (event) =>
  { console.log('Started recording Howl output...') };
mediaRecorder.ondataavailable = (event) =>
  { audioChunks.push( event.data ) };
mediaRecorder.onstop = (event) =>
  { console.log('Completed Recording', new Blob( audioChunks ) ) };

mediaRecorder.start();

setTimeout( ()=>{ mediaRecorder.stop(); sound.stop() }, 5000);

};

click anywhere to start
0 голосов
/ 15 февраля 2020

Кажется, что запись заблокирована политикой автовоспроизведения, которая запрещает воспроизведение чего-либо без участия пользователя. Если вы запускаете запись из обработчика щелчков, она работает. Я создал обновленную версию вашей скрипки, которая делает это.

https://jsfiddle.net/786zkLcu/

Я изменил только последние строки. Код теперь генерирует динамическую кнопку c и присоединяет обработчик щелчков. Это также означает, что пользователь должен нажать кнопку, чтобы начать запись.

const $button = document.createElement('button');

$button.innerHTML = 'click';
$button.onclick = () => {
    sound.play();
    mediaRecorder.start();

    setTimeout(() => {
        mediaRecorder.stop();
        sound.stop();
    }, 5000);
};

document.body.append($button);
...