Cómo grabar pantalla en Chrome con Javascript! (Desktop)

Dile adiós a OBS y Hola a javascript!

David Amaya

David Amaya

Cómo grabar pantalla en Chrome con Javascript! (Desktop)

Grabar pantalla se ha vuelto una necesidad en la era de las clases virtuales y el trabajo remoto, Y aunque existen aplicaciones muy robustas para lograr esto, en ocasiones nos vendrían bien opciones más ligeras y rápidas de utilizar. Por eso hoy te explicaré cómo utilizando 35 líneas de javascript y dos botones puedes crear tu aplicación web para grabar el video de tu pantalla, más el audio del computador y del micrófono.

Puedes probar el resultado final del ejemplo sobre cómo grabar pantalla en Chrome con Javascript! (Desktop) (Codepen)

1 - Crear los botones de iniciar y detener la grabación

  <button onclick="empezarGrabacion()">EMPEZAR A GRABAR</button>
  <button onclick="grabadora.stop()">DETENER GRABACION</button>

2 - Crear la función de grabar pantalla

  • 2.1 Obtener el stream de video de la pantalla y el audio del computador
const empezarGrabacion = async () => {
  const pantallaStream = await navigator.mediaDevices.getDisplayMedia({ video:true, audio: true })
}
  • 2.2 Obtener el audio del micrófono
const empezarGrabacion = async () => {
  const pantallaStream = await navigator.mediaDevices.getDisplayMedia({ video:true, audio: true })
  /* 2.2 */
  const usuarioStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
}
  • 2.3 Unir todas las fuentes de audio y la de video en un solo stream
const empezarGrabacion = async () => {
  const pantallaStream = await navigator.mediaDevices.getDisplayMedia({ video:true, audio: true })
  const usuarioStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
  /* 2.3 */
  const context = new AudioContext();
  const destination = context.createMediaStreamDestination();
  if(pantallaStream.getAudioTracks().length){
    const fuente1 = context.createMediaStreamSource(pantallaStream);
    const f1Gain = context.createGain();
    f1Gain.gain.value = 1;
    fuente1.connect(f1Gain).connect(destination);
  }
  if(usuarioStream.getAudioTracks().length){
    const fuente2 = context.createMediaStreamSource(usuarioStream)
    const f2Gain = context.createGain();
    f2Gain.gain.value = 1;
    fuente2.connect(f2Gain).connect(destination);
  }
  const tracks = [
    ...pantallaStream.getVideoTracks(), 
    ...destination.stream.getAudioTracks()
  ];
  const bundleStream = new MediaStream(tracks);
}
  • 2.4 Crear el objeto grabadora y un arreglo de blobs
const empezarGrabacion = async () => {
  const pantallaStream = await navigator.mediaDevices.getDisplayMedia({ video:true, audio: true })
  const usuarioStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
  const context = new AudioContext();
  const destination = context.createMediaStreamDestination();
  if(pantallaStream.getAudioTracks().length){
    const fuente1 = context.createMediaStreamSource(pantallaStream);
    const f1Gain = context.createGain();
    f1Gain.gain.value = 1;
    fuente1.connect(f1Gain).connect(destination);
  }
  if(usuarioStream.getAudioTracks().length){
    const fuente2 = context.createMediaStreamSource(usuarioStream)
    const f2Gain = context.createGain();
    f2Gain.gain.value = 1;
    fuente2.connect(f2Gain).connect(destination);
  }
  const tracks = [
    ...pantallaStream.getVideoTracks(), 
    ...destination.stream.getAudioTracks()
  ];
  const bundleStream = new MediaStream(tracks);
  /* 2.4 */
  let blobs = []
  window.grabadora = new MediaRecorder(bundleStream, {mimeType: 'video/webm; codecs=vp8,opus'});
  window.grabadora.ondataavailable = (e) => blobs.push(e.data);
}
  • 2.5 Empezar a grabar
