# pulsemeeter: mixing virtual audio devices under PulseAudio and PipeWire

> pulsemeeter is a Python and GTK front end for the routing capabilities of PulseAudio and PipeWire, arranged around virtual inputs and outputs in the style of Voicemeeter. It is a small application that leans on the sound server's own routing model rather than implementing mixing itself.

**theRealCarneiro/pulsemeeter** — A pulseaudio and pipewire audio mixer inspired by voicemeeter

- Repository: https://github.com/theRealCarneiro/pulsemeeter
- Stars: 781 · Forks: 39
- Language: Python
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/therealcarneiro-pulsemeeter

## A front end for routing the sound server already does

pulsemeeter is described as a frontend to ease the use of PulseAudio's routing capabilities, much like Voicemeeter's workflow. The repository description is blunter about the scope: a PulseAudio and PipeWire audio mixer inspired by Voicemeeter.

The framing matters. This is not a mixer in the sense of processing samples. Everything here is built on the routing graph the sound server already maintains, and the application's job is to make that graph manipulable with sliders, menus and buttons rather than with command line tools.

The Voicemeeter comparison is the right mental model for the user experience. Voicemeeter is famous for the idea of a virtual bus, several sources routed into one, and that bus then treated as a source for another virtual bus, so a voice chat application and a music player can end up in separate outputs and be recombined later. Pulsemeeter offers the same arrangement of virtual inputs and outputs, with the routing actually living in the sound server.

The audience is Linux users doing audio routing work: podcasters and streamers separating a microphone from a game, people recording from two sources at once, and anyone who needs a second output that a second sound device cannot provide.

## Virtual inputs and outputs as the organising idea

The feature list is short and every item is a routing operation.

The first is creating virtual inputs and outputs. In the sound server's model these are the modules that have no hardware behind them, and they are what makes Voicemeeter style workflows possible, because they can be used as destinations for one source and as sources for another.

The second is routing audio from input devices to output devices, either hardware or virtual. That is the core operation, and the phrase either hardware or virtual captures the two directions: a real output such as headphones, or another virtual bus that a later stage consumes.

The third is volume and mute control per channel, and the fourth is the channel layout for virtual devices, where you choose mono, stereo and similar. The layout setting is the one that has consequences beyond the user interface, because it determines how many channels the virtual device presents to whatever connects to it, and a mismatch there produces a channel count error that is easy to misread.

The last two features are for hardware specifically: port selection for hardware devices, meaning you choose which channels of a hardware device should be active, and custom port to port connection mapping. Together they cover the case where a device exposes more ports than you want to route, and where a specific source port should go to a specific sink port rather than to a device as a whole.

## The GTK front end and how it talks to the sound server

The user interface is a GTK application, and the README notes that the screenshot was taken with the Ant Dracula GTK theme and that the application will use your theme. That is a small detail but it says something about the design intent: this is a native desktop utility rather than a web app or a themed panel.

The Python side leans on the sound server's native protocol rather than on shell commands. The runtime requirements list is short and tells you the shape of the thing:

```bash
pulsectl
pulsectl_asyncio
pygobject
pydantic
```

pulsectl is the Python binding for the PulseAudio protocol, and pulsectl_asyncio is its asynchronous counterpart, so the application can drive the server without blocking on a synchronous call. pygobject is the binding to GTK itself, which is what makes the interface a native one rather than a web view, and pydantic handles the data model, which matters when the application is juggling device, port and module descriptions with optional fields.

There is a development requirements file alongside it, and the repository is a conventional Python project with src/ for the package, tests/, share/ for the data files such as the stylesheet, locale/ for the translations and packaging/ for the distribution definitions.

## Installation is delegated to the wiki

The README is brief about installation by design. It says to visit the wiki for in depth information on how to install, and the wiki has an Installation page and a How to use page.

What the repository itself shows is the range of routes. The README carries badges for the PyPI package, for an AUR stable package and for an AUR git package, plus a Weblate translation widget and a Discord server. The AUR packages mean an Arch user can install the application from the distribution's own channels, and the git variant tracks the repository rather than a tagged release.

The build system in the tree is where the packaging detail lives. The pyproject.toml declares a setuptools build backend with setuptools and babel in the build requirements, and setup.py adds a custom build_py subclass that runs the compile_catalog command before the normal build, so the gettext catalogues are compiled during the build rather than as a separate step.

The data file layout is also handled there. A helper walks the locale directory and copies the compiled .mo files into share, DATA_FILES collects the licence into share/licenses/pulsemeeter, and the remaining files under share are gathered as data files as well. There is also a ZIP_BUILD environment variable that switches on a zip build path, and the message extractors are configured over the Python sources so that the translations cover the whole package rather than a hand maintained list.

