mirror of
https://github.com/onyx-and-iris/voicemeeter-api-powershell.git
synced 2026-01-24 17:27:48 +00:00
update obs vm sync example
This commit is contained in:
parent
d51ffacfaf
commit
fc75bc2020
293
examples/obs/Sync-OBS-Voicemeeter.ps1
Normal file
293
examples/obs/Sync-OBS-Voicemeeter.ps1
Normal file
@ -0,0 +1,293 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Synchronizes OBS Studio scene changes with Voicemeeter audio settings.
|
||||
|
||||
.DESCRIPTION
|
||||
This script monitors OBS Studio for scene changes via WebSocket connection and
|
||||
automatically adjusts Voicemeeter audio settings based on the active scene.
|
||||
|
||||
.PARAMETER ConfigPath
|
||||
Path to the configuration file. Defaults to 'config.psd1' in the script directory.
|
||||
|
||||
.PARAMETER VoicemeeterKind
|
||||
Type of Voicemeeter to connect to. Defaults to 'basic'.
|
||||
|
||||
.EXAMPLE
|
||||
.\Vm-Obs-Sync.ps1
|
||||
|
||||
.EXAMPLE
|
||||
.\Vm-Obs-Sync.ps1 -ConfigPath "C:\myconfig.psd1" -VoicemeeterKind "banana"
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$ConfigPath = (Join-Path $PSScriptRoot 'config.psd1'),
|
||||
[ValidateSet('basic', 'banana', 'potato')]
|
||||
[string]$VoicemeeterKind = 'basic'
|
||||
)
|
||||
|
||||
#Requires -Modules obs-powershell
|
||||
|
||||
# Import required modules
|
||||
try {
|
||||
Import-Module ..\..\lib\Voicemeeter.psm1
|
||||
Import-Module obs-powershell
|
||||
}
|
||||
catch {
|
||||
Write-Error "Failed to import required modules: $($_.Exception.Message)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Script-level variables
|
||||
$script:vmr = $null
|
||||
$script:obsJob = $null
|
||||
$script:shouldExit = $false
|
||||
|
||||
#region Helper Functions
|
||||
|
||||
function Write-Log {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Writes timestamped log messages to the console.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory, ValueFromPipeline)]
|
||||
[string]$Message,
|
||||
[ValidateSet('Info', 'Warning', 'Error')]
|
||||
[string]$Level = 'Info'
|
||||
)
|
||||
|
||||
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
|
||||
$logMessage = "[$timestamp] [$Level] $Message"
|
||||
|
||||
switch ($Level) {
|
||||
'Info' { Write-Information $logMessage -InformationAction Continue }
|
||||
'Warning' { Write-Warning $logMessage }
|
||||
'Error' { Write-Error $logMessage }
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ConnectionConfig {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Loads OBS connection configuration from file.
|
||||
#>
|
||||
param([string]$Path = $ConfigPath)
|
||||
|
||||
try {
|
||||
if (-not (Test-Path $Path)) {
|
||||
throw "Configuration file not found: $Path"
|
||||
}
|
||||
|
||||
$config = Import-PowerShellDataFile -Path $Path -ErrorAction Stop
|
||||
|
||||
# Validate required properties
|
||||
$requiredProperties = @('host', 'port', 'password')
|
||||
foreach ($prop in $requiredProperties) {
|
||||
if (-not $config.ContainsKey($prop)) {
|
||||
throw "Missing required configuration property: $prop"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log "Configuration loaded successfully from: $Path"
|
||||
return $config
|
||||
}
|
||||
catch {
|
||||
Write-Log "Failed to load configuration: $($_.Exception.Message)" -Level Error
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
||||
function Initialize-Connections {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Initializes connections to Voicemeeter and OBS.
|
||||
#>
|
||||
try {
|
||||
$script:vmr = Connect-Voicemeeter -Kind $VoicemeeterKind -ErrorAction Stop
|
||||
Write-Log 'Voicemeeter connection established'
|
||||
|
||||
$obsConfig = Get-ConnectionConfig
|
||||
|
||||
|
||||
$webSocketUri = "ws://$($obsConfig.host):$($obsConfig.port)"
|
||||
$script:obsJob = Watch-OBS -WebSocketURI $webSocketUri -WebSocketToken $obsConfig.password -ErrorAction Stop
|
||||
Write-Log "OBS connection at $webSocketUri established"
|
||||
}
|
||||
catch {
|
||||
Write-Log "Failed to initialize connections: $($_.Exception.Message)" -Level Error
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
||||
function Disconnect-All {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Safely disconnects from all services.
|
||||
#>
|
||||
Write-Log 'Cleaning up connections...'
|
||||
|
||||
try {
|
||||
if ($script:obsJob) {
|
||||
Remove-Job -Job $script:obsJob -Force -ErrorAction SilentlyContinue
|
||||
Disconnect-OBS -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Log "Error disconnecting from OBS: $($_.Exception.Message)" -Level Warning
|
||||
}
|
||||
|
||||
try {
|
||||
if ($script:vmr) {
|
||||
Disconnect-Voicemeeter -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Log "Error disconnecting from Voicemeeter: $($_.Exception.Message)" -Level Warning
|
||||
}
|
||||
|
||||
Write-Log 'Cleanup completed'
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
function Invoke-CurrentProgramSceneChanged {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Handles OBS scene change events.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[System.Object]$EventData
|
||||
)
|
||||
|
||||
if (-not $EventData.sceneName) {
|
||||
Write-Log 'Scene change event received but no scene name provided' -Level Warning
|
||||
return
|
||||
}
|
||||
|
||||
Write-Log "Scene changed to: $($EventData.sceneName)"
|
||||
|
||||
try {
|
||||
switch ($EventData.sceneName) {
|
||||
'START' {
|
||||
Write-Log 'Toggling mute for strip 0'
|
||||
$script:vmr.strip[0].mute = !$script:vmr.strip[0].mute
|
||||
}
|
||||
'BRB' {
|
||||
Write-Log 'Setting gain to -8.3dB for strip 0'
|
||||
$script:vmr.strip[0].gain = -8.3
|
||||
}
|
||||
'END' {
|
||||
Write-Log 'Enabling mono for strip 0'
|
||||
$script:vmr.strip[0].mono = $true
|
||||
}
|
||||
'LIVE' {
|
||||
Write-Log 'Setting color_x to 0.3 for strip 0'
|
||||
$script:vmr.strip[0].color_x = 0.3
|
||||
}
|
||||
default {
|
||||
Write-Log "Unknown scene '$($EventData.sceneName)'. Expected: START, BRB, END, or LIVE" -Level Warning
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Log "Error processing scene change: $($_.Exception.Message)" -Level Error
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-ExitStarted {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Handles OBS exit events.
|
||||
#>
|
||||
param([System.Object]$EventData)
|
||||
|
||||
Write-Log 'OBS shutdown detected - initiating graceful exit'
|
||||
$script:shouldExit = $true
|
||||
}
|
||||
|
||||
function Invoke-EventDispatcher {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Dispatches OBS events to appropriate handlers.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[System.Object]$EventData
|
||||
)
|
||||
|
||||
if (-not $EventData.eventType) {
|
||||
Write-Log 'Event received without eventType property' -Level Warning
|
||||
return
|
||||
}
|
||||
|
||||
$handlerName = "Invoke-$($EventData.eventType)"
|
||||
|
||||
if (Get-Command $handlerName -ErrorAction SilentlyContinue) {
|
||||
try {
|
||||
& $handlerName -EventData $EventData.eventData
|
||||
}
|
||||
catch {
|
||||
Write-Log "Error in event handler '$handlerName': $($_.Exception.Message)" -Level Error
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Log "No handler found for event type: $($EventData.eventType)" -Level Warning
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Main Execution
|
||||
|
||||
function Start-VoicemeeterObsSync {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Main execution function for the sync process.
|
||||
#>
|
||||
Write-Log 'Starting Voicemeeter-OBS synchronization service'
|
||||
|
||||
try {
|
||||
Initialize-Connections
|
||||
|
||||
Write-Log 'Monitoring OBS events... Press Ctrl+C to stop'
|
||||
|
||||
while (-not $script:shouldExit) {
|
||||
try {
|
||||
$obsEvents = Receive-Job -Job $script:obsJob -ErrorAction SilentlyContinue
|
||||
|
||||
foreach ($obsEvent in $obsEvents) {
|
||||
if ($obsEvent.MessageData.op -eq 5) {
|
||||
Invoke-EventDispatcher -EventData $obsEvent.MessageData.d
|
||||
}
|
||||
}
|
||||
|
||||
Start-Sleep -Milliseconds 100
|
||||
}
|
||||
catch {
|
||||
Write-Log "Error processing OBS events: $($_.Exception.Message)" -Level Error
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Log "Fatal error: $($_.Exception.Message)" -Level Error
|
||||
exit 1
|
||||
}
|
||||
finally {
|
||||
Disconnect-All
|
||||
}
|
||||
|
||||
Write-Log 'Voicemeeter-OBS synchronization service stopped'
|
||||
}
|
||||
|
||||
# Handle Ctrl+C gracefully
|
||||
$null = Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {
|
||||
$script:shouldExit = $true
|
||||
}
|
||||
|
||||
Start-VoicemeeterObsSync
|
||||
|
||||
#endregion
|
||||
@ -1,68 +0,0 @@
|
||||
[cmdletbinding()]
|
||||
param()
|
||||
|
||||
Import-Module ..\..\lib\Voicemeeter.psm1
|
||||
Import-Module obs-powershell
|
||||
|
||||
function CurrentProgramSceneChanged {
|
||||
param([System.Object]$data)
|
||||
Write-Host 'Switched to scene', $data.sceneName
|
||||
|
||||
switch ($data.sceneName) {
|
||||
'START' {
|
||||
$vmr.strip[0].mute = !$vmr.strip[0].mute
|
||||
}
|
||||
'BRB' {
|
||||
$vmr.strip[0].gain = -8.3
|
||||
}
|
||||
'END' {
|
||||
$vmr.strip[0].mono = $true
|
||||
}
|
||||
'LIVE' {
|
||||
$vmr.strip[0].color_x = 0.3
|
||||
}
|
||||
default { 'Expected START, BRB, END or LIVE scene' | Write-Warning; return }
|
||||
}
|
||||
}
|
||||
|
||||
function ExitStarted {
|
||||
param([System.Object]$data)
|
||||
'OBS shutdown has begun!' | Write-Host
|
||||
break
|
||||
}
|
||||
|
||||
function eventHandler($data) {
|
||||
if (Get-Command $data.eventType -ErrorAction SilentlyContinue) {
|
||||
& $data.eventType -data $data.eventData
|
||||
}
|
||||
}
|
||||
|
||||
function ConnFromFile {
|
||||
$configpath = Join-Path $PSScriptRoot 'config.psd1'
|
||||
return Import-PowerShellDataFile -Path $configpath
|
||||
}
|
||||
|
||||
function main {
|
||||
$vmr = Connect-Voicemeeter -Kind 'basic'
|
||||
|
||||
$conn = ConnFromFile
|
||||
$job = Watch-OBS -WebSocketURI "ws://$($conn.host):$($conn.port)" -WebSocketToken $conn.password
|
||||
|
||||
try {
|
||||
while ($true) {
|
||||
Receive-Job -Job $job | ForEach-Object {
|
||||
$data = $_.MessageData
|
||||
|
||||
if ($data.op -eq 5) {
|
||||
eventHandler($data.d)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
Disconnect-OBS
|
||||
Disconnect-Voicemeeter
|
||||
}
|
||||
}
|
||||
|
||||
main
|
||||
Loading…
x
Reference in New Issue
Block a user