raise them when we fail to validate incoming packets. add VbanRTRequestHeader post_init to validate the provided bps value. VbanRTSubscribeHeader and VbanRTRequestHeader properties now return int type. They are then directly packed into the header.
VBAN CMD
This python interface allows you to send Voicemeeter/Matrix commands over a network.
It offers the same public API as Voicemeeter Remote Python API.
Only the VBAN SERVICE/TEXT subprotocols are supported, there is no support for AUDIO or MIDI in this package.
For an outline of past/future changes refer to: CHANGELOG
Tested against
- Basic 1.1.2.2
- Banana 2.1.2.2
- Potato 3.1.2.2
Requirements
- Voicemeeter
- Python 3.10 or greater
Installation
pip install vban-cmd
Use
Connection
Load VBAN connection info from toml config. A valid vban.toml might look like this:
[connection]
host = "localhost"
port = 6980
streamname = "Command1"
It should be placed in <user home directory> / "Documents" / "Voicemeeter" / "configs"
Alternatively you may pass host, port, streamname as keyword arguments.
__main__.py
Simplest use case, use a context manager to request a VbanCmd class of a kind.
Login and logout are handled for you in this scenario.
import vban_cmd
class ManyThings:
def __init__(self, vban):
self.vban = vban
def things(self):
self.vban.strip[0].label = 'podmic'
self.vban.strip[0].mute = True
print(
f'strip 0 ({self.vban.strip[0].label}) mute has been set to {self.vban.strip[0].mute}'
)
def other_things(self):
self.vban.bus[3].gain = -6.3
self.vban.bus[4].eq = True
info = (
f'bus 3 gain has been set to {self.vban.bus[3].gain}',
f'bus 4 eq has been set to {self.vban.bus[4].eq}',
)
print('\n'.join(info))
def main():
KIND_ID = 'banana'
with vban_cmd.api(
KIND_ID, host='localhost', port=6980, streamname='Command1'
) as vban:
do = ManyThings(vban)
do.things()
do.other_things()
# set many parameters at once
vban.apply(
{
'strip-2': {'A1': True, 'B1': True, 'gain': -6.0},
'bus-2': {'mute': True},
'vban-in-0': {'on': True},
}
)
if __name__ == '__main__':
main()
Otherwise you must remember to call vban.login(), vban.logout() at the start/end of your code.
KIND_ID
Pass the kind of Voicemeeter as an argument. KIND_ID may be:
basicbananapotato
A fourth kind matrix has been added, if you pass it as a KIND_ID you are expected to use the {VbanCmd}.sendtext() method for sending text requests.
Available commands
Strip
The following properties are available.
mono: booleansolo: booleanmute: booleanlabel: stringgain: float, -60 to 12A1 - A5,B1 - B3: booleanlimit: int, from -40 to 12
example:
vban.strip[3].gain = 3.7
print(vban.strip[0].label)
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:
vban.strip[5].appmute('Spotify', True)
vban.strip[5].appgain('Spotify', 0.5)
Strip.Comp
The following properties are available.
knob: float, from 0.0 to 10.0gainin: float, from -24.0 to 24.0ratio: float, from 1.0 to 8.0threshold: float, from -40.0 to -3.0attack: float, from 0.0 to 200.0release: float, from 0.0 to 5000.0knee: float, from 0.0 to 1.0gainout: float, from -24.0 to 24.0makeup: boolean
example:
print(vban.strip[4].comp.knob)
Strip Comp knob is defined for all versions, all other parameters potato only.
Strip.Gate
The following properties are available.
knob: float, from 0.0 to 10.0threshold: float, from -60.0 to -10.0damping: float, from -60.0 to -10.0bpsidechain: int, from 100 to 4000attack: float, from 0.0 to 1000.0hold: float, from 0.0 to 5000.0release: float, from 0.0 to 5000.0
example:
vban.strip[2].gate.attack = 300.8
Strip Gate knob is defined for all versions, all other parameters potato only.
Strip.Denoiser
The following properties are available.
knob: float, from 0.0 to 10.0
strip.denoiser properties are defined as write only, potato version only.
Strip.EQ
The following properties are available.
on: booleanab: boolean
example:
vban.strip[0].eq.ab = True
Strip.EQ.Channel.Cell
The following properties are available.
on: booleantype: int, from 0 up to 6f: float, from 20.0 up to 20_000.0gain: float, from -36.0 up to 18.0q: float, from 0.3 up to 100
example:
vban.strip[0].eq.channel[0].cell[2].on = True
vban.strip[1].eq.channel[0].cell[2].f = 5000
Strip EQ parameters are defined for PhysicalStrips, potato version only.
Only channel[0] properties are readable over VBAN.
Gainlayers
gain: float, from -60.0 to 12.0
example:
vban.strip[3].gainlayer[3].gain = 3.7
Gainlayers are defined for potato version only.
Levels
The following properties are available.
prefader
example:
print(vban.strip[3].levels.prefader)
Level properties will return -200.0 if no audio detected.
Bus
The following properties are available.
mono: booleanmute: booleanlabel: stringgain: float, -60 to 12
example:
print(vban.bus[0].label)
Bus.EQ
The following properties are available.
on: booleanab: boolean
vban.bus[4].eq.on = true
Modes
The following properties are available.
normal: booleanamix: booleanbmix: booleancomposite: booleantvmix: booleanupmix21: booleanupmix41: booleanupmix61: booleancenteronly: booleanlfeonly: booleanrearonly: boolean
The following methods are available.
get(): Returns the current bus mode
example:
vban.bus[4].mode.amix = True
print(vban.bus[2].mode.get())
Levels
The following properties are available.
all
example:
print(vban.bus[0].levels.all)
levels.all will return -200.0 if no audio detected.
Strip | Bus
The following methods are available.
fadeto(amount, time): float, intfadeby(amount, time): float, int
Modify gain to or by the selected amount in db over a time interval in ms.
example:
vban.strip[0].fadeto(-10.3, 1000)
vban.bus[3].fadeby(-5.6, 500)
Recorder
The following methods are available
play()stop()pause()record()ff()rew()load(filepath): raw stringgoto(time_string): time string in formathh:mm:ss
The following properties are available
samplerate: int, (22050, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000)bitresolution: int, (8, 16, 24, 32)channel: int, from 1 to 8kbps: int, (32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320)gain: float, from -60.0 to 12.0
example:
vban.recorder.play()
vban.recorder.stop()
# filepath as raw string
vban.recorder.load(r'C:\music\mytune.mp3')
# set the goto time to 1m 30s
vban.recorder.goto('00:01:30')
Command
Certain 'special' commands are defined by the API as performing actions rather than setting values. The following methods are available:
show(): Bring Voiceemeter GUI to the frontshutdown(): Shuts down the GUIrestart(): Restart the audio enginereset(): Applies theresetconfig. (phys strip B1, virt strip A1, gains, comp, gate 0.0, mute, mono, solo, eq false)
The following properties are write only and accept boolean values.
showvbanchat: booleanlock: boolean
example:
vban.command.restart()
vban.command.showvbanchat = true
Multiple parameters
applySet many strip/bus parameters at once, for example:
vban.apply(
{
'strip-0': {'A1': True, 'B1': True, 'gain': -6.0},
'bus-1': {'mute': True, 'mode': 'composite'},
'bus-2': {'eq': {'on': True}},
'vban-in-0': {'on': True},
}
)
Or for each class you may do:
vban.strip[0].apply({'mute': True, 'gain': 3.2, 'A1': True})
vban.vban.outstream[0].apply({'on': True, 'name': 'streamname', 'bit': 24})
Config Files
vban.apply_config(<configname>)
You may load config files in TOML format. Three example configs have been included with the package. Remember to save current settings before loading a user config. To load one you may do:
import vban_cmd
with vban_cmd.api('banana') as vban:
vban.apply_config('example')
will load a config file at configs/banana/example.toml for Voicemeeter Banana.
Your configs may be located in one of the following paths:
- <current working directory> / "configs" / kind_id
- <user home directory> / ".config" / "vban-cmd" / kind_id
- <user home directory> / "Documents" / "Voicemeeter" / "configs" / kind_id
If a config with the same name is located in multiple locations, only the first one found is loaded into memory, in the above order.
config extends
You may also load a config that extends another config with overrides or additional parameters.
You just need to define a key extends in the config TOML, that names the config to be extended.
Three example 'extender' configs are included with the repo. You may load them with:
import vban_cmd
with vban_cmd.api('banana') as vm:
vm.apply_config('extender')
Events
Level updates are considered high volume, by default they are NOT listened for. Use subs keyword arg to initialize event updates.
example:
import vban_cmd
opts = {
'host': '<ip address>',
'streamname': 'Command1',
'port': 6980,
}
with vban_cmd.api('banana', ldirty=True, **opts) as vban:
...
vban.subject
Use the Subject class to register an app as event observer.
The following methods are available:
add: registers an app as an event observerremove: deregisters an app as an event observer
example:
# register an app to receive updates
class App():
def __init__(self, vban):
vban.subject.add(self)
...
vban.event
Use the event class to toggle updates as necessary.
The following properties are available:
pdirty: booleanldirty: boolean
example:
vban.event.ldirty = True
vban.event.pdirty = False
Or add, remove a list of events.
The following methods are available:
add()remove()get()
example:
vban.event.remove(['pdirty', 'ldirty'])
# get a list of currently subscribed
print(vban.event.get())
VbanCmd class
vban_cmd.api(kind_id: str, **opts)
You may pass the following optional keyword arguments:
host: str='localhost', ip or hostname of remote machineport: int=6980, vban udp port of remote machine.streamname: str='Command1', name of the stream to connect to.bps: int=256000, bps rate of the stream.channel: int=0, channel on which to send the UDP requests.pdirty: boolean=False, parameter updatesldirty: boolean=False, level updatesscript_ratelimit: float=0.05, default to 20 script requests per second. This affects vban.sendtext() specifically.timeout: int=5, timeout for socket operations.disable_rt_listeners: boolean=False, setTrueif you don't wish to receive RT packets.- You can still send Matrix string requests ending with
?and receive a response.
- You can still send Matrix string requests ending with
vban.pdirty
True iff a parameter has been changed.
vban.ldirty
True iff a level value has been changed.
vban.sendtext(script)
Sends a script block as a string request, for example:
vban.sendtext('Strip[0].Mute=1;Bus[0].Mono=1')
You can even use it to send matrix commands:
vban.sendtext('Point(ASIO128.IN[1..4],ASIO128.OUT[1]).dBGain = -3.0')
vban.sendtext('Command.Version = ?')
Errors
errors.VBANCMDError: Base VBANCMD Exception class.errors.VBANCMDConnectionError: Exception raised when connection/timeout errors occur.
Logging
It's possible to see the messages sent by the interface's setters and getters, may be useful for debugging.
example:
import vban_cmd
logging.basicConfig(level=logging.DEBUG)
opts = {'host': 'localhost', 'port': 6980, 'streamname': 'Command1'}
with vban_cmd.api('banana', **opts) as vban:
...
Run tests
Install poetry and then:
poetry poe test-basic
poetry poe test-banana
poetry poe test-potato