Muninn

Faça seu agente iniciar a ditadura (apenas OSX)

Documentação

muninn

Crates.io Version CI CodSpeed Crates.io Downloads License Discord Buymecoffee

Ditado nativo de macOS na barra de menus, feito para texto de desenvolvedores.

Muninn grava a fala, transcreve, processa a transcrição por um pipeline de texto configurável e injeta o texto final no aplicativo ativo. O pipeline padrão é projetado para ditado próximo a código: comandos, flags, nomes de pacotes, caminhos de arquivos, variáveis de ambiente, siglas e outros tokens que o ditado de uso geral frequentemente altera.

Muninn menu-bar dictation screenshot

Conteúdo

O que o Muninn faz

Fluxo padrão no modo de gravação:

hotkey or tray click
-> record temporary WAV
-> resolve transcription provider route
-> transcribe with the first usable provider
-> run the refine step
-> run optional external filters
-> inject final text into the active app

O Muninn inclui:

  • um aplicativo de barra de menus do macOS com indicador de bandeja ao vivo
  • atalhos globais para push-to-talk, alternância do modo concluído e cancelamento
  • captura de microfone para um WAV temporário, padrão de 16 kHz mono
  • uma rota de transcrição local-first entre Apple Speech, whisper.cpp, Deepgram, OpenAI, Google e SpaceXAI (xAI) com transcrição gravada
  • um modo de streaming opcional para provedores que suportam transcrição ao vivo neste código
  • uma etapa refine integrada que aplica um prompt conservador de ditado para desenvolvedores (OpenAI ou SpaceXAI / xAI)
  • suporte a filtros Unix externos para etapas personalizadas do pipeline
  • injeção de texto por eventos de teclado no aplicativo atual
  • controle externo opcional por URLs muninn:// e um servidor MCP em localhost
  • artefatos de reprodução opcionais para depuração de enunciados

Controles padrão:

AçãoPadrão
Push-to-talkctrl com gatilho double_tap e janela de toque duplo de 300 ms
Alternância do modo concluídoctrl + shift + d
Cancelar captura ativactrl + shift + x
Clique esquerdo na bandejaAlternar: iniciar quando ocioso, parar quando gravando

Alterações de atalhos são lidas da configuração, mas o recarregamento ao vivo da configuração não substitui os atalhos ativos. Reinicie o Muninn após alterar os atalhos.

Início rápido

Use este caminho quando quiser executar o Muninn a partir deste repositório.

Pré-requisitos

  • macOS
  • Rust 1.88.0 ou mais recente
  • Ferramentas de linha de comando do Xcode para builds locais
  • Permissões do macOS para Microfone, Acessibilidade e Monitoramento de Entrada
  • Chaves opcionais de provedores em nuvem ao usar Deepgram, OpenAI, Google, SpaceXAI (xAI) ou uma etapa refine com suporte em nuvem

1. Compilar o binário

cargo build --release --bin muninn

2. Criar um arquivo de configuração

O Muninn lê a configuração nesta ordem:

  1. MUNINN_CONFIG
  2. $XDG_CONFIG_HOME/muninn/config.toml
  3. ~/.config/muninn/config.toml

Se o arquivo de configuração resolvido estiver ausente, o Muninn cria uma configuração padrão inicializável. Para começar pela configuração de exemplo:

CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/muninn"
mkdir -p "$CONFIG_DIR"
cp configs/config.sample.toml "$CONFIG_DIR/config.toml"

3. Definir credenciais quando necessário

O Muninn carrega ./.env do diretório de trabalho atual por padrão. Variáveis de ambiente existentes do shell substituem .env e valores de configuração.

Crie .env apenas com as chaves que você usa:

OPENAI_API_KEY=<OPENAI_API_KEY>
DEEPGRAM_API_KEY=<DEEPGRAM_API_KEY>
GOOGLE_API_KEY=<GOOGLE_API_KEY>
GOOGLE_STT_TOKEN=<GOOGLE_STT_TOKEN>
XAI_API_KEY=<XAI_API_KEY>

Defina MUNINN_LOAD_DOTENV=0, false ou no para desativar o carregamento de .env.

4. Executar o aplicativo de bandeja

cargo run --release --bin muninn

