App de Transcrição de Áudio
2025Pipeline de transcrição de áudio e diarização de falantes local-first. Whisper (6 tiers de modelo) converte fala em texto; pyannote.audio 3.1 identifica falantes. Suporta arquivos até 1GB via segmentação automática FFmpeg com rastreamento de offset de timestamp, e exporta para PDF/DOCX. UI bilíngue (EN/PT-BR).
O Audio Transcription App é um pipeline de fala-para-texto local-first construído com Streamlit que combina dois modelos state-of-the-art: OpenAI Whisper para transcrição e pyannote.audio para diarização de falantes. Usuários fazem upload de áudio (até 1GB, qualquer formato suportado pelo FFmpeg), selecionam um tier de modelo Whisper, e recebem uma transcrição com labels de falantes exportada como PDF ou DOCX. Toda a inferência roda localmente — nenhum áudio sai da máquina.
Serviços de transcrição como Otter.ai e Rev enviam áudio para servidores na nuvem — inaceitável para entrevistas confidenciais, consultas médicas ou gravações jurídicas. Implantações locais do Whisper lidam com transcrição, mas não com identificação de falantes. O pyannote.audio lida com diarização, mas requer alinhar sua saída com os timestamps do Whisper. O desafio era integrar ambos os modelos em um pipeline onde arquivos grandes não esgotam a memória e os labels de falante permanecem alinhados após transcrição segmentada.
Construir um pipeline de transcrição local-first que: (1) rode inteiramente on-device sem chamadas a APIs na nuvem; (2) lide com arquivos de áudio até 1GB via segmentação; (3) atribua labels de falante a cada segmento Whisper usando diarização pyannote; (4) exporte transcrições com labels como PDF e DOCX; (5) forneça UI Streamlit amigável com suporte bilíngue.
- ◈Desenvolvedor solo — arquitetura do pipeline ML, processamento de áudio, UI, formatos de exportação
- 01Segmentação FFmpeg proporcional para arquivos grandes — em vez de chunks de duração fixa (que podem cortar no meio de uma frase), total_duration é dividido pelo número de segmentos necessários para produzir chunks balanceados. Cada chunk é resampleado para 16kHz mono WAV e seu offset de início rastreado. Após a transcrição, os timestamps são deslocados por chunk_start para restaurar a posição global.
- 02Correspondência por ponto médio para atribuição de falante — para cada segmento Whisper, o falante é determinado encontrando qual intervalo de diarização contém o ponto médio do segmento: (início + fim) / 2. Isso lida com o caso comum onde um falante muda no meio do segmento.
- 03fp16=False para qualidade de transcrição — Whisper suporta inferência em meia-precisão (fp16) que é mais rápida, mas reduz a acurácia, especialmente para fala em línguas não-inglesas e áudio com ruído. Usar propositalmente precisão 32-bit prioriza qualidade de transcrição sobre velocidade.
- 04pyannote/speaker-diarization-3.1 como modelo restrito — o modelo do pyannote requer aprovação de conta no Hugging Face antes do download. O app lida com o token HF via variável de ambiente; o acesso restrito adiciona uma etapa de configuração, mas garante um modelo de diarização de nível de produção.
- 05session_state do Streamlit para renomear falantes — a diarização retorna labels genéricos (SPEAKER_00, SPEAKER_01). O session_state do Streamlit persiste os mapeamentos de nomes customizados do usuário (ex: 'Entrevistador', 'Candidato') entre interações sem re-executar o pipeline.
- 06Entrega de áudio via fila para robustez — chunks de áudio são empurrados para uma fila Python entre a extração FFmpeg e a transcrição Whisper. Isso desacopla o ritmo de extração do ritmo de inferência, permitindo que o pipeline lide com chunks de duração variável sem backpressure bloqueando o FFmpeg.
- →A correspondência por ponto médio é mais robusta que a correspondência por tempo de início para atribuição de falante — versões iniciais atribuíam falante verificando qual intervalo de diarização continha segment_start. Isso falhava quando uma mudança de falante ocorria 0,1s dentro do segmento.
- →A segmentação proporcional requer rastreamento explícito de offsets — a primeira versão concatenava saídas do Whisper sem correção de offset. A diarização rodava no arquivo completo, mas os timestamps de transcrição eram relativos a cada chunk, causando labels de falante aplicados às frases erradas.
- →O hardware para inferência ML local importa enormemente — o modelo large-v3 roda em tempo real em GPU, mas leva 3× o tempo real em CPU para um arquivo de 30 minutos. Expor a seleção de modelo para usuários com diretrizes claras de desempenho foi mais prático que escolher um tier.
- →O session_state do Streamlit é a ferramenta certa para workflows ML em múltiplas etapas — o pipeline tem 4 estágios (upload, transcrição, diarização, label). O session_state cacheia a saída de cada estágio para que editar nomes de falantes não re-execute a transcrição.
Funcional — ferramenta desktop local para workflows de transcrição privados