Gravação de Tela com JavaScript: Construindo uma Aplicação com Persistência no Navegador

12/03/2025

A gravação de tela é um recurso essencial para tutoriais, suporte técnico e captura de conteúdos dinâmicos. Pensando nisso, desenvolvi um sistema completo de gravação de tela utilizando JavaScript e a MediaRecorder API, garantindo a captura tanto do vídeo quanto do áudio do sistema e do microfone. O diferencial desse projeto é a persistência das gravações no navegador, utilizando localStorage.

O código-fonte do projeto está disponível no GitHub:
Repositório GitHub – ScreenRec


Arquitetura do Projeto

O projeto consiste em uma interface web construída com HTML, CSS e Bootstrap 5, além da lógica de gravação implementada em JavaScript puro. Os vídeos são armazenados no navegador e podem ser acessados posteriormente.

Principais Tecnologias Utilizadas

  • JavaScript (ES6+) para manipulação da API de mídia e armazenamento.
  • MediaRecorder API para captura de tela e áudio do sistema.
  • localStorage para persistência dos vídeos no navegador.
  • Bootstrap 5 para estilização e componentes responsivos.

Funcionalidades Implementadas

Gravação de Tela com Áudio

Utilizei a MediaRecorder API para capturar tanto o vídeo da tela quanto o áudio do sistema e do microfone. A função navigator.mediaDevices.getDisplayMedia() permite selecionar a tela ou janela a ser gravada, enquanto navigator.mediaDevices.getUserMedia() adiciona o áudio do usuário.

Código:


  1. async function startRecording() {  
  2.     try {  
  3.         const displayStream = await navigator.mediaDevices.getDisplayMedia({  
  4.             video: { cursor: "always" },  
  5.             audio: { systemAudio: "include" }  
  6.         });  
  7.   
  8.         const audioStream = await navigator.mediaDevices.getUserMedia({ audio: true });  
  9.   
  10.         const combinedStream = new MediaStream([  
  11.             ...displayStream.getVideoTracks(),  
  12.             ...audioStream.getAudioTracks(),  
  13.         ]);  
  14.   
  15.         mediaRecorder = new MediaRecorder(combinedStream);  
  16.         mediaRecorder.start();  
  17.     } catch (error) {  
  18.         console.error("Erro ao iniciar gravação:", error);  
  19.     }  
  20. }  


Armazenamento Persistente no Navegador

Os vídeos são convertidos para Base64 e salvos no localStorage. Isso permite que o usuário acesse gravações anteriores sem necessidade de download imediato.

O problema dessa abordagem é que o localStorage tem um limite de aproximadamente cinco megabytes, o que restringe gravações maiores. A melhoria futura seria migrar o armazenamento para IndexedDB, que permite armazenar arquivos grandes.


  1. function saveRecording(blob) {  
  2.     const reader = new FileReader();  
  3.     reader.onloadend = () => {  
  4.         const base64 = reader.result;  
  5.         const recordings = JSON.parse(localStorage.getItem("recordings")) || [];  
  6.         recordings.push({ date: new Date().toLocaleString(), base64 });  
  7.         localStorage.setItem("recordings", JSON.stringify(recordings));  
  8.     };  
  9.     reader.readAsDataURL(blob);  
  10. }  

Interface com Lista de Gravações

O sistema exibe todas as gravações armazenadas e permite que o usuário baixe, visualize ou exclua cada uma delas.

Uma melhoria futura seria implementar paginação e filtros para facilitar a navegação em grandes volumes de gravações.



  1. function loadRecordings() {  
  2.     const recordings = JSON.parse(localStorage.getItem("recordings")) || [];  
  3.     recordingsTableBody.innerHTML = "";  
  4.     recordings.forEach((rec, index) => {  
  5.         recordingsTableBody.innerHTML += `  
  6.             <tr>  
  7.                 <td>${rec.date}</td>  
  8.                 <td><a href="${rec.base64}" download="gravacao.mp4" class="btn btn-success">Baixar</a></td>  
  9.                 <td><button class="btn btn-info" onclick="openModal(${index})">Visualizar</button></td>  
  10.                 <td><button class="btn btn-danger" onclick="deleteRecording(${index})">Excluir</button></td>  
  11.             </tr>`;  
  12.     });  
  13. }  

Pontos de Melhoria

Apesar do projeto estar funcional, há pontos que podem ser otimizados:

Substituir localStorage por IndexedDB

O localStorage tem uma limitação severa de espaço e não foi projetado para armazenar arquivos grandes. A solução ideal é migrar o armazenamento para IndexedDB, que permite salvar arquivos binários sem limitação prática de tamanho.

Implementar Compressão de Vídeo

Os arquivos gerados podem ser grandes. Para reduzir o consumo de armazenamento e melhorar a experiência do usuário, é possível usar a WebCodecs API ou um backend que processe e compacte os vídeos antes do download.

Melhorar o Controle de Erros

Atualmente, o código não trata cenários como:

  • Usuário negando permissões de câmera e microfone.
  • Falha ao gravar por falta de espaço.
  • Erros ao salvar vídeos no localStorage.

Adicionando um tratamento de erros robusto, a experiência do usuário melhora.

Implementar Upload para Nuvem

Atualmente, todas as gravações são armazenadas no navegador. Uma solução mais eficiente seria permitir o upload automático para um serviço de armazenamento em nuvem, como AWS S3, Google Drive ou Firebase Storage.


O projeto ScreenRec é uma solução prática para gravação de tela diretamente no navegador. Utilizando apenas JavaScript puro, MediaRecorder API e localStorage, consegui criar um sistema funcional e persistente.

Entretanto, ainda há melhorias que podem ser feitas, como a migração para IndexedDB, implementação de compressão de vídeo, aprimoramento no tratamento de erros e suporte para armazenamento na nuvem.

Se quiser testar ou contribuir para o projeto, o código-fonte está disponível no GitHub:
Repositório GitHub – ScreenRec

Caso tenha sugestões ou dúvidas, deixe um comentário.