Resultado esperado: o Muninn aparece na barra de menus do macOS com um indicador de bandeja M.

5. Conceder permissões e verificar

Conceda estas permissões ao próprio Muninn:

PermissãoPor que o Muninn precisaCaminho nas Configurações do Sistema
MicrofoneGravar sua falaPrivacidade e Segurança > Microfone
AcessibilidadeInjetar texto final no aplicativo ativoPrivacidade e Segurança > Acessibilidade
Monitoramento de EntradaOuvir atalhos globais enquanto outro aplicativo está ativoPrivacidade e Segurança > Monitoramento de Entrada

Para verificar o aplicativo:

  1. Foque um campo de texto em outro aplicativo.
  2. Clique no ícone de bandeja do Muninn para iniciar a gravação.
  3. Fale uma frase curta.
  4. Clique no ícone de bandeja novamente para parar a gravação.

Resultado esperado: o Muninn transcreve o enunciado, executa o pipeline e digita o texto final no aplicativo focado.

Se o macOS parar de mostrar o prompt de permissão, redefina o serviço TCC afetado e reinicie o Muninn:

tccutil reset ListenEvent
tccutil reset Accessibility
tccutil reset Microphone

Instalar e executar

Instalar a partir do crates.io

cargo install muninn-speech-to-text
muninn

O nome do pacote é muninn-speech-to-text; o nome do binário é muninn.

Executar a partir da configuração de exemplo

MUNINN_CONFIG="$PWD/configs/config.sample.toml" cargo run --release --bin muninn

Isso é útil para desenvolvimento local, pois evita alterar sua configuração de usuário.

Instalar um binário de versão

O fluxo de trabalho de versão compila arquivos tar para:

  • aarch64-apple-darwin
  • x86_64-apple-darwin

Após extrair um arquivo de versão, mantenha o binário em um caminho estável antes de conceder permissões do macOS:

mkdir -p "$HOME/.local/bin"
mv muninn "$HOME/.local/bin/muninn"
chmod +x "$HOME/.local/bin/muninn"
"$HOME/.local/bin/muninn"

As permissões do macOS são vinculadas à identidade exata do aplicativo ou binário. Mover ou substituir um binário bruto pode exigir conceder permissões novamente.

Compilar um pacote .app local

Use o pacote de aplicativo quando quiser uma identidade de aplicativo estável, tratamento de URL muninn:// e comportamento normal de Itens de Login.

cargo build --release --bin muninn
bash scripts/package-macos-app.sh
open dist/Muninn.app

O script de empacotamento cria dist/Muninn.app, assina ad hoc por padrão e cria dist/Muninn.app.zip quando ditto está disponível. Defina CODESIGN_IDENTITY para usar um certificado Developer ID, ou defina CODESIGN_APP=0 para pular a assinatura.

Configuração recomendada do pacote de aplicativo:

  1. Mova dist/Muninn.app para /Applications/Muninn.app.
  2. Inicie uma vez e conceda permissões a Muninn.
  3. Adicione em Configurações do Sistema > Geral > Itens de Login.
  4. Mantenha [app].autostart = false ao usar Itens de Login.

O Finder e os Itens de Login não herdam o ambiente do seu shell. Armazene credenciais na configuração ou certifique-se de que o diretório de trabalho do Muninn contenha o arquivo .env que você espera que ele leia.

Ativar inicialização automática de binário bruto

Defina [app].autostart = true para permitir que o Muninn grave um LaunchAgent para o caminho do executável atual.

Comportamento:

  • O Muninn grava ~/Library/LaunchAgents/com.bnomei.muninn.plist quando inicia ou recarrega a configuração.
  • As alterações entram em vigor no próximo login do macOS.
  • O LaunchAgent inclui MUNINN_CONFIG.
  • O LaunchAgent não herda exportações interativas do shell.
  • Ao usar Muninn.app, prefira Itens de Login do macOS em vez deste caminho de LaunchAgent de binário bruto.

Configurar o Muninn

O exemplo canônico está em configs/config.sample.toml. O esquema raiz está em src/config.rs.

Seções importantes da configuração

