[ POR DENTRO ]
Como ele é feito
O Yummi cabe em cinco dependências e nenhuma delas é pesada. O que ele faz de mais incomum — capturar o áudio de um processo só — é feito em ctypes puro, porque a API não tem biblioteca em Python.
Camadas
Só a pasta ui/ conhece o Tkinter e só a audio/ conhece o PortAudio. É por isso que o resto roda nos testes sem placa de som e sem tela.
yummi/audio/devices.pydescoberta e escolha de dispositivosyummi/audio/loader.pydecodificação, reamostragem, normalizaçãoyummi/audio/player.pyreprodução em várias saídas e a ponte ao vivoyummi/audio/loopback.pycaptura por processo (WASAPI process loopback)yummi/tts/motores de síntese, reserva automática e cacheyummi/ui/a janela Tkinter e o tema preto e brancoyummi/library.pya biblioteca de clipesyummi/files.pya varredura da pasta de áudiosyummi/config.pypreferências em JSONyummi/hotkeys.pyatalhos globais (prontos, desligados)
As cinco dependências
numpy
as contas em cima das amostras
sounddevice
a ponte com as placas de som, via PortAudio
soundfile
decodifica MP3 e companhia direto da memória, pela libsndfile
edge-tts
as vozes neurais da Microsoft
gTTS
a reserva, quando a primeira não responde
O ffmpeg, o pydub e o scipy ficaram para trás na versão 3. O pydub tinha parado de funcionar no Python 3.13, quando o módulo audioop saiu da biblioteca padrão.
A captura por janela
ActivateAudioInterfaceAsync
AUDIOCLIENT_ACTIVATION_TYPE_PROCESS_LOOPBACK
PROCESS_LOOPBACK_MODE_INCLUDE_TARGET_PROCESS_TREE
O Windows expõe o áudio de um processo por ActivateAudioInterfaceAsync, com parâmetros de process loopback. É uma API de C e COM, sem binding em Python: as interfaces são chamadas em ctypes, pela posição de cada método na tabela de funções, e o objeto que recebe o retorno assíncrono é montado à mão em Python. Fora do Windows o módulo importa normalmente e só a captura recusa, com recado.
A escolha fica salva pelo nome do executável, não pelo identificador do processo: fechar e reabrir o Brave não perde a configuração.
Onde ficam os arquivos
Nada é gravado dentro do repositório. Preferências, clipes e cache moram na pasta do usuário:
Apagar essa pasta devolve o programa ao estado de recém-instalado, sem desinstalar nada.
%APPDATA%\Yummi\ ├── config.json saídas, voz, pasta de áudios, origem da ponte ├── clipes/ a biblioteca + biblioteca.json └── cache/ as falas já sintetizadas
Testes
São 157 testes rodando em quatro versões do Python a cada push, mais o ruff no mesmo passo. Os que dependem de placa de som são pulados no servidor, e a interface é testada com uma raiz Tk de mentira.
157
pytest
4
3.10 → 3.13
MIT
licença