mirror of
https://github.com/onyx-and-iris/duckypad-twitch.git
synced 2026-04-20 01:13:30 +00:00
Compare commits
2 Commits
21775e5066
...
upd-fadein
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f045c00fd | |||
| 36ffdb5c61 |
@@ -29,23 +29,22 @@ We use a triple pc streaming setup, one gaming pc for each of us and a third pc
|
||||
|
||||
- Both of our microphones, as well as both gaming pc are wired into an [MR18 mixer][mr18] which itself is connected to the streaming pc.
|
||||
- Then we vban our microphones from the workstation off to each of our pcs in order to talk in-game. All audio is routed through [Voicemeeter][voicemeeter].
|
||||
- Voicemeeter is connected to Studio ONE daw for background noise removal. Any voice communication software (such as Discord) is therefore installed onto the workstation, separate of our gaming pcs.
|
||||
- Voicemeeter is connected to Studio ONE daw for live processing. Any voice communication software (such as Discord) is therefore installed onto the workstation, separate of our gaming pcs.
|
||||
|
||||
If you've ever attempted to setup a dual pc streaming setup, you may appreciate the challenges of a triple pc setup.
|
||||
|
||||
## Details about the code
|
||||
|
||||
This package is for demonstration purposes only. Several of the interfaces on which it depends have been tightly coupled into a duckypad macros program.
|
||||
This package is for demonstration purposes only. Several of the interfaces on which it depends have been merged into a duckypad macros program.
|
||||
|
||||
- The package entry point can be found at `duckypad_twitch.macros.duckypad`.
|
||||
- A base DuckyPad class in duckypad.py is used to connect the various layers of the driver.
|
||||
- Most of the audio routing for the dual stream is handled in the `Audio class` in audio.py with the aid of Voicemeeter's Remote API.
|
||||
- Some communication with the Xair mixer and the vban protocol can also be found in this class.
|
||||
- Some communication with the XAir mixer and the vban protocol can also be found in this class.
|
||||
- Scene switching and some audio routing are handled in the `Scene class` in scene.py.
|
||||
- A `OBSWS` class is used to communicate with OBS websocket.
|
||||
- Dataclasses are used to hold internal states and states are updated using event callbacks.
|
||||
- Decorators are used to confirm websocket connections.
|
||||
- A separate OBSWS class is used to handle scenes and mic muting (for a single pc stream).
|
||||
- Logging is included to help with debugging but also to provide stream information in real time.
|
||||
|
||||
## License
|
||||
|
||||
@@ -264,14 +264,29 @@ class Audio(ILayer):
|
||||
|
||||
### Workstation and TV Audio Routing via VBAN ###
|
||||
|
||||
def _fade_mixer(self, target_fader, fade_in=True):
|
||||
"""Fade the mixer's fader to the target level."""
|
||||
current_fader = self.mixer.lr.mix.fader
|
||||
step = 1 if fade_in else -1
|
||||
while (fade_in and current_fader < target_fader) or (not fade_in and current_fader > target_fader):
|
||||
current_fader += step
|
||||
self.mixer.lr.mix.fader = current_fader
|
||||
time.sleep(0.05)
|
||||
def __fadein_main(self, target_level: float, duration: float = 5.0):
|
||||
current_level = self.mixer.lr.mix.fader
|
||||
level_difference = abs(target_level - current_level)
|
||||
steps = max(10, min(100, int(level_difference)))
|
||||
step_duration = duration / steps
|
||||
level_step = (target_level - current_level) / steps
|
||||
|
||||
for _ in range(steps):
|
||||
current_level += level_step
|
||||
self.mixer.lr.mix.fader = current_level
|
||||
time.sleep(step_duration)
|
||||
|
||||
def __fadeout_main(self, target_level: float, duration: float = 5.0):
|
||||
current_level = self.mixer.lr.mix.fader
|
||||
level_difference = abs(current_level - target_level)
|
||||
steps = max(10, min(100, int(level_difference)))
|
||||
step_duration = duration / steps
|
||||
level_step = (current_level - target_level) / steps
|
||||
|
||||
for _ in range(steps):
|
||||
current_level -= level_step
|
||||
self.mixer.lr.mix.fader = current_level
|
||||
time.sleep(step_duration)
|
||||
|
||||
def _toggle_workstation_routing(self, state_attr, target_name, vban_config_key):
|
||||
"""Toggle routing of workstation audio to either Onyx or Iris via VBAN."""
|
||||
@@ -287,14 +302,14 @@ class Audio(ILayer):
|
||||
vban.vban.instream[6].on = True
|
||||
self.vm.strip[5].gain = -6
|
||||
self.vm.vban.outstream[2].on = True
|
||||
self._fade_mixer(-90, fade_in=False)
|
||||
self.__fadeout_main(-90)
|
||||
self.logger.info(f'Workstation audio routed to {target_name}')
|
||||
else:
|
||||
with vban_cmd.api('potato', outbound=True, **target_conn) as vban:
|
||||
vban.vban.instream[6].on = False
|
||||
self.vm.strip[5].gain = 0
|
||||
self.vm.vban.outstream[2].on = False
|
||||
self._fade_mixer(-36, fade_in=True)
|
||||
self.__fadein_main(-24)
|
||||
self.logger.info('Workstation audio routed back to monitor speakers')
|
||||
|
||||
def toggle_workstation_to_onyx(self):
|
||||
|
||||
Reference in New Issue
Block a user