SeçãoFinalidade
[app]Perfil padrão, contrato estrito de etapas, inicialização automática de binário bruto
[hotkeys.*]Atalhos de push-to-talk, alternância do modo concluído e cancelamento
[indicator]Visibilidade e cores do indicador de bandeja
[recording]Formato de captura WAV e pós-processamento opcional de tempo com FFmpeg; padrão mono, 16 kHz e postprocess_speed = 1.0
[transcription]Modo gravado versus streaming e rota ordenada de provedores
[pipeline]Prazo do pipeline, formato de payload e etapas pós-transcrição
[transcript]Prompt base e texto de anexo de prompt para a etapa de refinamento integrada
[refine]Provedor de refinamento (openai ou xai), endpoint, modelo, temperatura e proteções
[voices.*]Comportamento de refinamento nomeado e glifo opcional de um caractere na bandeja
[profiles.*]Substituições específicas de contexto para gravação, rota, pipeline, transcrição ou refinamento
[[profile_rules]]Correspondências ordenadas para o aplicativo em primeiro plano e título da janela
[external_control]Esquema de URL e configurações de controle de gravação via MCP
[logging]Artefatos de reprodução, retenção e detalhes de depuração
[providers.*]Credenciais de provedores, endpoints, modelos e configurações de streaming

Pós-processamento de tempo do WAV gravado

Defina uma velocidade acima de 1.0 para pós-processar cada captura concluída com FFmpeg antes que um provedor gravado a leia. O filtro preserva o tom:

[recording]
postprocess_speed = 2.0

O padrão, 1.0, deixa o WAV finalizado inalterado. Valores de 1.0 a 16.0 são aceitos; valores acima de 2× são expressos como múltiplos estágios atempo do FFmpeg para evitar o comportamento de pular amostras do filtro em um único fator alto. O Muninn precisa de ffmpeg em PATH quando o valor configurado está acima de 1.0 (por exemplo, brew install ffmpeg); se indisponível, a bandeja pisca em estado de erro vermelho e a captura é descartada. Provedores de streaming ainda recebem quadros de captura ao vivo em velocidade normal; o WAV pós-processado é usado para transcrição gravada, fallback e reprodução após o término da captura.

Rota de provedores

A rota padrão de provedores é local-first:

[transcription]
providers = ["apple_speech", "whisper_cpp", "deepgram", "openai", "google", "xai"]

Perfis podem substituir apenas a rota:

[profiles.mail.transcription]
providers = ["deepgram", "openai", "google", "xai"]

Se você ainda tiver etapas stt_* explícitas em pipeline.steps, o Muninn as aceita e infere a rota dessa ordem. Novas configurações devem preferir [transcription].providers.

Etapas do pipeline

Cada etapa do pipeline tem:

  • id
  • cmd
  • args opcional
  • io_mode opcional
  • timeout_ms
  • on_error

Valores suportados de io_mode:

ValorComportamento
autoIntegrados usam JSON de envelope; comandos externos usam filtragem de texto por padrão
envelope_jsonA etapa lê e grava o envelope JSON completo
text_filterA etapa lê o texto da transcrição e grava texto de substituição

Valores suportados de on_error:

ValorComportamento
continueManter o envelope anterior e executar etapas posteriores
fallback_rawSubstituir transcript.raw_text e continuar
abortParar o pipeline e exibir a falha

Exemplo:

[transcription]
providers = ["apple_speech", "whisper_cpp", "deepgram", "openai", "google", "xai"]

[[pipeline.steps]]
id = "refine"
cmd = "refine"
timeout_ms = 2500
on_error = "continue"

[[pipeline.steps]]
id = "uppercase"
cmd = "/usr/bin/tr"
args = ["[:lower:]", "[:upper:]"]
timeout_ms = 250
on_error = "continue"

Dicas de prompt de refinamento

transcript.system_prompt e transcript.system_prompt_append orientam a etapa refine integrada. Eles não alteram o provedor de fala para texto, e o Muninn não analisa JSON anexado em APIs de adaptação nativas do provedor.

[transcript]
system_prompt = "Prefer minimal corrections. Focus on technical terms, developer tools, package names, commands, flags, file names, paths, env vars, acronyms, and obvious dictation errors. If uncertain, keep the original wording."
system_prompt_append = """
Vocabulary JSON:
{"terms":["Muninn","whisper.cpp","Deepgram","Cargo.toml"],"commands":["cargo test --all-targets","rg --files"],"paths":["src/config.rs",".env"]}
"""

