Estoy tratando de construir una plataforma de radio por Internet y he luchado mucho con el problema que se menciona en el título.
Para explicarme más, lo que estoy tratando de lograr es, 1) mientras grabo la entrada del micrófono de la emisora, mezclarlo con el audio de la reproducción de música y 2) al mismo tiempo poder bajar o subir el volumen de la reproducción de música (también en tiempo real a través de la interfaz de usuario) para que la voz del locutor se mezcle con la música.
¡Esto es para imitar el comportamiento habitual de un locutor de radio donde el volumen de la música baja cuando la persona quiere hablar y vuelve a subir cuando termina de hablar! La segunda característica definitivamente viene después de la primera, pero supongo que mencionarla ayuda a explicar ambas.
Para concluir, ya logré escribir un código que recibe y reproduce la entrada del micrófono (¡aunque no funciona perfectamente!). En este punto, necesito saber si hay código o bibliotecas que puedan ayudarme a hacer exactamente lo que estoy tratando de hacer. Todo esto se hace con la esperanza de no necesitar usar IceCast, etc.
A continuación se muestra mi código para obtener la entrada del micrófono:
// getting microphone input and sending it to our server var recordedChunks = []; var mediaRecorder = null; let slice = 100; // how frequently we capture sound const slices = 20; // 20 * => after 2 sec let sendfreq = slice * slices; // how frequently we send it /* get microphone button handle */ var microphoneButton = document.getElementById('console-toggle-microphone'); microphoneButton.setAttribute('on', 'no'); /* initialise mic streaming capability */ navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(stream => { _stream = stream; }) .catch(function(err) { show_error('Error: Microphone access has been denied probably!', err); }); function toggle_mic() { if (microphoneButton.getAttribute('on') == 'yes') { clearInterval(); microphoneButton.setAttribute('on', 'no'); microphoneButton.innerHTML = 'start mic'; } else if (microphoneButton.getAttribute('on') == 'no') { microphoneButton.setAttribute('on', 'yes'); microphoneButton.innerHTML = 'stop mic'; function record_and_send() { const recorder = new MediaRecorder(_stream); const chunks = []; recorder.ondataavailable = e => chunks.push(e.data); recorder.onstop = e => socket.emit('console-mic-chunks', chunks); setTimeout(()=> recorder.stop(), sendfreq); // we'll have a 5s media file recorder.start(); } // generate a new file every 5s setInterval(record_and_send, sendfreq); } }¡Muchas gracias!
En caso de que su pista de audio del micrófono no necesite sincronizarse con la reproducción de audio (en mi caso, no veo ninguna razón para esto), puede reproducir dos instancias de audio separadas y cambiar el volumen de la que está en curso. (reproducción de audio en su caso).
En pocas palabras, no tiene que mezclar pistas de audio y hacer cosas complejas para resolver esta tarea.
Proyecto de ejemplo:
<input type="range" id="myRange" value="20" oninput="changeVol(this.value)" onchange="changeVol(this.value)"> // Audio playback const audioPlayback = new Audio(); const audioPlaybackSrc = document.createElement("source"); audioPlaybackSrc.type = "audio/mpeg"; audioPlaybackSrc.src = "path/to/audio.mp3"; audioPlayback.appendChild(audioPlaybackSrc); audioPlayback.play(); // Change volume for audio playback on the fly function changeVol(newVolumeValue) { audioPlayback.volume = newVolumeValue; } // Dealing with the microphone navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { // Start recording the audio const mediaRecorder = new MediaRecorder(stream); mediaRecorder.start(); // While recording, store the audio data chunks const audioChunks = []; mediaRecorder.addEventListener("dataavailable", event => { audioChunks.push(event.data); }); // Play the audio after stop mediaRecorder.addEventListener("stop", () => { const audioBlob = new Blob(audioChunks); const audioUrl = URL.createObjectURL(audioBlob); const audio = new Audio(audioUrl); audio.play(); }); // Stop recording the audio setTimeout(() => { mediaRecorder.stop(); }, 3000); });Reproduce múltiples archivos de audio simultáneamente