Files
transcript/docs/superpowers/specs/2026-07-13-audio-history-streaming-fallback-design.md
T
evandrodevbr 06aaeeaf79 wip: snapshot das alterações não commitadas (2026-10-20)
Origem: D:/Documents/Github/transcript
Arquivos omitidos (segredos, bancos de dados, logs, >50 MB): 2
2026-10-20 00:50:17 -03:00

3.0 KiB

Áudio persistente, fallback local e streaming — Design

Objetivo

Guardar os 10 áudios mais recentes enviados à transcrição, permitir salvar qualquer um deles em um local escolhido pelo usuário, usar Whisper local em PT-BR quando a API falhar e inserir texto progressivamente quando a API responder em streaming.

Escopo e decisões

Histórico de áudio

  • Cada gravação finalizada permanece no diretório de dados do aplicativo como WAV.
  • O histórico é limitado a 10 arquivos, ordenados por data de modificação decrescente. Ao finalizar uma gravação, arquivos mais antigos são removidos.
  • Cada item expõe somente id (nome de arquivo validado), nome, tamanho e data. Caminhos absolutos nunca são enviados ao frontend.
  • O frontend mostra um <details> compacto de “Áudios recentes”, com “Baixar último áudio” e ações de salvar por item.
  • O salvamento usa o diálogo nativo de arquivo e copia o WAV para a localização escolhida. Cancelar o diálogo não é erro.

Fallback API → Whisper

  • O modo de servidor tenta a API configurada primeiro.
  • Qualquer falha antes de texto parcial aciona Whisper embarcado com idioma fixo pt.
  • Se uma resposta streaming já tiver emitido texto parcial, não há fallback automático: repetir o texto poderia duplicar o que já foi inserido no campo ativo. O erro é mostrado para revisão.
  • O modo local continua usando Whisper primeiro e API como fallback, preservando o comportamento existente.

Streaming de resposta

  • O cliente envia Accept: text/event-stream, application/x-ndjson, application/json.
  • A API é detectada como streaming exclusivamente pelo Content-Type da resposta: text/event-stream ou application/x-ndjson.
  • Eventos SSE/NDJSON aceitam delta, text, transcript, result, output, data e choices[0].delta.content; payloads cumulativos são convertidos em somente o sufixo novo.
  • Na janela principal, cada fragmento atualiza o editor de transcrição.
  • No atalho global, o primeiro fragmento esconde a barra não focável e tenta colar imediatamente no campo externo ativo; a transcrição final não é colada uma segunda vez.
  • Respostas JSON normais mantêm o fluxo atual: texto completo somente após concluir.

Segurança e limites

  • IDs de áudio são nomes simples de WAV; separadores de diretório, extensões diferentes e caminhos fora do diretório de gravações são rejeitados.
  • O backend nunca recebe um destino de arquivo escolhido pelo frontend; o diálogo nativo escolhe o destino e o backend executa a cópia local.
  • Áudio é dado potencialmente sensível. A retenção fixa em 10 arquivos é deliberada e visível na UI; não há telemetria nem upload adicional.

Testes

  • Histórico: limita a 10, remove o mais antigo, rejeita IDs inseguros.
  • Fallback: API-only usa Whisper PT-BR quando não houve parcial; streaming parcial não dispara fallback.
  • Streaming: detecta Content-Type, extrai deltas/cumulativos e evita duplicação.
  • Frontend: renderiza histórico e pede download do item selecionado.