## Translations are a first class part of the project

The Weblate badge points at a hosted translation project, and the build system treats localisation as part of the build rather than as an afterthought.

That is visible in setup.py. The custom BuildWithTranslations class overrides the normal build_py command so that compile_catalog runs first, gathering the .mo files from the locale directory into the share directory that the application loads at runtime. The babel commands for extract_messages, init_catalog and update_catalog are registered alongside it, and the message extractors are pointed at the Python sources, so the strings to translate are discovered from the code rather than from a list someone maintains.

The practical consequences are worth spelling out. A contributor who adds a user facing string will have it picked up by the extraction step, and a translator can then work in Weblate without touching the source tree. A packager gets the compiled catalogues because the build produces them.

The other thing the packaging reveals is that the data files are not incidental. The share directory is gathered wholesale into the distribution, and the licence is installed into share/licenses/pulsemeeter, so the application ships as a set of data files alongside the Python code rather than as a single script. That is the shape of a desktop application installed system wide, and it is why the wiki, rather than a single pip command, is the reference for installation.

## Where pulsemeeter is the wrong tool

Three cases point elsewhere.

The first is a routing problem that is really a configuration problem. PulseAudio and PipeWire can both express a fixed source to sink mapping in configuration, and if you want one microphone to one output with no mixing and no per channel control, a configuration file is simpler than a graphical mixer and it survives a reboot without a user session.

The second is a platform where this application does not run. The dependencies are GTK and the PulseAudio protocol, so the natural home is a Linux desktop with one of those sound servers. On a system with a different audio stack, the routing model has to be recreated, and at that point you are writing a new application rather than configuring one.

The third is a workflow that needs real audio processing rather than routing. A mixer that sends sources to outputs is not a compressor, an equaliser or a noise suppressor, and while some of that exists elsewhere in the sound server's module set, do not expect this front end to cover it.

The last practical note is about how the application talks to the sound server. pulsectl and pulsectl_asyncio speak the server's protocol directly, which is fast and precise but also means the application is tied to the PulseAudio family of servers. PipeWire provides a compatible layer, which is why the project describes itself as a PipeWire mixer too, but the details of how a module appears to the protocol can differ between implementations, and that is where a version difference shows up first.

## Conclusion

Adopt pulsemeeter if you run Linux with PulseAudio or PipeWire, need to mix several sources into separate outputs, and want a graphical control surface instead of pactl commands. Do not adopt it if your audio routing is simple enough for the sound server's own module tools, or if you are on a platform where the equivalent routing work is done differently. Verify three things first: which sound server your distribution actually runs, since the project targets both and the modules differ; that the runtime dependencies are present, since it needs pulsectl, pulsectl_asyncio, pygobject and pydantic and the GTK binding is a hard requirement; and which installation route you will use, because the README defers to the wiki for installation details while the repository ships PyPI, an AUR stable package, an AUR git package and a source tree. The licence is MIT, the last push was on 2026-10-19, and the newest release is v2.2.0 dated 2026-07-25.

## FAQ

### What is pulsemeeter?

It is a front end that eases the use of PulseAudio's routing capabilities, much like Voicemeeter's workflow, and the repository describes it as a PulseAudio and PipeWire audio mixer inspired by Voicemeeter. It creates virtual inputs and outputs and routes audio between devices and buses.

### What can pulsemeeter do with hardware devices?

It offers port selection for hardware devices, so you can choose which channels of a hardware device should be active, and custom port to port connection mapping for routing a specific source port to a specific sink port.

### What are pulsemeeter's runtime dependencies?

The requirements file lists pulsectl, pulsectl_asyncio, pygobject and pydantic. The GTK binding is what makes the interface a native desktop application rather than a web view.

### How is pulsemeeter installed?

The README sends you to the project wiki for in depth installation instructions. The repository ships a PyPI package, an AUR stable package and an AUR git package, plus a source tree with a setup.py that compiles the gettext catalogues during the build.

### Does pulsemeeter work with PipeWire?

The project describes itself as a PulseAudio and PipeWire audio mixer, and the implementation talks to the server through the PulseAudio protocol using pulsectl and its asynchronous counterpart rather than through shell commands.

## Sources

- [Issues](https://github.com/theRealCarneiro/pulsemeeter/issues)
- [License: MIT](https://github.com/theRealCarneiro/pulsemeeter/blob/main/LICENSE)
- [README](https://github.com/theRealCarneiro/pulsemeeter/blob/main/README.md)
- [Releases](https://github.com/theRealCarneiro/pulsemeeter/releases)
- [theRealCarneiro/pulsemeeter on GitHub](https://github.com/theRealCarneiro/pulsemeeter)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/therealcarneiro-pulsemeeter