Provedores de transcrição

ProviderModo gravadoModo streamingCredenciaisObservações
Apple SpeechSimNãoNenhumaProvedor local para macOS 26+. Usa os recursos de Speech gerenciados pela Apple para o idioma selecionado.
whisper.cppSimNãoNenhumaProvedor local. Padrão para tiny.en, armazenado em ~/.local/share/muninn/models, com device = "auto".
DeepgramSimSimDEEPGRAM_API_KEY ou providers.deepgram.api_keyUploads gravados usam /v1/listen; streaming usa a API WebSocket ao vivo.
OpenAISimSimOPENAI_API_KEY ou providers.openai.api_keyUploads gravados são pré-validados contra o limite de áudio de 25 MB da OpenAI; streaming usa transcrição em tempo real.
GoogleSimNão chamável atualmenteGOOGLE_API_KEY, GOOGLE_STT_TOKEN ou valores de configuraçãoA transcrição REST gravada funciona pelo endpoint configurado. O adaptador de streaming do Google constrói solicitações Speech-to-Text v2, mas a dependência fixada google-cloud-speech-v2 1.12.0 não expõe uma RPC de streaming chamável, então o Muninn relata google_official_client_streaming_rpc_unavailable.
SpaceXAI (xAI)SimSimXAI_API_KEY ou providers.xai.api_keyID de configuração xai, etapa stt_xai. Uploads gravados usam POST https://api.x.ai/v1/stt (multipart; sem campo STT model). Streaming usa wss://api.x.ai/v1/stt com autenticação Bearer, PCM mono de 16 kHz e handshake transcript.created. Opcionais language, format, keyterm, diarize, filler_words e vad_threshold em [providers.xai]. Substituições por variáveis de ambiente: XAI_STT_ENDPOINT, XAI_STT_STREAMING_ENDPOINT, XAI_STT_LANGUAGE.

