ezequias.rocha / sessão de transcrição

Ezequias Rocha

Foto de Ezequias Rochafalante 1
faster-whisper-small em 127.0.0.1

[00:00.4]Oi. Eu sou o Ezequias Rocha, analista de sistemas e pesquisador no Laboratório de Sistemas de Informação da UFCG, em Campina Grande.

[00:08.6]Sou bacharel em Ciência da Computação pela UFCG e estou no mestrado.

[00:12.9]Replico paper de IA em PyTorch, escrevo API com lint e cobertura de teste desde o primeiro commit e já gravei vídeo resolvendo questão de algoritmo para turma de iniciante.

[00:23.0]Em 2026 corrigi um bug do turbo-whisper que, em teclado ABNT, trocava o apóstrofo por til. O resto desta página é sobre esse bug e sobre o que veio antes dele.

Sublinhado pontilhado: baixa confiança. Os valores de confiança desta transcrição são encenados.

[faixas 2019 a 2026]

Cada projeto é um clipe, no ano em que aconteceu.

A régua é a de um editor de áudio, em escala real de anos. Cinco trilhas: pesquisa em IA, backend, front e mobile, ensino e o próprio ambiente de trabalho. Clique num clipe para abrir o detalhe técnico.

ano
IA e pesquisaPython, PyTorch, Whisper
BackendNode, FastAPI, SQL
Front e mobileReact, RN, Next.js
Ensinoalgoritmos, vJudge
AmbienteLua, tmux

Clipes empilhados no mesmo ano são projetos paralelos. 2020 teve duas Semanas Omnistack e uma NLW.

replication-ANES

Replicação do artigo Aspect-oriented unsupervised social link inference on user trajectory data (Byun, Choi e Kim, Information Sciences, vol. 626, 2023). A pergunta do paper: dá para inferir quem é amigo de quem, sem nenhum rótulo, só olhando check-ins do Foursquare em Nova York?

  • códigoCerca de 2.400 linhas de Python em 8 módulos: preprocessing.py, ANES.py (treino), model.py (776 linhas), data.py, loss.py, projection.py, graphutils.py, utils.py.
  • representaçãoEmbeddings separados de usuário, POI, tempo, categoria e geografia, 128 dimensões cada. Cada check-in vira uma tripla orientada a aspecto, projetada no estilo TransH, TransR e TransD, como em grafo de conhecimento.
  • tempo168 slots semanais (dia vezes hora), com correção de fuso a partir do offset em minutos.
  • perdasMargin loss, orthogonal loss (mantém o vetor de relação ortogonal ao hiperplano) e norm loss.
  • amostragemNegativos sorteados por busca binária sobre a CDF da distribuição: O(log n) por amostra.
  • variantesANES, ANES_GEO, ANES_GEO_YELP, ANES_GEO_Others, LBGC_v4.
  • experimentoRecortes NYC_20, 40, 60, 80 e 100 com pares verdadeiros e falsos de treino, validação e teste. lr 1e-4, L1, 1000 iterações, t-SNE para olhar o espaço aprendido.

turbo-whisper

setembro de 2026, open sourcePython, PyQt6github.com/ezequiasOR/turbo-whisper

Fork do knowall-ai/turbo-whisper, um app de ditado por voz no estilo SuperWhisper: OpenAI Whisper, 99 idiomas, PyQt6, atalho global e waveform na tela. Três commits dele: o conserto do teclado ABNT, seleção de idioma com gravação sem janela e mensagem de erro clara para servidor offline, e as notas do setup self-hosted no Pop!_OS.

A história completa, com demo, está em Bug ABNT e Whisper local, logo abaixo.

ia-ufcg

Quizzes de Inteligência Artificial da UFCG resolvidos em notebooks Jupyter. É onde a trilha de IA começa, dois anos antes da replicação do ANES.

fast_zero

2025Python 3.14, FastAPIgithub.com/ezequiasOR/fast_zero

