Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

471
Visualizações
Cómo grabar un lienzo + audio sin un dibujo nuevo en el lienzo

Quiero grabar un video de una secuencia de comandos que se ejecuta en un lienzo HTML y, al mismo tiempo, grabar el audio del micrófono. Estoy usando canvas.captureStream() para crear una transmisión de video desde el lienzo. Luego creo una transmisión de audio desde getUserMedia() y mezclo ambas transmisiones en una sola que se pasa a un nuevo MediaRecorder .

El problema es que, de forma predeterminada, no se captura ningún cuadro en el flujo del lienzo si no se pinta nada en el lienzo. Entonces, el video y el audio están desincronizados en las partes donde el lienzo está inactivo.

El código que estoy usando se ve así:

 let recording = false; let mediaRecorder; let chunks = []; let newStream, canvasStream let constrains = { audio: { channelCount: { ideal: 2, min: 1 }, sampleRate: 48000, sampleSize: 16, volume: 1, echoCancellation: true, noiseSuppression: true, autoGainControl: true, }, video: false }; recButton.addEventListener("click", () => { recording = !recording; if (recording) { recButton.textContent = "Click to Stop"; recButton.style.color = "red"; canvasStream = canvas.captureStream(40); // ---> captureStream() navigator.mediaDevices.getUserMedia(constrains) // ---> audioStream .then(audioStream => { canvasStream.addTrack(audioStream.getTracks()[0]); // --> joint the two streams mediaRecorder = new MediaRecorder(canvasStream, { mimeType: 'video/webm; codecs=vp9', // ignoreMutedMedia: false }); mediaRecorder.ondataavailable = e => { if (e.data.size > 0) { chunks.push(e.data); // chunks = []; already defined above.... } }; mediaRecorder.start(); }) .catch(err => { console.log(err.name, err.message); }); } else { recButton.textContent = "Record"; recButton.style.color = "black"; mediaRecorder.stop() stopTracks(canvasStream); // function stop defined below console.log(mediaRecorder.state) setTimeout(() => { // why this is necessary? const blob = new Blob(chunks, { type: "video/mp4" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "recording.mp4"; a.click(); URL.revokeObjectURL(url); }, 200); } }); let stopTracks = stream => stream.getTracks().forEach(track => track.stop());
about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

Eso es un pequeño error de Chrome, ya que incluso si la pista de video no debería haber producido datos en este caso, la pista de audio sí lo ha hecho y MediaRecorder debería haberla capturado.

La única forma de solucionar esto es realizar un nuevo dibujo en el lienzo al menos en el mismo marco de pintura que su llamada a canvas.captureStream() .
Con un contexto 2D, la forma menos intrusiva de hacerlo es dibujar un rectángulo transparente de 1x1.

 let recording = false; let mediaRecorder; const chunks = []; let newStream, canvasStream const constrains = { audio: { channelCount: { ideal: 2, min: 1 }, sampleRate: 48000, sampleSize: 16, volume: 1, echoCancellation: true, noiseSuppression: true, autoGainControl: true, }, video: false }; recButton.addEventListener("click", () => { recording = !recording; if (recording) { recButton.textContent = "Click to Stop"; recButton.style.color = "red"; canvasStream = canvas.captureStream(40); // force activate the Canvas track forceEmptyDrawing(canvas); navigator.mediaDevices.getUserMedia(constrains) // ---> audioStream .then(audioStream => { canvasStream.addTrack(audioStream.getTracks()[0]); // --> joint the two streams mediaRecorder = new MediaRecorder(canvasStream, { // don't forget the audio codec mimeType: "video/webm; codecs=vp9,opus", // ignoreMutedMedia: false }); mediaRecorder.ondataavailable = e => { if (e.data.size > 0) { chunks.push(e.data); } }; mediaRecorder.start(10); }) .catch(err => { console.log(err.name, err.message); }); } else { recButton.textContent = "Record"; recButton.style.color = "black"; mediaRecorder.stop() // wait for the stop event // don't rely on some magic timeout mediaRecorder.onstop = () => { // only when the recorder is completely stopped // you can stop the tracks stopTracks(canvasStream); const blob = new Blob(chunks, { type: "video/webm" // you asked for webm, not mp4 }); // just to verify we did record something console.log(`recorded a ${ blob.size }b file`); }; } }); const stopTracks = stream => stream.getTracks().forEach(track => track.stop()); // draws a 1x1 transparent rectangle function forceEmptyDrawing(canvas) { const ctx = canvas.getContext("2d"); const alpha = ctx.globalAlpha; ctx.globalAlpha = 0; ctx.fillRect(0, 0, 1, 1); ctx.globalAlpha = alpha; }

Como un violín , ya que StackSnippets no puede usar gUM (solo para Chrome, Firefox y Safari no admiten el mimeType provisto).

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda