From 2c573a49eababe65403240d62cd22c4bf7126976 Mon Sep 17 00:00:00 2001
From: Evandro Fonseca Junior <1+evandro@noreply.git.evandro.dev.br>
Date: Sat, 24 Oct 2026 04:13:06 +0000
Subject: [PATCH] docs(readme): padroniza README (hero, badges, quickstart,
arquitetura)
---
README.md | 227 ++++++++++++++++++++++++++++++++++++------------------
1 file changed, 151 insertions(+), 76 deletions(-)
diff --git a/README.md b/README.md
index aa84172..e6f0978 100644
--- a/README.md
+++ b/README.md
@@ -1,96 +1,171 @@
-# Transcript Desktop
+
-Aplicativo desktop de transcrição para Windows e Linux, construído com Tauri + Rust + TypeScript. O objetivo é oferecer ditado/transcrição offline-first com revisão obrigatória em modal antes de inserir texto em outro aplicativo.
+
Transcript Desktop
-## Estado atual
+
Ditado offline para Windows e Linux: grave com um atalho global, revise o texto e cole no app em foco.
-Este repositório contém um MVP nativo funcional:
+
Quickstart ·
+
Arquitetura ·
+
Documentação ·
+
Issues
-- app Tauri 2 funcional;
-- modal editável em TypeScript sem framework pesado;
-- backend Rust modular;
-- catálogo e download do modelo `cstr/parakeet-tdt-0.6b-v3-GGUF` em Q8;
-- captura real de microfone em WAV via CPAL;
-- execução do sidecar CrispASR/Parakeet;
-- hotkey global `Ctrl+Shift+Space`;
-- inserção híbrida por clipboard + paste automático no Windows/X11 quando disponível;
-- fallback manual no Wayland;
-- tray/system tray básico;
-- CI, build e release via GitHub Actions.
+
+
+
-## Arquitetura
+
+
+
+
+## 📌 O problema
+
+Ditar texto em qualquer aplicativo do desktop exige gravar, transcrever e colar o resultado por conta própria, e boa parte das opções depende de serviço online. O Transcript fica residente na bandeja, grava por atalho global, transcreve localmente e deixa o texto editável antes de inseri-lo no aplicativo em foco.
+
+## ✨ O que faz
+
+- Alterna a gravação com o atalho global `Ctrl+Shift+Space` (evento `transcript://toggle-recording` para o frontend).
+- Captura o microfone em WAV (cpal + hound) na pasta de dados do app.
+- Transcreve localmente 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).
+- Inclui adaptadores para o sidecar CrispASR (modelo GGUF legado) e para APIs compatíveis com OpenAI.
+- Mostra o texto num editor, com os botões Copiar e Inserir, para revisar antes de colar.
+- Cola no app em foco: copia para o clipboard e aciona `Ctrl+V` (PowerShell no Windows, `xdotool` no X11).
+- Mantém ícone na bandeja com o menu Mostrar app, Iniciar gravação e Sair; o clique esquerdo mostra a janela.
+- Lista o catálogo de modelos com status e baixa o modelo padrão.
+
+## 🚀 Quickstart
+
+| Ferramenta | Versão |
+|---|---|
+| Node.js + npm | 22 (usada nos workflows; não há `.nvmrc` nem `engines`) |
+| Rust (cargo) | `stable`, edition 2021 (workflows usam `dtolnay/rust-toolchain@stable`) |
+| Tauri CLI | `^2.9.0` (devDependency) |
+| Linux (build) | `libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libasound2-dev` |
+| Linux X11 (colar) | `xdotool`, opcional |
+| `tar` com bzip2 | usado por `scripts/setup-fixtures.mjs` |
+
+```bash
+npm ci
+node scripts/setup-sidecar.mjs # baixa 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/
+```
+
+O modelo não vai no instalador: o app o baixa para a pasta de dados (`%LOCALAPPDATA%\transcript\models` no Windows, `~/.local/share/transcript/models` no Linux) pelo comando Tauri `download_default_model_command`. As gravações ficam em `recordings/` na mesma pasta.
+
+Não há `.env.example` e nenhuma variável é obrigatória. As opcionais:
+
+| Variável | Obrigatória | Descrição |
+|---|---|---|
+| `SHERPA_ONNX_SIDECAR` | Não | Caminho do sidecar; tem prioridade sobre `src-tauri/binaries/` e sobre o `PATH`. |
+| `SHERPA_ONNX_VERSION` | Não | Versão do release sherpa-onnx baixada por `setup-sidecar.mjs` (padrão `v1.12.23`). |
+| `SHERPA_ONNX_TRIPLE` | Não | Target triple do sidecar (padrão: detectado via `rustc -vV`). |
+
+## 🧱 Arquitetura
+
+```mermaid
+flowchart LR
+ HK["Hotkey global Ctrl+Shift+Space"] --> UI["Frontend TypeScript"]
+ UI --> CMD["Comandos Tauri em Rust"]
+ CMD --> REC["Gravação WAV com cpal e hound"]
+ REC --> ASR["Sidecar sherpa-onnx-offline"]
+ ASR --> UI
+ UI -->|Inserir| INS["Clipboard e Ctrl+V no app em foco"]
+```
+
+O hotkey 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 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. As threads do sidecar são limitadas a 1–4.
+
+### Caminhos de transcrição
+
+| Caminho | Arquivo | Estado no código |
+|---|---|---|
+| Sidecar sherpa-onnx (local) | `transcription/sherpa_onnx.rs` | É o único chamado por `stop_recording_and_transcribe`. Procura o binário em `SHERPA_ONNX_SIDECAR`, depois em `src-tauri/binaries/sherpa-onnx-offline-`, depois no `PATH`. |
+| Sidecar CrispASR (local) | `transcription/crispasr.rs` | Adaptador que executa ` -m -f -t `. Hoje nenhum comando o instancia. O spec original recomendava compilar o `parakeet-main` do CrispASR (branch `parakeet`). |
+| API OpenAI-compatible | `transcription/openai.rs` | Adaptador de envio do WAV. `settings` guarda `mode` (`localFirst` ou `apiOnly`, padrão `apiOnly`) e o endpoint padrão `http://localhost:8022/v1/audio/transcriptions`. |
+
+### Modelos
+
+| ID | 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 (`encoder`, `decoder`, `joiner` int8 + `tokens.txt`) | ~640 MB | 25 idiomas europeus, incluindo `pt` | Padrão; recomendado para PC simples |
+| `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 |
+
+### Compatibilidade por sistema
+
+| 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 a mensagem avisa. |
+| Linux X11 | Clipboard + `xdotool key --clearmodifiers ctrl+v` | Sem `xdotool`, o texto fica copiado para colar manualmente. |
+| Linux Wayland | Só copia (suporte parcial) | Sem colagem automática: cole com `Ctrl+V`. |
+| Linux sem sessão detectada | Só copia | Cole manualmente no aplicativo desejado. |
+
+A sessão é detectada por `XDG_SESSION_TYPE`, `WAYLAND_DISPLAY` e `DISPLAY`. O método de inserção configurável é `clipboardPaste` (padrão), `keyTyping` ou `manualCopy`.
+
+## 🗂️ Estrutura
```text
-src/ Frontend TypeScript/CSS
+src/ Frontend TypeScript (app.ts, main.ts, styles.css, app.test.ts)
src-tauri/src/
- audio/ Captura de microfone e gravação WAV
- transcription/ Contratos, CrispASR sidecar e API compatível com OpenAI
- injection/ Clipboard, paste automático e fallback manual
- models/ Catálogo do modelo offline
- settings/ Configuração padrão
- tray.rs Menu da bandeja do sistema
- ui_commands.rs Comandos Tauri expostos ao frontend
- app_state.rs Estado compartilhado mínimo
+ audio/ Captura do microfone em WAV
+ transcription/ sherpa_onnx.rs, crispasr.rs, openai.rs
+ injection/ Clipboard, paste automático e fallback manual
+ models/ Catálogo e download de modelos
+ settings/ Configuração padrão
+ tray.rs shortcuts.rs ui_commands.rs app_state.rs diagnostics.rs error.rs
+src-tauri/binaries/ Sidecar sherpa-onnx-offline e DLLs onnxruntime (Windows)
+src-tauri/tests/fixtures/ Modelo ONNX grande para teste real (o clone passa de 1 GB)
+scripts/ setup-sidecar.mjs, setup-fixtures.mjs
+.github/workflows/ ci.yml, build.yml, release.yml
```
-A regra de design é manter arquivos pequenos, responsabilidades claras e zero overengineering. O app começa com contratos e stubs explícitos para as partes nativas mais arriscadas.
+## 🧪 Scripts
-## Modelo offline principal
+| Comando | O que faz |
+|---|---|
+| `npm run dev` | Vite em `127.0.0.1:1420`, só o frontend. |
+| `npm run build` | `tsc --noEmit` e `vite build`. |
+| `npm test` | `vitest` (ambiente jsdom); em modo não interativo use `npm test -- --run`, como o CI. |
+| `npm run typecheck` | `tsc --noEmit`. |
+| `npm run tauri:dev` | `tauri dev`. |
+| `npm run tauri:build` | `tauri build`. |
+| `cargo test --manifest-path src-tauri/Cargo.toml` | Testes Rust. |
+| `node scripts/setup-sidecar.mjs` | Baixa o release `*-shared` do sherpa-onnx e extrai `sherpa-onnx-offline` para `src-tauri/binaries/`. Plataformas: Linux x64/arm64, macOS, Windows x64. |
+| `node scripts/setup-fixtures.mjs` | Baixa `parakeet-sample.wav` para `src-tauri/tests/fixtures/`. |
-- Repositório: `cstr/parakeet-tdt-0.6b-v3-GGUF`
-- Arquivo: `parakeet-tdt-0.6b-v3-q8_0.gguf`
-- Quantização: `Q8_0`
-- Tamanho registrado no catálogo: `745121600` bytes
-- Modelo base: NVIDIA Parakeet TDT 0.6B v3
-- Idioma: detecção automática; português incluído no conjunto suportado pelo modelo base.
+### Workflows (`.github/workflows/`)
-O modelo não deve ser embutido no instalador principal. A estratégia recomendada é instalar o app leve e baixar o GGUF pelo gerenciador de modelos.
+| Arquivo | Gatilho | O que faz |
+|---|---|---|
+| `ci.yml` | PR e push em `main` | Em `ubuntu-22.04` com Node 22: `npm ci`, `typecheck`, `npm run test -- --run`, `build` e `cargo test`. Depois prepara sidecar, fixture e modelo, e roda o teste real de transcrição com `--ignored`. |
+| `build.yml` | Push em `main` e manual | Matriz `windows-latest` e `ubuntu-22.04`: `npm run tauri:build` e upload de `src-tauri/target/release/bundle/**/*` (`windows-bundles`, `linux-bundles`). |
+| `release.yml` | Tag `v*.*.*` e manual (input `tag`) | `tauri-apps/tauri-action@v0` nas mesmas duas plataformas; publica a GitHub Release `Transcript `, sem rascunho e sem pré-release. |
-## Sidecar CrispASR
+## 📚 Documentação
-O app chama por padrão o binário `parakeet-main` com:
+- [Design do app](docs/superpowers/specs/2026-06-10-transcription-app-design.md)
+- [sherpa-onnx como sidecar](docs/superpowers/specs/2026-06-11-sherpa-onnx-sidecar.md)
+- [Redesign do frontend](docs/superpowers/specs/2026-08-08-frontend-redesign-design.md)
+- Planos: [MVP](docs/superpowers/plans/2026-06-10-transcription-app-mvp.md), [integrações nativas](docs/superpowers/plans/2026-06-10-transcription-app-native-integrations.md), [redesign](docs/superpowers/plans/2026-08-08-frontend-redesign.md)
+- Tauri: [commands](https://v2.tauri.app/develop/calling-rust), [system tray](https://v2.tauri.app/learn/system-tray), [sidecars](https://v2.tauri.app/develop/sidecar), [pipelines GitHub](https://v2.tauri.app/distribute/pipelines/github), [pré-requisitos Linux](https://v2.tauri.app/start/prerequisites)
+- Modelos: [NVIDIA Parakeet v3](https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3/blob/main/README.md), [cstr GGUF](https://huggingface.co/cstr/parakeet-tdt-0.6b-v3-GGUF)
+
+## 🛣️ Limitações e próximos passos
+
+- **whisper.cpp:** só aparece no spec do redesign, e `bundle.resources` aponta para `resources/whisper/`, pasta que não existe no repositório. Não há código nem modelo Whisper no catálogo; `whisper-1` é só um exemplo de nome de modelo na API.
+- O app ainda não escolhe o caminho de transcrição por `mode`: `stop_recording_and_transcribe` sempre usa o sherpa-onnx.
+- `tauri.conf.json` não declara `bundle.externalBin`, embora o spec preveja o sidecar empacotado no instalador.
+- Divergências vistas na leitura do código, que não foi compilado: o frontend invoca `stop_recording`, `transcribe_pending`, `minimize_window`, `close_window`, `save_openai_api_key` e `clear_openai_api_key`, ausentes do `invoke_handler` de `lib.rs`; `openai.rs` importa `crate::secrets`, que `lib.rs` não declara; `ui_commands.rs` lê `settings.transcription.model_id` e `settings` usa `shortcuts::DEFAULT_HOTKEY`, e nenhum dos dois existe.
+- O hotkey `Ctrl+Shift+Space` é fixo em `shortcuts.rs`, e o item Iniciar gravação da bandeja só mostra a janela.
+- O catálogo aponta para o modelo `v2-int8`, mas o `ci.yml` baixa o `v3-int8` (~670 MB) e cita o teste `real_transcription_returns_known_text`, que não está em `sherpa_onnx.rs`.
+- As versões divergem: `0.1.0` em `package.json` e `Cargo.toml`, `0.3.1` em `tauri.conf.json`.
+
+## 🤝 Contribuindo
+
+Mantenha módulos pequenos, com responsabilidades claras. Antes de abrir o PR, estes comandos devem passar:
```bash
-parakeet-main -m -f -t
+npm run typecheck && npm test -- --run && cargo test --manifest-path src-tauri/Cargo.toml
```
-Para o modelo v3, o projeto CrispASR recomenda compilar o target `parakeet-main` no branch `parakeet`. O app limita automaticamente o número de threads a no máximo 4 para manter compatibilidade com PCs simples.
+## 📄 Licença
-Enquanto o binário não estiver no `PATH` ou empacotado como sidecar, a transcrição local retorna erro claro após a gravação.
-
-## Compatibilidade Windows/Linux
-
-- Windows: clipboard + tentativa de `Ctrl+V` via `SendKeys`.
-- Linux X11: clipboard + tentativa de `Ctrl+V` via `xdotool` quando instalado.
-- Linux Wayland: suporte parcial por limitação de segurança dos compositors. O fallback seguro é copiar o texto e orientar o usuário a colar manualmente.
-
-## Comandos locais
-
-```bash
-npm install
-npm run typecheck
-npm run test -- --run
-npm run build
-cargo test --manifest-path src-tauri/Cargo.toml
-npm run tauri:build
-```
-
-## CI/CD
-
-Workflows:
-
-- `.github/workflows/ci.yml`: valida PRs e pushes em `main`.
-- `.github/workflows/build.yml`: gera bundles Windows/Linux em push para `main` e manualmente.
-- `.github/workflows/release.yml`: publica GitHub Releases em tags `v*.*.*`.
-
-A lógica fica em comandos npm/cargo para facilitar migração futura para GitLab CI.
-
-## Fontes técnicas usadas
-
-- Tauri 2 commands: https://v2.tauri.app/develop/calling-rust
-- Tauri 2 system tray: https://v2.tauri.app/learn/system-tray
-- Tauri 2 sidecars: https://v2.tauri.app/develop/sidecar
-- Tauri GitHub pipelines: https://v2.tauri.app/distribute/pipelines/github
-- Tauri Linux prerequisites: https://v2.tauri.app/start/prerequisites
-- NVIDIA Parakeet v3 model card: https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3/blob/main/README.md
-- cstr Parakeet GGUF: https://huggingface.co/cstr/parakeet-tdt-0.6b-v3-GGUF
+Sem licença definida — todos os direitos reservados.