Uma API pequena montada com a engenharia em volta já no lugar: o CRUD é simples de propósito, o que importa é o que roda antes e depois de cada teste.

  • APIFastAPI com Pydantic v2: EmailStr e os schemas UserSchema, UserPublic, UserDB, UserList. CRUD REST de usuários com HTTPStatus e 404 tratado.
  • lintRuff com as regras I, F, E, W, PL (pylint) e PT (estilo pytest), em modo preview.
  • testespytest e pytest-cov com relatório HTML; TestClient entregue por fixture.
  • tarefastaskipy encadeia tudo: pre_test = lint, post_test = coverage html. Não dá para rodar teste sem passar no lint.
  • ambientePython 3.14 com Poetry.

DevRadar

2020, Semana Omnistack123 commits delegithub.com/ezequiasOR/DevRadar

Mapa de devs por tecnologia, com aviso em tempo real quando alguém próximo se cadastra.

  • backendExpress com MongoDB e Mongoose, usando consultas geoespaciais para achar devs num raio.
  • tempo realSocket.io empurra o dev novo para quem está perto, sem polling.
  • integraçãoDados do perfil puxados da API do GitHub com axios.
  • clientesWeb em React; mobile em Expo com mapas, localização, WebView e socket.io-client.

be-the-hero

2020, Semana Omnistack122 commits delegithub.com/ezequiasOR/be-the-hero

Uma API Express com as rotas cobertas por teste, mais front e app consumindo ela.

  • APIExpress, Knex e SQLite, validação com Celebrate.
  • testesJest com Supertest batendo nas rotas; cross-env para separar o ambiente de teste.
  • clientesFront em React e app em React Native com Expo.

Java na UFCG

2020Java

Os primeiros projetos orientados a objeto da graduação: coisa (Controle Institucional da Situação Acadêmica), agenda-de-contatos e controle-de-alunos.

Python-Estudos

desde 2019105 commits dele

Estudo de Python voltado a banco de dados: CRUD, paginação com limit e offset e consultas parametrizadas, com um exercício inteiro chamado "selecionar sem SQL injection". Ao lado, o ibdmd reúne datasets para BI (lojas, gerentes e vendas).

Web-Estudos

2019 a 2025844 commits, 479 dele

Sete anos de estudo de web num repositório só.

  • JavaScriptDo zero ao avançado: map, filter, reduce, imperativo contra declarativo.
  • AJAXA mesma requisição em XHR, fetch, axios e jQuery.
  • ferramentasExpress, Gulp, Webpack, Vue e React.
  • dadosSQL relacional com joins e agregação; MongoDB com lookup.
  • avulsosbin2dec, casa-criativa e doe (MaratonaDev).

Ecoleta

2020, NLW124 commits delegithub.com/ezequiasOR/Ecoleta

Marketplace de pontos de coleta de resíduos por geolocalização, em TypeScript nas três pontas.

  • APINode, Express e Knex com migrations e seeds sobre SQLite. Validação com Celebrate e Joi, upload com Multer, CORS.
  • webReact e TypeScript, mapa com Leaflet e react-leaflet, upload por arrastar e soltar com react-dropzone, react-router.
  • mobileReact Native com Expo: react-native-maps, expo-location, expo-mail-composer e React Navigation.

audio-speed-controller

2020extensão de navegador

Extensão que acelera os áudios do WhatsApp Web. Seis anos antes do turbo-whisper, já era um projeto sobre voz e paciência.

clone-tabnews

  • appNext.js 13 com o driver pg e um endpoint /api/v1/status.
  • bancoPostgres em Docker Compose, definido em infra/compose.yaml.
  • testesTeste de integração com Jest contra o banco de pé.
  • higienePrettier, .editorconfig e .nvmrc para fixar a versão do Node. Deploy na Vercel.

Aprendizado de Algoritmos

