@dev-belts/tui-pipew
v0.1.0
Published
TUI minimalista para gerenciar dispositivos de áudio PipeWire
Readme
@dev-belts/tui-pipew
TUI (Terminal User Interface) para gerenciar dispositivos de áudio PipeWire diretamente no terminal — sem mouse, sem GUI, sem frescura.
┌──────────────────────────────────────────────────────────────────────────────┐
│ 🎵 PipeWire Audio Control │
└──────────────────────────────────────────────────────────────────────────────┘
┌──────────┐
│ 🔊 Saída │ 🎤 Entrada 📱 Apps
╰──────────╯
╭────────────────────────────────────────────────────────────────────────────╮
│ │
│ ► 🎧 Wireless Headset PADRÃO │
│ 📺 HDMI Audio │
│ 🔌 USB Audio Speakers │
│ │
╰────────────────────────────────────────────────────────────────────────────╯
Tab/←→: alternar aba ↑↓: navegar Enter: padrão d: ocultar ESC: sairO que faz
- Saída — lista todos os sinks disponíveis, define o padrão com Enter
- Entrada — lista todos os sources disponíveis, define o padrão com Enter
- Apps — mostra quais apps estão reproduzindo áudio e em qual dispositivo; Enter abre um picker para redirecionar o stream em tempo real
- Ocultar devices — tecla
desconde um device da lista (persistido em~/.config/dev-belts/tui-pipew/config.json) - Tela de erro — se o PipeWire não estiver disponível, exibe uma tela explicativa no terminal em vez de travar
Dependências do sistema
Estas ferramentas precisam estar instaladas e rodando:
| Ferramenta | Pacote | Verificar |
|---|---|---|
| pipewire | pipewire | pipewire --version |
| pw-dump | pipewire | pw-dump --help |
| pw-metadata | pipewire | pw-metadata --help |
| wpctl | wireplumber | wpctl status |
Arch / CachyOS
sudo pacman -S pipewire wireplumber
systemctl --user enable --now pipewire pipewire-pulse wireplumberDebian / Ubuntu
sudo apt install pipewire wireplumber pipewire-audio-client-libraries
systemctl --user enable --now pipewire wireplumberFedora
sudo dnf install pipewire wireplumber
systemctl --user enable --now pipewire wireplumberInstalação global
npm install -g @dev-belts/tui-pipewDepois disso, use de qualquer lugar:
pipew # abre com abas Saída e Entrada
pipew --apps # abre com a aba Apps tambémPATH: se
pipewnão for encontrado após a instalação, adicione o bin global do npm ao seu PATH:export PATH="$PATH:$(npm prefix -g)/bin"Coloque essa linha no seu
~/.bashrcou~/.zshrc.
Como usar localmente
git clone <repo>
cd tui-pipew
npm install
npm run dev
npm run dev -- --appsAtalhos de teclado
| Tecla | Ação |
|---|---|
| Tab / → | Próxima aba |
| ← | Aba anterior |
| ↑ / ↓ | Navegar na lista |
| Enter | Definir como padrão (Saída/Entrada) · Abrir picker (Apps) |
| d | Ocultar device selecionado |
| ESC | Fechar picker · Sair |
Estrutura do projeto
src/
├── index.tsx # Entry point — carrega dados e renderiza App
├── App.tsx # Orquestrador: estado + teclado (useInput)
├── types.ts # AudioDevice, AppStream, Tab, PickerState
├── config.ts # Lê/escreve ~/.config/dev-belts/tui-pipew/config.json
├── components/
│ ├── Header.tsx # Barra de título
│ ├── Footer.tsx # Barra de atalhos
│ ├── TabBar.tsx # Abas com highlight
│ ├── DeviceList.tsx # Lista de sinks/sources com badge PADRÃO
│ ├── AppStreamList.tsx # Lista de streams com device atual
│ ├── DevicePicker.tsx # Modal para redirecionar stream
│ └── ErrorScreen.tsx # Tela de erro divertida (sem PipeWire)
└── pipewire/
├── types.ts # Sink, Source, Stream, VolumeInfo, erros
├── command.ts # run(cmd) — exec promisificado
├── dump.ts # fetchDump() — parseia pw-dump JSON
├── sinks.ts # listSinks, getDefaultSink, setDefaultSink
├── sources.ts # listSources, getDefaultSource, setDefaultSource
├── streams.ts # listStreams, moveStreamToSink
├── volume.ts # getVolume, setVolume, mute, toggleMute
├── stubs.ts # Adaptador TUI ↔ lib (mapeamento de tipos + ícones)
└── index.ts # Namespace PipeWire (API pública da lib)Lib PipeWire (uso standalone)
A lib em src/pipewire/ é independente do TUI e pode ser usada em qualquer projeto Node.js/TypeScript:
import { PipeWire } from "./src/pipewire/index.js";
const sinks = await PipeWire.sinks.list();
const default = await PipeWire.sinks.getDefault();
await PipeWire.sinks.setDefault(sinkId);
const sources = await PipeWire.sources.list();
await PipeWire.sources.setDefault(sourceId);
const streams = await PipeWire.streams.list();
await PipeWire.streams.moveTo(streamId, sinkId);
const vol = await PipeWire.volume.get(nodeId);
await PipeWire.volume.set(nodeId, "50%");
await PipeWire.volume.toggle(nodeId);Referência de comandos CLI
Ver CLI-INSTRUCT.md para os comandos PipeWire usados internamente.