A etapa refine não é um provedor de STT. Ela usa a configuração [refine] e HTTP compatível com chat-completions por padrão (provider = "openai"). Defina provider = "xai" para refinar com SpaceXAI / xAI (https://api.x.ai/v1/chat/completions, modelo grok-4.5 por padrão). Definir apenas o provedor alterna endpoint e modelo para os padrões do fornecedor, para que uma chave xAI nunca seja enviada a uma URL da OpenAI.

Variáveis de ambiente

AssuntoVariáveis
Caminho de configuraçãoMUNINN_CONFIG
Carregamento de .envMUNINN_LOAD_DOTENV
DeepgramDEEPGRAM_API_KEY, DEEPGRAM_STT_ENDPOINT, DEEPGRAM_STT_MODEL, DEEPGRAM_STT_LANGUAGE, MUNINN_DEEPGRAM_STUB_TEXT
Transcrição e refinamento OpenAIOPENAI_API_KEY, MUNINN_OPENAI_STUB_TEXT, MUNINN_REFINE_STUB_TEXT
Transcrição gravada GoogleGOOGLE_API_KEY, GOOGLE_STT_TOKEN, GOOGLE_STT_ENDPOINT, GOOGLE_STT_MODEL, MUNINN_GOOGLE_STUB_TEXT
Transcrição e refinamento SpaceXAI (xAI)XAI_API_KEY, XAI_STT_ENDPOINT, XAI_STT_STREAMING_ENDPOINT, XAI_STT_LANGUAGE, MUNINN_XAI_STT_STUB_TEXT, MUNINN_REFINE_STUB_TEXT

Variáveis simuladas (stub) são destinadas a verificações locais rápidas e testes. Elas ignoram chamadas reais ao provedor para a etapa correspondente.

Ciclo de vida do modelo whisper.cpp

Comportamento padrão:

  • providers.whisper_cpp.model não definido resolve para tiny.en
  • tiny.en resolve para ggml-tiny.en.bin
  • diretório de modelo padrão é ~/.local/share/muninn/models
  • Muninn baixa automaticamente modelos canônicos conhecidos no primeiro uso
  • caminhos de modelos personalizados explícitos devem já existir
  • device = "auto" usa Metal em builds Apple Silicon compatíveis e CPU caso contrário

Pré-aqueça o cache do modelo padrão:

mkdir -p "$HOME/.local/share/muninn/models"
curl -L \
  -o "$HOME/.local/share/muninn/models/ggml-tiny.en.bin" \
  "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.en.bin"

Se uma rota somente local apontar para um modelo personalizado ausente, o Muninn registra um diagnóstico missing_whisper_cpp_model e não injeta nada, a menos que outro provedor produza transcript.raw_text posteriormente.

Modelo de pipeline

O Muninn passa um envelope por todas as etapas internas e externas. Etapas internas de STT preenchem transcript.raw_text; etapas de transformação, como refine, escrevem output.final_text. A injeção prefere output.final_text e pode recorrer a transcript.raw_text.

Comandos de etapas internas:

ComandoFinalidade
stt_apple_speechTranscrição Apple Speech de gravação concluída
stt_whisper_cppTranscrição local whisper.cpp de gravação concluída
stt_deepgramTranscrição Deepgram de gravação concluída
stt_openaiTranscrição OpenAI de gravação concluída
stt_googleTranscrição Google REST de gravação concluída
stt_xaiTranscrição SpaceXAI / xAI de gravação concluída
refineLimpeza de ditado do desenvolvedor via chat-completions (openai ou xai)

Execute uma etapa interna diretamente para verificações rápidas:

cargo run -q -- __internal_step <stt_apple_speech|stt_whisper_cpp|stt_deepgram|stt_openai|stt_google|stt_xai|refine>

Use os fixtures JSON em tests/fixtures para exemplos de envelopes de entrada.

Transcrição em streaming

O modo gravado é o padrão. Habilite o streaming explicitamente:

[transcription]
mode = "streaming"
providers = ["deepgram", "openai", "xai"]

[transcription.streaming]
frame_ms = 100
finish_timeout_ms = 10000
fallback_to_recorded_on_error = true

Comportamento do streaming:

  • O streaming Deepgram envia áudio LINEAR16 mono via WebSocket.
  • O streaming OpenAI usa transcrição em tempo real e força captura mono de 24 kHz para essa elocução.
  • O streaming SpaceXAI / xAI usa wss://api.x.ai/v1/stt com Bearer XAI_API_KEY, aguarda transcript.created, envia quadros PCM mono de 16 kHz e finaliza com audio.done. Quando xAI é o provedor de streaming ativo, o Muninn força captura mono de 16 kHz para essa elocução.
  • O streaming Google não é chamável atualmente porque a dependência fixada google-cloud-speech-v2 1.12.0 expõe tipos de solicitação e resposta, mas nenhum método de streaming chamável.
  • O Muninn ainda grava o WAV concluído durante o streaming.
  • Quando o streaming falha e fallback_to_recorded_on_error = true, o Muninn pode executar a rota de WAV concluído.
  • Uma transcrição de streaming bem-sucedida alimenta transcript.raw_text; refine, pontuação, reprodução e injeção usam o mesmo pipeline downstream do modo gravado.
  • Resultados intermediários de streaming são transitórios. O Muninn não mostra uma interface de transcrição parcial nem persiste histórico de transcrição parcial.

Perfis contextuais e vozes

O Muninn pode alterar o comportamento de refinamento com base no aplicativo em primeiro plano. Ele captura o ID do bundle, o nome do aplicativo e um título de janela de melhor esforço, e então aplica a primeira entrada profile_rules correspondente. Se nenhuma regra corresponder, o comportamento recai em [app].profile; o glifo da bandeja ociosa recai em M.

Ordem de resolução:

  1. Comece pela configuração base.
  2. Aplique a voz correspondente, se o perfil correspondente nomear uma.
  3. Aplique as substituições do perfil por último.

Voz significa comportamento de modelagem de texto mais um glifo opcional de bandeja, não uma voz de áudio.

[app]
profile = "default"

[voices.codex]
indicator_glyph = "C"
system_prompt = "Prefer terse developer dictation. Keep commands, flags, file names, and code tokens intact."
system_prompt_append = """
Vocabulary JSON:
{"terms":["Codex","Muninn","Cargo.toml"],"commands":["cargo test --all-targets","cargo clippy --all-targets -- -D warnings"]}
"""

[voices.terminal]
indicator_glyph = "T"
system_prompt = "Preserve shell commands exactly. Prefer minimal punctuation changes."

[profiles.codex]
voice = "codex"

[profiles.terminal]
voice = "terminal"

[[profile_rules]]
id = "codex-app"
profile = "codex"
app_name = "Codex"

[[profile_rules]]
id = "terminal-app"
profile = "terminal"
bundle_id = "com.apple.Terminal"

Comportamento da bandeja:

  • a pré-visualização ociosa mostra o glifo da voz correspondente, ou M
  • gravação e processamento congelam o glifo resolvido para essa elocução
  • ? é reservado para feedback de credenciais ausentes

Controle externo

O Muninn pode ser controlado por agentes e scripts por meio de dois transportes:

  • esquema de URL muninn://, disponível para o .app macOS empacotado
  • servidor MCP HTTP streamable em localhost, desabilitado por padrão

Ambos os transportes usam o mesmo vocabulário de controle de gravação dos eventos de bandeja e atalho.

[external_control]
url_scheme_enabled = true
mcp_enabled = false
start_recording_enabled = false
mcp_bind_address = "127.0.0.1:2769"

Semântica de ações:

AçãoComportamento
startInicia a gravação somente quando ocioso e start_recording_enabled = true
stopInterrompe uma gravação ativa e executa o pipeline; sem efeito quando ocioso
toggleInicia quando ocioso e permitido; caso contrário, interrompe uma gravação ativa
cancelDescarta uma gravação ativa sem transcrição ou injeção

O início externo é desabilitado por padrão porque inicia a captura do microfone. Habilitar start_recording_enabled = true é a decisão de confiança local para agentes e scripts configurados.

Esquema de URL

O .app empacotado registra muninn:// por meio de CFBundleURLTypes.

URLAção
muninn://record, muninn://startiniciar
muninn://stop, muninn://doneparar
muninn://togglealternar
muninn://cancel, muninn://abortcancelar
open "muninn://record"

Um binário iniciado com cargo run não recebe esses links do LaunchServices.

Servidor MCP

Quando mcp_enabled = true, o Muninn serve MCP em:

http://127.0.0.1:2769/mcp

Ferramentas:

  • get_status
  • start_recording
  • stop_recording
  • cancel_recording

Exemplo de registro com um cliente compatível com MCP:

auggie mcp add muninn --transport http --url http://127.0.0.1:2769/mcp

get_status é somente leitura e retorna JSON como:

{
  "state": "idle",
  "recording_active": false,
  "busy": false,
  "permissions": {
    "microphone": "granted",
    "accessibility": "granted",
    "input_monitoring": "granted"
  }
}

state é um de idle, recording_active, permission_blocked, already_running ou failed.

Restrições de segurança:

  • O servidor MCP não tem autenticação.
  • mcp_bind_address deve ser um endereço de socket loopback explícito, como 127.0.0.1:2769 ou [::1]:2769.
  • O Muninn recusa binds curinga, LAN, hostname e outros não loopback.
  • O servidor MCP inicia somente na inicialização do aplicativo. Alterar mcp_enabled depois exige reiniciar o Muninn.

Privacidade, reprodução e depuração

Logs de rastreamento vão para stderr e são controlados com RUST_LOG.

RUST_LOG=recording=debug cargo run --release --bin muninn

O log de reprodução é desabilitado por padrão. Quando habilitado:

  • replay_detail = "minimal" armazena apenas metadados esparsos de elocução
  • replay_detail = "full_debug" armazena configuração redigida, contexto de destino, envelopes finais, resultado do pipeline, contexto de refinamento e rota de injeção
  • replay_retain_audio = true mantém áudio somente quando replay_detail = "full_debug"
  • áudio retido usa hard link quando possível e recorre a cópia
  • snapshots de depuração completa redigem segredos do provedor e campos de prompt
  • artefatos de reprodução são para inspeção, não para reexecução
[logging]
replay_enabled = true
replay_detail = "minimal"
replay_retain_audio = false
replay_dir = "~/.local/state/muninn/replay"
replay_retention_days = 7
replay_max_bytes = 52428800

Verificações comuns de recuperação:

SintomaVerificação
Atalho não inicia a gravaçãoConceda Monitoramento de Entrada ao Muninn e reinicie após alterar a configuração do atalho
Clique na bandeja grava, mas o atalho nãoMonitoramento de Entrada ausente ou o ouvinte de atalho precisa ser reiniciado
Texto não é injetadoConceda Acessibilidade ao Muninn
Nenhum texto é injetado após uma rota Whisper somente localVerifique missing_whisper_cpp_model e confirme o caminho do modelo configurado
Início externo via MCP é rejeitadoDefina external_control.start_recording_enabled = true e reinicie se o servidor MCP não foi habilitado na inicialização
Streaming Google recai ou relata indisponívelUse transcrição Google gravada, streaming Deepgram, streaming OpenAI ou streaming xAI
SpaceXAI / xAI sem credenciaisDefina XAI_API_KEY ou providers.xai.api_key; para refinamento, defina também [refine] provider = "xai"

Desenvolvimento

Execute as verificações principais:

cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets

O repositório também inclui hooks prek:

prek validate-config
prek run --all-files
prek install

Execute a suíte de benchmarks:

cargo bench --bench runtime_bottlenecks

Filtre para um grupo de benchmark:

cargo bench --bench runtime_bottlenecks pipeline_runner
cargo bench --bench runtime_bottlenecks replay_persist

O alvo do benchmark foca em caminhos de latência por elocução que não exigem chamadas de rede:

  • transformação e reamostragem de saída de áudio
  • idas e voltas JSON de envelope
  • construção do corpo de solicitação do Google
  • resolução de perfil e voz
  • pontuação de substituição
  • sobrecarga do executor de pipeline em processo
  • persistência de reprodução com e sem artefatos de áudio retidos

Limitações atuais

  • O runtime suportado do Muninn é macOS.
  • Apple Speech exige macOS 26+ e recursos de Speech gerenciados pela Apple.
  • whisper.cpp e Apple Speech são provedores somente de gravação concluída.
  • A construção de solicitação de streaming Google existe, mas o streaming Google ao vivo não é chamável até que o cliente oficial fixado exponha uma RPC de streaming.
  • O modo streaming usa apenas o texto final do provedor. Não há interface de transcrição parcial.
  • Artefatos de reprodução são para inspeção, não reprodução determinística.
  • Transcrição baseada em provedor precisa de orçamentos de tempo limite realistas.
  • O servidor MCP de controle externo não tem autenticação, é desabilitado por padrão, faz bind somente em loopback e inicia apenas na inicialização do aplicativo.
  • O fluxo de release do repositório empacota binários brutos; use o script de empacotamento local quando precisar de um bundle .app.

Mapa de fontes

Use estes arquivos ao verificar afirmações do README contra o código-fonte:

ÁreaFonte
Metadados do pacote e MSRVCargo.toml
Configuração de exemploconfigs/config.sample.toml
Esquema de configuração e padrõessrc/config.rs, src/config/logging.rs
Vocabulário do provedor e rota padrãosrc/transcription.rs
Executor de pipeline e componentes integradossrc/runner.rs, src/internal_tools.rs
Provedor Apple Speechsrc/stt_apple_speech_tool.rs, src/apple_speech_transcriber.swift
Provedor whisper.cppsrc/stt_whisper_cpp_tool.rs
Provedor Deepgramsrc/stt_deepgram_tool.rs, src/streaming_transcription/deepgram.rs
Provedor OpenAI e refinesrc/stt_openai_tool.rs, src/streaming_transcription/openai.rs, src/refine.rs
Provedor SpaceXAI / xAI e refinesrc/stt_xai_tool.rs, src/streaming_transcription/xai.rs, src/refine.rs
Provedor Googlesrc/stt_google_tool.rs, src/streaming_transcription/google.rs
Atalhos de teclado, bandeja e fluxo de execuçãosrc/hotkeys.rs, src/runtime_tray.rs, src/runtime_flow.rs
Permissões do macOSsrc/runtime_permissions.rs, src/permissions.rs
Controle externosrc/external_control.rs, src/external_control/action.rs, src/external_control/mcp.rs, src/external_control/url_scheme.rs
Scripts de empacotamento e releasescripts/package-macos-app.sh, scripts/package-release.sh, .github/workflows/release.yml