primeira turma em 2020, nova turma em 2025github.com/ezequiasOR/aa-iniciantegithub.com/ezequiasOR/aa

Trilhas semanais com listas no vJudge e vídeos gravados por ele resolvendo as questões, para o aluno ver o raciocínio e não só o código final.

  • inicianteAd hoc, two pointers, soma acumulada, busca binária; fila, heap, pilha, set e mapa; GCD e LCM, crivo, aritmética modular e exponenciação binária.
  • avançadaSegment Tree, Lazy Propagation, Square Root Decomposition e o algoritmo de Mo.

atal-ufcg

2021Análise e Técnicas de Algoritmosgithub.com/ezequiasOR/atal-ufcg

Soluções de Codeforces organizadas por paradigma, do jeito que a disciplina cobra: força bruta, backtracking, guloso, divisão e conquista, programação dinâmica e grafos com BFS e DFS.

nvim e tmux

Neovim configurado em Lua: LSP, Telescope, Treesitter, Harpoon, Fugitive, Undotree, Trouble, Zen Mode, refactoring e cloak, este último para esconder segredo de arquivo .env na tela. Mais a configuração de tmux.

[turbo-whisper, commit 3f647e2]

O apóstrofo que virava til.

Dite "copo d'água" com o auto-typing em evdev. Num teclado americano, sai certo. Num ABNT2, o apóstrofo sai como til.

O turbo-whisper tinha vários jeitos de digitar o texto transcrito. Um deles, o evdev, cria um teclado virtual pelo kernel e manda códigos de tecla crus. O mapa desses códigos estava escrito para o layout US-QWERTY: para digitar ', ele aperta KEY_APOSTROPHE, a tecla à direita do ponto e vírgula americano.

Só que o kernel não sabe o que está impresso na tecla. Quem traduz código em caractere é o layout ativo, e no ABNT2 aquela mesma posição física é a tecla morta do til. O evdev pede um apóstrofo e o sistema entende ~.

A correção inverte a prioridade. O xdotool (X11) e o wtype (Wayland) mandam o caractere, não a posição, e respeitam o layout que estiver ativo. O código detecta Wayland por WAYLAND_DISPLAY ou XDG_SESSION_TYPE, tenta wtype, depois xdotool type --clearmodifiers --delay, e só então cai para evdev, PyAutoGUI e, no fim, para a área de transferência.

  • 3f647e2fix: prefer xdotool/wtype over evdev for auto-typing
  • 2d7f02dfeat: language selection, headless recording, clearer offline error, +143 linhas em api.py, config.py e main.py.
  • dffee46docs: self-hosted setup notes for Pop!_OS

A demo do teclado precisa de JavaScript. O mecanismo está descrito ao lado.

esperado
copo d'água
na janela
copo d~gua
src/turbo_whisper/typer.py, método _type_linuxtrecho real do commit
# Prefer xdotool (X11) / wtype (Wayland): both honor the active keyboard
# layout and handle Unicode. The evdev fallback sends raw US-QWERTY
# scancodes, so non-US layouts mistype punctuation (e.g. ABNT turns ' into ~).
is_wayland = bool(os.environ.get("WAYLAND_DISPLAY")) or (
    os.environ.get("XDG_SESSION_TYPE", "").lower() == "wayland"
)

if is_wayland and shutil.which("wtype"):
    try:
        subprocess.run(["wtype", "--", text], check=True, timeout=30)
        return True
    except Exception as e:
        print(f"wtype failed: {e}")

if shutil.which("xdotool"):
    try:
        delay_ms = max(1, int(self._typing_delay * 1000))
        subprocess.run(
            [
                "xdotool", "type", "--clearmodifiers",
                "--delay", str(delay_ms), "--", text,
            ],
            check=True, timeout=30,
        )
        return True
    except Exception as e:
        print(f"xdotool failed: {e}")

if self._evdev_available and self._uinput:
    try:
        return self._type_evdev(text)
    except Exception as e:
        print(f"evdev typing failed: {e}")
