Files
transcript/README.md
T

7.6 KiB

O que é

Transcript é um app de bandeja para Windows e Linux, feito com Tauri 2. Você aperta um atalho global, fala, e o texto transcrito localmente aparece num editor para revisão antes de ser colado no aplicativo em foco.

  • Alterna a gravação com o atalho global Ctrl+Shift+Space (evento transcript://toggle-recording para o frontend).
  • Grava o microfone em WAV (cpal + hound) na pasta de dados do app.
  • Transcreve chamando o sidecar sherpa-onnx-offline com o modelo Parakeet TDT 0.6B int8 e guarda um diagnóstico de cada tentativa (etapa, exit code, final de stdout/stderr).
  • Mostra o texto num editor, com os botões Copiar e Inserir.
  • Mantém um ícone na bandeja com o menu Mostrar app, Iniciar gravação e Sair.
  • Lista o catálogo de modelos com status e baixa o modelo padrão.

Por que usar

A transcrição roda na sua máquina: o comando que encerra a gravação chama o sherpa-onnx-offline local, sem serviço online no caminho. O texto só vai para o app em foco depois que você revisa e clica em Inserir, que copia para o clipboard e manda Ctrl+V.

Não use ainda se você precisa de um ditado que funcione hoje: o código atual não compila (veja Estado do projeto). Também não há colagem automática no Wayland nem no macOS, e o atalho é fixo.

Como funciona

  • O atalho emite um evento que o frontend escuta para iniciar ou parar a gravação.
  • Ao parar, stop_recording_and_transcribe fecha o WAV, roda o sidecar (de 1 a 4 threads) e devolve o texto num snapshot para o editor.
  • Só depois da revisão o botão Inserir chama request_insert_text, que copia o texto e tenta colar.
  • O código também tem adaptadores para o sidecar CrispASR (modelo GGUF legado) e para APIs compatíveis com OpenAI (padrão http://localhost:8022/v1/audio/transcriptions), mas nenhum comando os usa hoje.
Sistema Inserção no app em foco Fallback
Windows Clipboard + Ctrl+V via PowerShell SendKeys Se o Ctrl+V falhar, o texto fica copiado e uma mensagem avisa.
Linux X11 Clipboard + xdotool key --clearmodifiers ctrl+v Sem xdotool, o texto fica copiado para colar à mão.
Linux Wayland Só copia Cole com Ctrl+V.

A sessão é detectada por XDG_SESSION_TYPE, WAYLAND_DISPLAY e DISPLAY.

Modelo Formato Tamanho no catálogo Idiomas Uso
sherpa-onnx-nemo-parakeet-tdt-0.6b-v2-int8 tarball .tar.bz2 do release asr-models do k2-fsa/sherpa-onnx ~640 MB 25 idiomas europeus, incluindo pt Padrão
parakeet-tdt-0.6b-v3-q8_0 GGUF Q8_0, repositório cstr/parakeet-tdt-0.6b-v3-GGUF 745121600 bytes pt, en Legado, para o adaptador CrispASR

Início rápido

Ferramenta Versão Observação
Node.js + npm 22 Versão usada nos workflows; não há .nvmrc nem engines.
Rust (cargo) stable, edition 2021 Os workflows usam dtolnay/rust-toolchain@stable.
Tauri CLI ^2.9.0 devDependency, vem com npm ci.
Linux (build) libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libasound2-dev Pacotes instalados no CI.
Linux X11 (colar) xdotool Opcional.
tar com bzip2 qualquer Usado por scripts/setup-fixtures.mjs.
git clone https://git.evandro.dev.br/evandro/transcript.git
cd transcript
npm ci
node scripts/setup-sidecar.mjs   # baixa o sherpa-onnx-offline para src-tauri/binaries/
npm run tauri:dev                # app em desenvolvimento (Vite em 127.0.0.1:1420)
npm run tauri:build              # bundles em src-tauri/target/release/bundle/

Hoje os dois comandos tauri:* param na compilação do Rust. O front end sozinho roda com npm run dev, e os testes dele com npm test -- --run.

O modelo não vem no instalador: o app baixa para a pasta de dados (%LOCALAPPDATA%\transcript\models no Windows, ~/.local/share/transcript/models no Linux) pelo comando download_default_model_command. As gravações ficam em recordings/ na mesma pasta.

Configuração

Não há .env.example e nenhuma variável é obrigatória.

Variável Descrição
SHERPA_ONNX_SIDECAR Caminho do sidecar; tem prioridade sobre a pasta binaries/ e o PATH.
SHERPA_ONNX_VERSION Versão do release do sherpa-onnx baixada por setup-sidecar.mjs (padrão v1.12.23).
SHERPA_ONNX_TRIPLE Target triple do sidecar (padrão: detectado via rustc -vV).

O método de inserção nas configurações aceita clipboardPaste (padrão), keyTyping e manualCopy.

Estado do projeto

Protótipo em desenvolvimento por uma pessoa. As versões divergem: 0.1.0 em package.json e Cargo.toml, 0.3.1 em tauri.conf.json. O que a leitura do código mostra:

  • O crate Rust não compila como está: settings/mod.rs usa crate::shortcuts::DEFAULT_HOTKEY, que não existe; transcription/openai.rs importa crate::secrets, módulo que lib.rs não declara; ui_commands.rs lê settings.transcription.model_id, campo que TranscriptionSettings não tem.
  • O frontend chama comandos que não estão registrados no invoke_handler de lib.rs: stop_recording (usado pelo botão Parar), transcribe_pending, minimize_window, close_window, save_openai_api_key e clear_openai_api_key.
  • Nome do sidecar: setup-sidecar.mjs grava src-tauri/binaries/sherpa-onnx-offline-<triple>, mas o app procura sherpa-onnx-offline sem o sufixo e cai no PATH. Até isso mudar, aponte SHERPA_ONNX_SIDECAR para o binário.
  • keyTyping não tem efeito: request_insert_text usa sempre ClipboardPaste.
  • tauri.conf.json não declara bundle.externalBin (o sidecar não vai no instalador), bundle.resources aponta para resources/whisper/, que não existe, e só icons/icon.ico existe dos ícones listados. whisper.cpp só aparece no spec do redesign.
  • O atalho Ctrl+Shift+Space é fixo em shortcuts.rs, e o item Iniciar gravação da bandeja só mostra a janela.
  • ci.yml baixa o modelo v3-int8 (o catálogo usa v2-int8) e chama o teste sherpa_onnx::tests::real_transcription_returns_known_text, que não existe em sherpa_onnx.rs.

Workflows em .github/workflows/: ci.yml (PR e push em main: typecheck, testes, build e cargo test no Ubuntu 22.04), build.yml (push em main e manual: bundles para Windows e Linux como artefatos) e release.yml (tag v*.*.* ou manual: publica a GitHub Release Transcript <tag>).

Antes de abrir um PR: npm run typecheck && npm test -- --run && cargo test --manifest-path src-tauri/Cargo.toml.

Licença

Sem licença publicada: todos os direitos reservados.