2022-08-06 08:56:53 +01:00
[![PyPI version ](https://badge.fury.io/py/voicemeeter-api.svg )](https://badge.fury.io/py/voicemeeter-api)
2022-06-16 16:17:33 +01:00
[![License: MIT ](https://img.shields.io/badge/License-MIT-yellow.svg )](https://github.com/onyx-and-iris/voicemeeter-api-python/blob/dev/LICENSE)
2022-06-16 14:07:12 +01:00
[![Code style: black ](https://img.shields.io/badge/code%20style-black-000000.svg )](https://github.com/psf/black)
[![Imports: isort ](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336 )](https://pycqa.github.io/isort/)
![Tests Status ](./tests/basic.svg?dummy=8484744 )
![Tests Status ](./tests/banana.svg?dummy=8484744 )
![Tests Status ](./tests/potato.svg?dummy=8484744 )
# Python Wrapper for Voicemeeter API
This package offers a Python interface for the Voicemeeter Remote C API.
For an outline of past/future changes refer to: [CHANGELOG ](CHANGELOG.md )
## Tested against
2022-08-08 16:40:59 +01:00
- Basic 1.0.8.4
- Banana 2.0.6.4
- Potato 3.0.2.4
2022-06-16 14:07:12 +01:00
## Requirements
- [Voicemeeter ](https://voicemeeter.com/ )
2022-09-03 16:28:19 +01:00
- Python 3.10 or greater
2022-06-16 14:07:12 +01:00
## Installation
### `Pip`
Install voicemeeter-api package from your console
`pip install voicemeeter-api`
## `Use`
Simplest use case, use a context manager to request a Remote class of a kind.
Login and logout are handled for you in this scenario.
#### `__main__.py`
```python
import voicemeeterlib
class ManyThings:
def __init__ (self, vm):
self.vm = vm
def things(self):
self.vm.strip[0].label = "podmic"
self.vm.strip[0].mute = True
print(
2022-08-06 10:49:56 +01:00
f"strip 0 ({self.vm.strip[0].label}) mute has been set to {self.vm.strip[0].mute}"
2022-06-16 14:07:12 +01:00
)
def other_things(self):
info = (
f"bus 3 gain has been set to {self.vm.bus[3].gain}",
f"bus 4 eq has been set to {self.vm.bus[4].eq}",
)
self.vm.bus[3].gain = -6.3
self.vm.bus[4].eq = True
print("\n".join(info))
def main():
with voicemeeterlib.api(kind_id) as vm:
do = ManyThings(vm)
do.things()
do.other_things()
# set many parameters at once
vm.apply(
{
"strip-2": {"A1": True, "B1": True, "gain": -6.0},
"bus-2": {"mute": True},
"button-0": {"state": True},
"vban-in-0": {"on": True},
"vban-out-1": {"name": "streamname"},
}
)
if __name__ == "__main__":
kind_id = "banana"
main()
```
Otherwise you must remember to call `vm.login()` , `vm.logout()` at the start/end of your code.
## `kind_id`
Pass the kind of Voicemeeter as an argument. kind_id may be:
- `basic`
- `banana`
- `potato`
## `Available commands`
2022-06-27 14:58:39 +01:00
### Strip
2022-06-16 14:07:12 +01:00
2022-06-27 14:58:39 +01:00
The following properties are available.
2022-06-16 14:07:12 +01:00
- `mono` : boolean
2022-06-27 14:58:39 +01:00
- `solo` : boolean
2022-06-16 14:07:12 +01:00
- `mute` : boolean
2022-06-27 14:58:39 +01:00
- `gain` : float, from -60.0 to 12.0
- `comp` : float, from 0.0 to 10.0
- `gate` : float, from 0.0 to 10.0
- `audibility` : float, from 0.0 to 10.0
2022-06-16 14:07:12 +01:00
- `limit` : int, from -40 to 12
- `A1 - A5` , `B1 - B3` : boolean
- `label` : string
- `device` : string
- `sr` : int
2022-06-27 14:58:39 +01:00
- `mc` : boolean
2022-06-27 16:38:59 +01:00
- `k` : int, from 0 to 4
- `bass` : float, from -12.0 to 12.0
- `mid` : float, from -12.0 to 12.0
- `treble` : float, from -12.0 to 12.0
2022-07-16 23:21:55 +01:00
- `reverb` : float, from 0.0 to 10.0
- `delay` : float, from 0.0 to 10.0
- `fx1` : float, from 0.0 to 10.0
- `fx2` : float, from 0.0 to 10.0
- `pan_x` : float, from -0.5 to 0.5
- `pan_y` : float, from 0.0 to 1.0
- `color_x` : float, from -0.5 to 0.5
- `color_y` : float, from 0.0 to 1.0
- `fx_x` : float, from -0.5 to 0.5
- `fx_y` : float, from 0.0 to 1.0
- `postreverb` : boolean
- `postdelay` : boolean
- `postfx1` : boolean
- `postfx2` : boolean
2022-06-27 16:38:59 +01:00
example:
```python
vm.strip[3].gain = 3.7
print(vm.strip[0].label)
```
2022-06-27 14:58:39 +01:00
The following methods are Available.
- `appgain(name, value)` : string, float, from 0.0 to 1.0
Set the gain in db by value for the app matching name.
- `appmute(name, value)` : string, bool
Set mute state as value for the app matching name.
example:
```python
vm.strip[5].appmute("Spotify", True)
vm.strip[5].appgain("Spotify", 0.5)
```
##### Gainlayers
2022-06-27 15:00:48 +01:00
2022-06-27 14:58:39 +01:00
- `gain` : float, from -60.0 to 12.0
example:
```python
vm.strip[3].gainlayer[3].gain = 3.7
```
Gainlayers are defined for potato version only.
##### Levels
The following properties are available.
- `prefader`
- `postfader`
- `postmute`
example:
```python
print(vm.strip[3].levels.prefader)
```
Level properties will return -200.0 if no audio detected.
### Bus
The following properties are available.
- `mono` : boolean
- `eq` : boolean
2022-06-27 15:11:18 +01:00
- `eq_ab` : boolean
2022-06-27 14:58:39 +01:00
- `mute` : boolean
2022-06-27 15:11:18 +01:00
- `sel` : boolean
2022-06-27 14:58:39 +01:00
- `gain` : float, from -60.0 to 12.0
- `label` : string
- `device` : string
2022-06-27 15:11:18 +01:00
- `sr` : int
2022-07-16 23:21:55 +01:00
- `returnreverb` : float, from 0.0 to 10.0
- `returndelay` : float, from 0.0 to 10.0
- `returnfx1` : float, from 0.0 to 10.0
- `returnfx2` : float, from 0.0 to 10.0
- `monitor` : boolean
2022-06-16 14:07:12 +01:00
example:
```python
2022-06-27 16:38:59 +01:00
vm.bus[3].gain = 3.7
print(vm.bus[0].label)
2022-06-16 14:07:12 +01:00
2022-06-27 16:38:59 +01:00
vm.bus[4].mono = True
```
##### Modes
2022-07-16 21:24:51 +01:00
The following properties are available.
2022-06-27 16:38:59 +01:00
- `normal` : boolean
- `amix` : boolean
- `bmix` : boolean
- `composite` : boolean
- `tvmix` : boolean
- `upmix21` : boolean
- `upmix41` : boolean
- `upmix61` : boolean
- `centeronly` : boolean
- `lfeonly` : boolean
- `rearonly` : boolean
2022-07-16 21:24:51 +01:00
The following methods are available.
- `get()` : Returns the current bus mode
2022-06-27 16:38:59 +01:00
example:
```python
vm.bus[4].mode.amix = True
2022-07-16 21:24:51 +01:00
print(vm.bus[2].mode.get())
2022-06-16 14:07:12 +01:00
```
2022-06-27 15:00:48 +01:00
##### Levels
The following properties are available.
- `all`
example:
```python
print(vm.bus[0].levels.all)
```
`levels.all` will return -200.0 if no audio detected.
2022-06-27 14:58:39 +01:00
### Strip | Bus
The following methods are available.
- `fadeto(amount, time)` : float, int
- `fadeby(amount, time)` : float, int
Modify gain to or by the selected amount in db over a time interval in ms.
example:
```python
vm.strip[0].fadeto(-10.3, 1000)
vm.bus[3].fadeby(-5.6, 500)
```
2022-06-16 14:07:12 +01:00
### Macrobuttons
2022-06-27 14:58:39 +01:00
The following properties are available.
2022-06-16 14:07:12 +01:00
- `state` : boolean
- `stateonly` : boolean
- `trigger` : boolean
example:
```python
2022-06-27 16:38:59 +01:00
vm.button[37].state = True
vm.button[55].trigger = False
2022-06-16 14:07:12 +01:00
```
### Recorder
2022-06-27 14:58:39 +01:00
The following methods are available
2022-06-16 14:07:12 +01:00
- `play()`
- `stop()`
- `pause()`
- `record()`
- `ff()`
- `rew()`
2022-07-16 21:24:51 +01:00
- `load(<filepath>)` : string
2022-06-27 14:58:39 +01:00
The following properties are available
2022-06-27 15:00:48 +01:00
2022-06-16 14:07:12 +01:00
- `loop` : boolean
- `A1 - A5` : boolean
- `B1 - A3` : boolean
example:
```python
vm.recorder.play()
vm.recorder.stop()
# Enable loop play
vm.recorder.loop = True
# Disable recorder out channel B2
vm.recorder.B2 = False
# filepath as raw string
vm.recorder.load(r'C:\music\mytune.mp3')
```
2022-06-27 14:58:39 +01:00
Recorder properties are defined as write only.
2022-06-16 14:07:12 +01:00
### VBAN
- `vm.vban.enable()` `vm.vban.disable()` Turn VBAN on or off
2022-06-27 14:58:39 +01:00
##### Instream | Outstream
The following properties are available.
2022-06-16 14:07:12 +01:00
- `on` : boolean
- `name` : string
- `ip` : string
- `port` : int, range from 1024 to 65535
- `sr` : int, (11025, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000)
- `channel` : int, from 1 to 8
- `bit` : int, 16 or 24
- `quality` : int, from 0 to 4
- `route` : int, from 0 to 8
2022-06-27 14:58:39 +01:00
`SR` , `channel` and `bit` are defined as:
2022-06-27 15:00:48 +01:00
2022-06-27 14:58:39 +01:00
- readonly for instreams.
- read and write for outstreams.
2022-06-16 14:07:12 +01:00
example:
```python
# turn VBAN on
vm.vban.enable()
# turn on vban instream 0
vm.vban.instream[0].on = True
# set bit property for outstream 3 to 24
vm.vban.outstream[3].bit = 24
```
### Command
2022-06-27 14:58:39 +01:00
Certain 'special' commands are defined by the API as performing actions rather than setting values.
2022-07-16 23:21:55 +01:00
2022-06-27 14:58:39 +01:00
The following methods are available:
2022-06-16 14:07:12 +01:00
- `show()` : Bring Voiceemeter GUI to the front
- `shutdown()` : Shuts down the GUI
- `restart()` : Restart the audio engine
2022-07-16 21:24:51 +01:00
- `reset()` : Applies the `reset` config. (phys strip B1, virt strip A1, gains, comp, gate 0.0, mute, mono, solo, eq false)
2022-06-16 14:07:12 +01:00
2022-06-27 14:58:39 +01:00
The following properties are available.
2022-06-16 14:07:12 +01:00
- `showvbanchat` : boolean
- `lock` : boolean
example:
```python
vm.command.restart()
2022-06-27 16:38:59 +01:00
vm.command.showvbanchat = True
2022-06-16 14:07:12 +01:00
```
2022-06-27 14:58:39 +01:00
`showvbanchat` and `lock` are write only.
2022-06-27 16:49:37 +01:00
### Device
- `ins` `outs` : Returns the number of input/output devices
- `input(i)` `output(i)` : Returns a dict of device properties for device[i]
example:
```python
import voicemeeterlib
with voicemeeterlib.api(kind_id) as vm:
for i in range(vm.device.ins):
print(vm.device.input(i))
```
2022-07-16 23:21:55 +01:00
### FX
2022-07-21 23:19:24 +01:00
The following properties are available:
2022-07-16 23:21:55 +01:00
- `reverb` : boolean
- `reverb_ab` : boolean
- `delay` : boolean
- `delay_ab` : boolean
2022-07-21 23:19:24 +01:00
example:
```python
vm.fx.reverb_ab = True
```
### Patch
The following properties are available:
- `postfadercomposite` : boolean
- `postfxinsert` : boolean
example:
```python
vm.patch.postfxinsert = False
```
##### asio[i]
- `get()` : int
- `set(patch_in)` : int, valid range determined by connected device.
example:
```python
vm.patch.asio[3].set(4)
```
i, from 0 to 10
##### A2[i] - A5[i]
- `get()` : int
- `set(patch_out)` : int, valid range determined by connected device.
example:
```python
2022-07-21 23:23:55 +01:00
vm.patch.A3[5].set(3)
2022-07-21 23:19:24 +01:00
```
i, from 0 to 8.
##### composite[i]
- `get()` : int
- `set(channel)` : int, from 0 up to number of channels depending on version.
example:
```python
2022-07-22 13:13:15 +01:00
vm.patch.composite[7].set(4)
2022-07-21 23:19:24 +01:00
```
i, from 0 to 8.
##### insert[i]
- `on` : boolean
example:
```python
vm.patch.insert[18].on = True
```
i, from 0 up to number of channels depending on version.
### Option
The following properties are available:
- `sr` : int
- `asiosr` : boolean
- `monitoronsel` : boolean
example:
```python
vm.option.sr = 48000
```
The following methods are available:
- `buffer(driver, buffer)` : Set buffer size for particular audio driver.
example:
```python
vm.option.buffer("wdm", 512)
```
driver defined as one of ("mme", "wdm", "ks", "asio")
2022-07-21 23:25:54 +01:00
2022-07-21 23:19:24 +01:00
buffer, from 128 to 2048
##### delay[i]
- `get()` : int
- `set(delay)` : int, from 0 to 500
example:
```python
vm.option.delay[4].set(30)
```
i, from 0 up to 4.
2022-07-24 14:38:16 +01:00
### Midi
The following properties are available:
- `channel` : int, returns the midi channel
- `current` : int, returns the current (or most recently pressed) key
The following methods are available:
- `get(key)` : int, returns most recent velocity value for a key
example:
```python
print(vm.midi.get(12))
```
get() may return None if no value for requested key in midi cache
2022-06-16 14:07:12 +01:00
### Multiple parameters
- `apply`
Set many strip/bus/macrobutton/vban parameters at once, for example:
```python
vm.apply(
{
"strip-2": {"A1": True, "B1": True, "gain": -6.0},
"bus-2": {"mute": True},
"button-0": {"state": True},
"vban-in-0": {"on": True},
"vban-out-1": {"name": "streamname"},
}
)
```
Or for each class you may do:
```python
2022-06-27 16:38:59 +01:00
vm.strip[0].apply(mute: True, gain: 3.2, A1: True)
vm.vban.outstream[0].apply(on: True, name: 'streamname', bit: 24)
2022-06-16 14:07:12 +01:00
```
2022-06-16 16:56:45 +01:00
## Config Files
2022-06-16 18:58:31 +01:00
`vm.apply_config(<configname>)`
2022-06-16 16:56:45 +01:00
You may load config files in TOML format.
2022-06-27 15:03:30 +01:00
Three example configs have been included with the package. Remember to save
current settings before loading a user config. To set one you may do:
2022-06-16 16:56:45 +01:00
```python
import voicemeeterlib
with voicemeeterlib.api('banana') as vm:
2022-06-16 18:58:31 +01:00
vm.apply_config('example')
2022-06-16 16:56:45 +01:00
```
2022-06-27 15:03:30 +01:00
will load a user config file at configs/banana/example.toml for Voicemeeter Banana.
2022-06-16 16:56:45 +01:00
2022-06-16 14:07:12 +01:00
## `Base Module`
### Remote class
2022-08-02 09:19:30 +01:00
`voicemeeterlib.api(kind_id: str)`
You may pass the following optional keyword arguments:
- `sync` : boolean=False, force the getters to wait for dirty parameters to clear. For most cases leave this as False.
- `ratelimit` : float=0.033, how often to check for updates in ms.
- `subs` : dict={"pdirty": True, "mdirty": True, "midi": True, "ldirty": False}, initialize which event updates to listen for.
- `pdirty` : parameter updates
- `mdirty` : macrobutton updates
- `midi` : midi updates
- `ldirty` : level updates
#### Event updates
To receive event updates you should do the following:
- register your app to receive updates using the `vm.subject.add(observer)` method, where observer is your app.
- define an `on_update(subject)` callback function in your app. The value of subject may be checked for the type of event.
See `examples/observer` for a demonstration.
Level updates are considered high volume, by default they are NOT listened for. However, polling them with strip.levels and bus.levels methods will still work.
So if you don't wish to receive level updates, or you prefer to handle them yourself simply leave ldirty as default (False).
Each of the update types may be enabled/disabled separately. Don't use a midi controller? You have the option to disable midi updates.
example:
```python
import voicemeeterlib
# Set updates to occur every 50ms
# Listen for level updates but disable midi updates
with voicemeeterlib.api('banana', ratelimit=0.05, subs={"ldirty": True, "midi": False}) as vm:
...
```
#### `vm.event`
You may also add/remove event subscriptions as necessary with the Event class.
example:
```python
vm.event.add("ldirty")
vm.event.remove("pdirty")
# get a list of currently subscribed
print(vm.event.get())
```
2022-06-16 14:07:12 +01:00
Access to lower level Getters and Setters are provided with these functions:
2022-06-27 16:38:59 +01:00
- `vm.get(param, is_string=False)` : For getting the value of any parameter. Set string to True if getting a property value expected to return a string.
2022-06-16 14:07:12 +01:00
- `vm.set(param, value)` : For setting the value of any parameter.
Access to lower level polling functions are provided with these functions:
2022-06-27 16:38:59 +01:00
- `vm.pdirty()` : Returns True if a parameter has been updated.
- `vm.mdirty()` : Returns True if a macrobutton has been updated.
- `vm.ldirty()` : Returns True if a level has been updated.
2022-06-16 14:07:12 +01:00
example:
```python
vm.get('Strip[2].Mute')
vm.set('Strip[4].Label', 'stripname')
vm.set('Strip[0].Gain', -3.6)
```
### Run tests
To run all tests:
```
pytest -v
```
### Official Documentation
- [Voicemeeter Remote C API ](https://github.com/onyx-and-iris/Voicemeeter-SDK/blob/main/VoicemeeterRemoteAPI.pdf )