Offline speech-to-text desktop app. Drop in WhatsApp voice notes, get clean TXT and SRT. Runs faster-whisper entirely on your machine — no cloud, no API keys.
Transcriber
Transcreve qualquer áudio em texto, 100% no seu computador: reunião, entrevista, aula, podcast, mensagem de voz. Fila para vários arquivos, exportação em TXT e SRT, e interface em português e inglês.
Usa faster-whisper
Índice
- Como funciona
- Instalação para usar
- Rodar a partir do código
- Como usar
- Fila e transcrição em lote
- Modelos e primeiro download
- GPU (CUDA)
- Inicializar o repositório
- Pipelines
- Gerar os instaladores localmente
- Estrutura do projeto
- Testes
- Troubleshooting
- Limitações conhecidas
- Privacidade
- Licença
Como funciona
Do arquivo escolhido até o texto exportado. A interface nunca trava porque a decodificação roda em threads separadas, que só conversam com a tela por uma fila de eventos.
flowchart TD A["Adicionar áudios"] --> B{"Extensão suportada<br/>e ainda não na fila?"} B -- não --> B1["Ignorado, com aviso"] B -- sim --> C["Fila de áudios"] C --> D["Botão Transcrever"] subgraph MAIN ["Thread principal — Tkinter"] D --> E["preload: importa o faster-whisper AQUI.<br/>Fazer isso na thread aborta o app no macOS"] E --> F["Cria o pool de 1 a 3 workers"] UI["Drena a fila de eventos a cada 80 ms<br/>e redesenha a tela"] end subgraph WORKER ["Threads de transcrição"] F --> G{"Modelo já<br/>em memória?"} G -- sim --> K G -- não --> H{"Pesos em disco?"} H -- não --> H1["Baixa do Hugging Face.<br/>Única etapa que usa internet"] H1 --> I H -- sim --> I["Carrega o modelo"] I --> J{"CUDA disponível<br/>e marcada?"} J -- sim --> J1["GPU float16"] J -- não --> J2["CPU int8"] J1 -. "qualquer falha:<br/>descarta e refaz" .-> J2 J1 --> K["Decodifica com VAD e beam_size 5"] J2 --> K K --> L{"Achou fala?"} L -- não --> L1["Erro amigável:<br/>nenhuma fala encontrada"] L -- sim --> M["Segmentos com timestamps"] end K -. "progresso e cancelamento<br/>a cada segmento" .-> UI L1 --> UI M --> N["Texto na caixa de transcrição"] N --> O["Copiar · TXT · SRT · Salvar todos"]
Três detalhes que o diagrama torna explícitos:
- na thread principal. Importar o
preloaddentro de uma thread cria umfaster-whisperfora da main thread e o macOS mata o processo. Por isso o import acontece antes de qualquer worker subir.Tk() - A GPU nunca derruba a transcrição. Qualquer falha em CUDA descarta o modelo e refaz o trabalho em CPU, sem perder o arquivo da fila.
- Internet só numa etapa. Baixar os pesos do modelo é a única coisa que usa rede, e só na primeira vez de cada modelo. O áudio nunca sai da máquina.
Instalação para usar
Baixe o arquivo da sua plataforma na página de Releases. Os binários não trazem os modelos Whisper: o primeiro uso baixa o modelo escolhido (precisa de internet uma vez).
macOS
- Baixe (Apple Silicon) ou
Transcriber-macos-arm64.dmg(Intel).Transcriber-macos-x86_64.dmg - Abra o e arraste o app para Aplicativos.
.dmg - Na primeira execução o Gatekeeper bloqueia, porque o binário não é assinado. Clique com o botão direito no app → Abrir → Abrir. Ou, pelo terminal:
xattr -dr com.apple.quarantine "/Applications/Transcriber.app"
Windows
- Baixe e extraia.
Transcriber-windows-x86_64.zip - Rode .
Transcriber.exe - O SmartScreen pode avisar por ser um executável não assinado: Mais informações → Executar assim mesmo.
Ubuntu / Debian
sudo apt install python3-tk # a interface precisa do Tk tar -xzf Transcriber-linux-x86_64.tar.gz ./Transcriber/Transcriber
Rodar a partir do código
Requer Python 3.11+ e Tkinter (Linux:
sudo apt install python3-tkbrew install python-tkWindows
python -m venv .venv .venv\Scripts\activate pip install -r requirements.txt python app.py
macOS/Linux
python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt python app.py
Importante: use sempre o Python do ambiente virtual. Chamar o
do sistema resulta em "A biblioteca faster-whisper não está instalada". Sem ativar o venv, use o caminho direto:python(Windows:.venv/bin/python app.py)..venv\Scripts\python app.py
Para testes e build, instale também
pip install -r requirements-dev.txtComo usar
- Adicionar áudios — um ou vários de uma vez. Formatos: MP3, WAV, M4A, OGG, OPUS,
AAC, FLAC. Isso cobre desde gravador de reunião até as mensagens de voz do WhatsApp,
que saem em .
.opus - Escolha o idioma do áudio, o modelo e quantas transcrições simultâneas.
- Transcrever. A linha de progresso avança e dá para Cancelar a qualquer momento.
- Clique em um arquivo da fila para ler a transcrição dele.
- Copiar texto, Salvar TXT, Salvar SRT, Salvar todos (TXT + SRT de tudo que terminou) ou Abrir pasta.
Resumo exibido ao terminar:
Arquivo: reuniao-2026-08-15.mp3 Idioma detectado: Português (pt) — confiança 100% Modelo: medium Dispositivo: CPU Duração do áudio: 00:20 Tempo de processamento: 7.4 segundos
SRT gerado:
1 00:00:00,000 --> 00:00:04,500 Olá, tudo bem? 2 00:00:04,500 --> 00:00:08,200 Estou enviando esse áudio...
O campo interface troca todos os textos entre Português (BR) e English na hora, sem reiniciar e sem perder a fila.
Fila e transcrição em lote
Cada arquivo tem seu estado: na fila, transcrevendo (com porcentagem), concluído (com o tempo), erro (com o motivo) ou cancelado. Um arquivo com erro não interrompe os outros.
Para tirar um arquivo da lista: selecione e clique em Remover selecionado (ou tecle
DeleteO campo simultâneas controla quantos arquivos rodam ao mesmo tempo:
| Valor | Quando usar | | ----- | ----------- | | 1 · fila (padrão) | Praticamente sempre. O CTranslate2 já usa todos os núcleos em um arquivo só. | | 2 ou 3 · paralelo | Só com modelos leves (
tinybasesmallRodar
mediumlarge-v3Modelos e primeiro download
Na primeira vez que um modelo é usado, os pesos são baixados do Hugging Face para
~/.cache/huggingface/hub%USERPROFILE%\.cache\huggingface\hubA aplicação só mostra o aviso de download para o modelo que ainda não está no disco.
| Modelo | Download | RAM (int8) | Quando usar | | ---------- | --------- | ---------- | ----------- | |
tinybasesmallmediumlarge-v3Medido neste projeto (macOS, Apple Silicon, CPU
int8| Modelo | Tempo | Proporção da duração | | -------- | ------ | -------------------- | |
smallmediumDiferença real de qualidade nesse áudio: o
smallmediumGPU (CUDA)
- GPUs NVIDIA são detectadas via CTranslate2 e a opção usar CUDA aparece automaticamente. Sem CUDA no sistema, o controle nem é exibido.
- Requer CUDA 12 + cuBLAS/cuDNN 9.
- Qualquer falha (driver, VRAM, cuDNN ausente) faz a transcrição ser refeita automaticamente na CPU, com aviso na barra de status.
- macOS não tem CUDA: sempre CPU ().
int8
Inicializar o repositório
O projeto já vem com
.gitignoreLICENSEcd /caminho/para/transcript git init git add . git commit -m "feat: transcrição de áudio offline com fila e identidade Nzila" git branch -M main
Crie o repositório no GitHub (vazio, sem README) e conecte:
git remote add origin git@github.com:samuelrms/transcriber.git git push -u origin main
O que não vai para o repositório, por decisão do
.gitignore.venv/build/dist/output/transcriber.logO que vai: as fontes
.ttfassets/fontsPublicar uma versão
A release é automática: sai a cada merge ou push direto na
main__version__# 1. suba a versão no pacote sed -i '' 's/__version__ = "1.0.0"/__version__ = "1.1.0"/' transcriber/__init__.py # 2. mande para a main, direto ou por pull request git commit -am "chore: bump version to 1.1.0" git push origin main
O workflow lê o
__version__v1.1.0- não existe → compila as quatro variantes, roda os testes em cada uma, cria a tag no commit e publica tudo em Releases;
- já existe → pula o build inteiro e registra um aviso no run. Commit comum não gera release nem gasta minutos de CI.
Não é preciso criar tag na mão: ela nasce junto da release, no mesmo commit, então a versão do código e a tag do repositório nunca divergem. O
Transcriber.spec__version__Info.plistPipelines
Dois workflows em .github/workflows/
ci.yml
— a cada push e pull request
ci.yml| Job | O que faz | | --- | --- | |
testpyflakespytestpyflakessmokexvfbrelease.yml
— a cada merge ou push na main
release.ymlmainPrimeiro um job curto lê o
__version__| Runner | Artefato | Formato | | --- | --- | --- | |
macos-latestTranscriber-macos-arm64.dmg.appmacos-13Transcriber-macos-x86_64.dmgwindows-latestTranscriber-windows-x86_64.zip.exeubuntu-22.04Transcriber-linux-x86_64.tar.gzCada job roda os testes antes de empacotar e falha cedo, com mensagem clara, se o Tkinter não estiver disponível — melhor do que publicar um binário cuja interface não abre. No fim, o job
releaseflowchart LR T["push na main"] --> V{"__version__ já<br/>tem release?"} V -- sim --> S["Para aqui, sem gastar build"] V -- não --> M1["macos-latest"] V -- não --> M2 V -- não --> W V -- não --> U M2["macos-13"] W["windows-latest"] U["ubuntu-22.04"] M1 --> P1["testes + PyInstaller"] M2 --> P2["testes + PyInstaller"] W --> P3["testes + PyInstaller"] U --> P4["testes + PyInstaller"] P1 --> A1["Transcriber-macos-arm64.dmg"] P2 --> A2["Transcriber-macos-x86_64.dmg"] P3 --> A3["Transcriber-windows-x86_64.zip"] P4 --> A4["Transcriber-linux-x86_64.tar.gz"] A1 --> R["Release no GitHub"] A2 --> R A3 --> R A4 --> R
O Ubuntu usa
ubuntu-22.04Gerar os instaladores localmente
pip install -r requirements-dev.txt pyinstaller --noconfirm --clean Transcriber.spec
O mesmo
.spec| Sistema | Saída | Observação | | --- | --- | --- | | macOS |
dist/Transcriber.appdist/Transcriber/.tar.gzdist/Transcriber.exeNos três casos o
.spectokenizershuggingface-hubUma build empacotada não escreve dentro do próprio bundle: o log vai para
~/Library/Logs/Transcriber~/Documents/TranscriberEstrutura do projeto
Código, comentários, nomes de arquivos e pastas em inglês; todo texto que o usuário lê fica em
i18n.pytranscript/ ├── app.py # ponto de entrada ├── conftest.py # deixa o pacote importável nos testes ├── requirements.txt # dependências de execução ├── requirements-dev.txt # pytest, pyflakes e pyinstaller ├── Transcriber.spec # build multiplataforma ├── LICENSE # MIT, com as licenças de terceiros ├── README.md / README.en.md # este arquivo, nos dois idiomas ├── DESIGN.md # a identidade Nzila dentro do Tkinter │ ├── .github/workflows/ │ ├── ci.yml # lint + testes + janela headless │ └── release.yml # binários para macOS, Windows e Ubuntu │ ├── assets/fonts/ # Fraunces + Instrument Sans (OFL) e licenças │ ├── transcriber/ │ ├── i18n.py # catálogo pt-BR / en │ ├── config.py # modelos, extensões, parâmetros do VAD │ ├── errors.py # exceções com chaves de tradução │ ├── audio.py # validação de arquivo e extensão │ ├── srt.py # timestamps e montagem do SRT │ ├── device.py # detecção de CUDA, perfis CPU/GPU │ ├── transcription.py # modelo, cache, transcrição, erros │ ├── batch.py # fila, estado e progresso agregado │ ├── model_store.py # quais modelos já estão baixados │ ├── paths.py # diretórios no código e no binário │ ├── fonts.py # registro das fontes só no processo │ ├── logging_setup.py # log em arquivo + terminal │ ├── desktop.py # abrir a pasta no gerenciador de arquivos │ └── ui/ │ ├── theme.py # tokens Nzila e estilos ttk │ ├── widgets.py # linha do caminho, botões e cartões │ ├── worker.py # pool de threads + fila de eventos │ └── main_window.py # janela principal │ ├── output/ # TXT e SRT salvos (sugestão padrão) └── tests/ # 124 testes, nenhum baixa modelo
A lógica de Whisper vive em
transcription.pyfaster_whispersrt.pyaudio.pybatch.pyTestes
pip install -r requirements-dev.txt pytest -q
124 testes em torno de 0,15 s: timestamps SRT, geração de legenda, validação de extensões, duração, progresso, fallback de GPU para CPU, cache do modelo, fila em lote, detecção de modelo baixado, diretórios em build congelada e a simetria dos catálogos de tradução. Nenhum modelo Whisper é baixado durante os testes.
Troubleshooting
| Problema | Solução | | --- | --- | |
A biblioteca faster-whisper não está instalada.venv/bin/python app.pyxattr -dr com.apple.quarantineModuleNotFoundError: No module named 'tkinter'sudo apt install python3-tkbrew install python-tkhf-xethuggingface_hubHF_HUB_DISABLE_XET=11 · filasmallbasemediumlarge-v3Library cublas64_12.dll is not foundassets/fonts.ttftranscriber.log~/Library/Logs/TranscriberLimitações conhecidas
- A qualidade depende do modelo e do áudio; gíria, ruído e falantes sobrepostos derrubam a precisão.
- Não há separação de falantes (diarization).
- e
mediumsão pesados para a maioria das CPUs.large-v3 - Transcrição paralela existe, mas em CPU quase não acelera — a fila é o caminho certo.
- Os binários publicados não são assinados.
- Python 3.14 funciona, mas 3.11/3.12 é o combo mais testado pelas dependências.
Privacidade
Transcrição realizada localmente no seu computador.
- Nenhum áudio, texto ou metadado sai da máquina.
- A única conexão de rede é o download dos pesos do modelo no primeiro uso.
- Depois disso, funciona totalmente offline.
- O log grava eventos e erros — nunca o conteúdo transcrito.
Licença
MIT. Componentes de terceiros mantêm suas licenças: faster-whisper e CTranslate2 (MIT), PyAV (BSD-3) com FFmpeg (LGPL), pesos Whisper (MIT, baixados em tempo de execução) e as fontes Fraunces e Instrument Sans (OFL 1.1).