[turbo-whisper, commit dffee46]

Whisper rodando na própria máquina.

As notas de setup que ele deixou no fork montam a transcrição inteira localmente no Pop!_OS: a placa de vídeo faz a inferência, e a porta do servidor só existe em 127.0.0.1.

  1. microfonePipeWire e PortAudio
  2. turbo-whisperPyQt6, atalho global
  3. faster-whisperDocker, CUDA, 127.0.0.1
  4. texto/v1/audio/transcriptions
  5. janela focadawtype ou xdotool
  • modeloSystran/faster-whisper-small, carregado por variável de ambiente.
  • GPU--gpus all com a imagem CUDA do servidor.
  • rede-p "127.0.0.1:…:8000". Publicada só no loopback, a porta não aparece para a rede local.
  • cache~/.cache/huggingface montado no container, então o modelo baixa uma vez.
  • reinício--restart unless-stopped, mais um curl em /health para conferir.
  • no appO commit de idioma faz o erro de conexão dizer que o servidor local não está rodando, em vez de culpar a internet.
# garantir que o servidor faster-whisper está rodando
if sudo docker ps -a --format '{{.Names}}' | grep -qx "$TW_CONTAINER_NAME"; then
  sudo docker start "$TW_CONTAINER_NAME"
else
  mkdir -p ~/.cache/huggingface

  sudo docker run -d \
    --name "$TW_CONTAINER_NAME" \
    --restart unless-stopped \
    --gpus all \
    -p "127.0.0.1:${TW_WHISPER_PORT}:8000" \
    -v "${HOME}/.cache/huggingface:/root/.cache/huggingface" \
    -e WHISPER__MODEL=Systran/faster-whisper-small \
    fedirz/faster-whisper-server:latest-cuda
fi

# testar servidor
sudo docker logs --tail=80 "$TW_CONTAINER_NAME"
curl -sS "http://127.0.0.1:${TW_WHISPER_PORT}/health"
[22 repositórios próprios, sem forks]

Níveis.

Contados clonando os repositórios e lendo o histórico. Cerca de 1.110 commits autorais.

Commits por ano

Escala até 256. 2022 bate no vermelho; 2026 é a contribuição no turbo-whisper.

  • 212019
  • 2072020
  • 2002021
  • 2562022
  • 1722023
  • 1932024
  • 612025
  • 32026

Volume de código por linguagem

Bytes nos repositórios próprios. É quanto código existe, não quanto ele sabe.

  • JavaScript828 KB
  • CSS392 KB
  • HTML330 KB
  • Jupyter294 KB
  • Python223 KB
  • TypeScript55 KB
  • Java36 KB
  • Lua11 KB
  • Vue11 KB
  • SQL6 KB
2018conta no GitHub, desde outubro
50repositórios públicos
138seguidores
~1.110commits autorais em 22 repos

Mesa de som.

A stack agrupada por canal. Ele também está na EssentIA (@EssentIA-Agents), organização no GitHub voltada a agentes de IA.

IA e dados

  • Python
  • PyTorch
  • scikit-learn
  • Pandas, NumPy
  • Jupyter
  • TransH, TransR, TransD
  • Whisper, faster-whisper

Backend

  • FastAPI, Pydantic
  • Node.js, Express
  • Next.js API routes
  • Knex, Mongoose
  • Socket.io

Front e mobile

  • TypeScript
  • React
  • React Native, Expo
  • Next.js
  • Leaflet
  • Vue

Dados

  • PostgreSQL
  • SQLite
  • MongoDB
  • MySQL e SQL

Qualidade e infra

  • pytest, Jest, Supertest
  • Ruff, Prettier
  • Poetry
  • Docker, Compose
  • CUDA
  • Vercel, Git

Ambiente

  • Linux, Pop!_OS
  • Neovim em Lua
  • tmux
  • Wayland e X11