const empezarGrabacion = async () => {
  const pantallaStream = await navigator.mediaDevices.getDisplayMedia({ video:true, audio: true })
  const usuarioStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
  const context = new AudioContext();
  const destination = context.createMediaStreamDestination();
  if(pantallaStream.getAudioTracks().length){
    const fuente1 = context.createMediaStreamSource(pantallaStream);
    const f1Gain = context.createGain();
    f1Gain.gain.value = 1;
    fuente1.connect(f1Gain).connect(destination);
  }
  if(usuarioStream.getAudioTracks().length){
    const fuente2 = context.createMediaStreamSource(usuarioStream)
    const f2Gain = context.createGain();
    f2Gain.gain.value = 1;
    fuente2.connect(f2Gain).connect(destination);
  }
  const tracks = [
    ...pantallaStream.getVideoTracks(), 
    ...destination.stream.getAudioTracks()
  ];
  const bundleStream = new MediaStream(tracks);
  let blobs = []
  window.grabadora = new MediaRecorder(bundleStream, {mimeType: 'video/webm; codecs=vp8,opus'});
  window.grabadora.ondataavailable = (e) => blobs.push(e.data);
  /* 2.5 */
  window.grabadora.start();
}
  • 2.6 Definir la función que se ejecutará cuando se detenga la grabación
const empezarGrabacion = async () => {
  const pantallaStream = await navigator.mediaDevices.getDisplayMedia({ video:true, audio: true })
  const usuarioStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
  const context = new AudioContext();
  const destination = context.createMediaStreamDestination();
  if(pantallaStream.getAudioTracks().length){
    const fuente1 = context.createMediaStreamSource(pantallaStream);
    const f1Gain = context.createGain();
    f1Gain.gain.value = 1;
    fuente1.connect(f1Gain).connect(destination);
  }
  if(usuarioStream.getAudioTracks().length){
    const fuente2 = context.createMediaStreamSource(usuarioStream)
    const f2Gain = context.createGain();
    f2Gain.gain.value = 1;
    fuente2.connect(f2Gain).connect(destination);
  }
  const tracks = [
    ...pantallaStream.getVideoTracks(), 
    ...destination.stream.getAudioTracks()
  ];
  const bundleStream = new MediaStream(tracks);
  let blobs = []
  window.grabadora = new MediaRecorder(bundleStream, {mimeType: 'video/webm; codecs=vp8,opus'});
  window.grabadora.ondataavailable = (e) => blobs.push(e.data);
  window.grabadora.start();
  /* 2.6 */
  window.grabadora.onstop = async () => {
    const blob = new Blob(blobs, {type: 'video/webm'});
    const btnDescargar = document.createElement('a');
    btnDescargar.href = window.URL.createObjectURL(blob);
    btnDescargar.download = `GRABACION_${new Date().getTime()}.webm`;
    btnDescargar.click()
  };
}

Y Listo! Ya tenemos aplicaciones web capaces grabar pantalla y audio en sólo 35 líneas de javascript + 2 botones (sin los comentarios)

Nota: En ambientes de producción, por motivos de seguridad la mayoría de navegadores exige tener instalado un certificado SSL que encripte los datos para acceder a la pantalla y el micrófono de los usuarios.

Para ver detalles de compatibilidad con otros navegadores visita el registro de compatibilidad del API getDisplayMedia según developer.mozilla.org

Recuerda: hacer click en la pantalla/ventana/pestaña que desees grabar cuando te salga el popup del navegador y también checkear la opción "compartir audio" si deseas grabar el audio del computador.
Ejemplo del popup para seleccionar el displayMediaEjemplo del popup para seleccionar el displayMedia

Créditos: Fotografía del banner por Soundtrap desde Unsplash

Ilustracion que representa como crece alguien profesionalmente

Entérate de las últimas novedades

Streamings, Noticias y Early Adopter bonus. Sé el primero en enterarte de todo.