Expand and clarify README.md with updated workflows, examples, and testing instructions.
This commit is contained in:
58
README.md
58
README.md
@@ -2,22 +2,40 @@
|
|||||||
|
|
||||||
Create and manage PipeWire virtual microphones easily, from the command line.
|
Create and manage PipeWire virtual microphones easily, from the command line.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## What it does
|
## What it does
|
||||||
|
|
||||||
A vmic is two chained loopback stages:
|
A vmic starts as a single loopback stage:
|
||||||
|
|
||||||
```
|
```
|
||||||
apps -> vmic_X_sink =(stage 1)=> vmic_X_mid -> vmic_X_mix =(stage 2)=> vmic_X_mic -> recorders
|
apps -> vmic_X_sink =(pw-loopback)=> vmic_X_mic -> recorders
|
||||||
^ hardware mic joins here (route -s)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Point an app's output device at `vmic_X_sink`, and a recording app's input device at
|
Point an app's output device at `vmic_X_sink`, and a recording app's input device at
|
||||||
`vmic_X_mic`. Optionally mix in a real microphone downstream, and optionally hear your
|
`vmic_X_mic`. Optionally mix in a real microphone (`route -s`), and optionally hear
|
||||||
own output via a self-monitor loopback (which never carries the mixed-in mic).
|
your own output via a self-monitor loopback (`edit -l`).
|
||||||
|
|
||||||
|
If you enable both a self-monitor loopback *and* a mixed-in hardware source at the
|
||||||
|
same time, vmic automatically splits into a second loopback stage so the hardware
|
||||||
|
source never leaks into your self-monitor:
|
||||||
|
|
||||||
|
```
|
||||||
|
apps -> vmic_X_sink =(stage 1)=> vmic_X_mid -> vmic_X_mix =(stage 2)=> vmic_X_mic -> recorders
|
||||||
|
^ hardware mic joins here instead
|
||||||
|
```
|
||||||
|
|
||||||
|
It collapses back to the single-stage form the moment either the loopback or the
|
||||||
|
mixed-in source goes away. `edit --loopback-no-mix true` opts a vmic out of this
|
||||||
|
split entirely, keeping it at one stage even with both active - the mixed source
|
||||||
|
just becomes audible in your self-monitor too, as an explicit tradeoff for staying
|
||||||
|
simpler. Either transition recreates the vmic's underlying sink/mic nodes (same
|
||||||
|
names, new ids); any stream that was routed into or out of them gets moved back
|
||||||
|
automatically, and vmic reports what happened either way.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- PipeWire + pipewire-pulse (`pactl`, `pw-loopback`, `pw-link` on `PATH`)
|
- PipeWire + pipewire-pulse (`pactl`, `pw-loopback` on `PATH`)
|
||||||
- Rust (edition 2021)
|
- Rust (edition 2021)
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
@@ -49,14 +67,18 @@ vmic create <name> [-l] # create a vmic, optionally with self-monit
|
|||||||
vmic route <name> -i <app[:media]> # move an app's playback into the vmic
|
vmic route <name> -i <app[:media]> # move an app's playback into the vmic
|
||||||
vmic route <name> -o <app[:media]> # move an app's recording off the vmic
|
vmic route <name> -o <app[:media]> # move an app's recording off the vmic
|
||||||
vmic route <name> -s <source|none> # mix a hardware mic in, or remove it
|
vmic route <name> -s <source|none> # mix a hardware mic in, or remove it
|
||||||
vmic edit <name> -l <true|false> # toggle the self-monitor loopback
|
vmic edit <name> -l [<true|false>] # toggle the self-monitor loopback
|
||||||
|
vmic edit <name> --loopback-no-mix [<true|false>] # keep 1 stage even with loopback + a mixed source
|
||||||
vmic edit <name> -v <0.8|80> # self-monitor loopback volume
|
vmic edit <name> -v <0.8|80> # self-monitor loopback volume
|
||||||
vmic edit <name> -sv <0.8|80> # mixed-in source volume
|
vmic edit <name> -sv <0.8|80> # mixed-in source volume
|
||||||
vmic delete <name> # tear down one vmic
|
vmic delete <name> # tear down one vmic
|
||||||
vmic list # show all vmics and their status
|
vmic list # show all vmics, their status, and current node shape
|
||||||
vmic wipe # tear down every vmic, tracked or not
|
vmic wipe # tear down every vmic, tracked or not
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`-l` and `--loopback-no-mix` accept a bare form (means `true`) or an explicit
|
||||||
|
`true`/`false`, e.g. `vmic edit podcast -l` and `vmic edit podcast -l false` both work.
|
||||||
|
|
||||||
Aliases: `create` = `mk`/`make`, `delete` = `rm`/`remove`, `list` = `ls`, `wipe` = `reset`.
|
Aliases: `create` = `mk`/`make`, `delete` = `rm`/`remove`, `list` = `ls`, `wipe` = `reset`.
|
||||||
|
|
||||||
Shell completions: `vmic completions <bash|zsh|fish|...>`.
|
Shell completions: `vmic completions <bash|zsh|fish|...>`.
|
||||||
@@ -75,6 +97,26 @@ vmic route podcast -s "USB Microphone"
|
|||||||
Tracked in a SQLite database at `~/.config/vmic/vmic.db` (override the directory with
|
Tracked in a SQLite database at `~/.config/vmic/vmic.db` (override the directory with
|
||||||
`VMIC_STATE_DIR_OVERRIDE`).
|
`VMIC_STATE_DIR_OVERRIDE`).
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
`cargo test` runs a handful of fast unit tests only - no PipeWire needed.
|
||||||
|
|
||||||
|
Two live integration test suites exercise every command against a real PipeWire
|
||||||
|
session: they spawn real `pw-loopback` processes, move real streams, and (guarded)
|
||||||
|
run the destructive `wipe` command. Neither runs automatically; opt in explicitly:
|
||||||
|
|
||||||
|
```
|
||||||
|
tests/live_test.sh --input-app firefox --output-app chromium --hw-source fifine
|
||||||
|
cargo test --test live_test -- --ignored --nocapture
|
||||||
|
```
|
||||||
|
|
||||||
|
Both take the same parameters - as flags for the shell version, or matching env vars
|
||||||
|
for either (`VMIC_TEST_INPUT_APP`, `VMIC_TEST_OUTPUT_APP`, `VMIC_TEST_HW_SOURCE`,
|
||||||
|
`VMIC_TEST_NAME`, `VMIC_TEST_SKIP_WIPE=1`) - so point them at whatever apps and
|
||||||
|
hardware source you actually have available. They only ever touch vmics named
|
||||||
|
`<name>`/`<name>_a`/`<name>_b`, refuse to run the `wipe` phase if any other vmic
|
||||||
|
exists at that point, and always clean up after themselves even on failure.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
APGL-3
|
APGL-3
|
||||||
|
|||||||
Reference in New Issue
Block a user