https://github.com/KopiasCsaba/open_sound_control_bridge Skip to content Navigation Menu Toggle navigation Sign in * Product + GitHub Copilot Write better code with AI + Security Find and fix vulnerabilities + Actions Automate any workflow + Codespaces Instant dev environments + Issues Plan and track work + Code Review Manage code changes + Discussions Collaborate outside of code + Code Search Find more, search less Explore + All features + Documentation + GitHub Skills + Blog * Solutions By company size + Enterprises + Small and medium teams + Startups By use case + DevSecOps + DevOps + CI/CD + View all use cases By industry + Healthcare + Financial services + Manufacturing + Government + View all industries View all solutions * Resources Topics + AI + DevOps + Security + Software Development + View all Explore + Learning Pathways + White papers, Ebooks, Webinars + Customer Stories + Partners * Open Source + GitHub Sponsors Fund open source developers + The ReadME Project GitHub community articles Repositories + Topics + Trending + Collections * Enterprise + Enterprise platform AI-powered developer platform Available add-ons + Advanced Security Enterprise-grade security features + GitHub Copilot Enterprise-grade AI features + Premium Support Enterprise-grade 24/7 support * Pricing Search or jump to... Search code, repositories, users, issues, pull requests... Search [ ] Clear Search syntax tips Provide feedback We read every piece of feedback, and take your input very seriously. [ ] [ ] Include my email address so I can be contacted Cancel Submit feedback Saved searches Use saved searches to filter your results more quickly Name [ ] Query [ ] To see all available qualifiers, see our documentation. Cancel Create saved search Sign in Sign up Reseting focus You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. Dismiss alert {{ message }} KopiasCsaba / open_sound_control_bridge Public * * Notifications You must be signed in to change notification settings * Fork 0 * Star 44 An advanced automation framework for audio mixer consoles, OBS, PTZ cameras and more based on the Open Sound Control protocol. License MIT license 44 stars 0 forks Branches Tags Activity Star Notifications You must be signed in to change notification settings * Code * Issues 0 * Pull requests 0 * Actions * Projects 0 * Security * Insights Additional navigation options * Code * Issues * Pull requests * Actions * Projects * Security * Insights KopiasCsaba/open_sound_control_bridge main BranchesTags [ ] Go to file Code Folders and files Name Name Last commit Last commit message date Latest commit History 29 Commits .github .github docker docker docs/assets/ docs/assets/ readme readme src src .dockerignore .dockerignore .gitignore .gitignore LICENSE LICENSE Makefile Makefile README.md README.md View all files Repository files navigation * README * MIT license Table of contents * Open Sound Control Bridge + Example uses * Install + Docker * Overview * Configuration + Example configuration + Actions o Debouncing + Trigger chain o Conditions # OSC_MATCH: Check if a single message exists @ Trigger on change # AND: Require all children condition to resolve to true # OR: Require at least one children to resolve to true # NOT: Negate the single child's result. + Sources o Digital Mixing Consoles o Dummy console o OBS bridges o HTTP bridges o Tickers + Tasks o HTTP request o OBS Scene change o OBS Vendor message o Delay o Run command o Send OSC message * Development Open Sound Control Bridge OSCBridge is a tool to help automate operations with audio/streaming gear. Input could come from various sources, such as: * Digital Audio Mixer Console state (such as Behringer X32 or other that supports OSC) * OBS Studio state * A HTTP Request * Time OSCBridge currently supports the following "tasks": * HTTP Request * Delay (just wait) * OBS Change preview scene * OBS Change program scene * OBS Send "vendor" message to any plugin that cares, e.g. to the amazingly excellent Advanced Scene Switcher. * Excecute a command * Send an OSC message Example uses Here is just a few idea: * When a microphone is unmuted, turn the PTZ camera to the speaker. * When the stage is unmuted, turn the PTZ camera to the stage. * When a special HTTP request arrives, mute/unmute something. * When a special HTTP request arrives, set the volume of a channel to the specified value. * At a specified time, unmute a microphone. * At a specified time, switch to an OBS Scene. * At a specified time, send an HTTP Request. * When something is unmuted, switch to a scene in OBS. * When a scene is activated in OBS unmute certain channels. * When a microphone is unmuted, then turn the camera but only if a ceratin OBS scene is active. * When ... send a command to Advanced Scene Switcher, to do a zillion other things * When ... then make Advanced Scene Switcher do an http request to execute some other actions through the oscbridge. ( Btw A.S.S. can send OSC messages too.) I think now you got the point! Install * Download the binary from the latest release * Create a config.yml next to the binary. * Execute! $:oscbridge$ ls config.yml oscbridge-6acaf3b4-linux-amd64.bin $:oscbridge$ chmod +x oscbridge-6acaf3b4-linux-amd64.bin $:oscbridge$ ./oscbridge-6acaf3b4-linux-amd64.bin 2023-11-13 07:30:51 [ INFO] OPEN SOUND CONTROL BRIDGE is starting. 2023-11-13 07:30:51 [ INFO] Version: v1.0.0 Revision: 6acaf3b4 2023-11-13 07:30:51 [ INFO] Initializing OBS connections... 2023-11-13 07:30:51 [ INFO] Connecting to streaming_pc_obs... 2023-11-13 07:30:51 [ INFO] Initializing OBS bridges... 2023-11-13 07:30:51 [ INFO] Initializing Open Sound Control (mixer consoles, etc) connections... ... You may override the config.yml location with the environment variable APP_CONFIG_FILE, e.g.: APP_CONFIG_FILE=/a/b/c/d/osc.yml. Docker A docker-hub version will be coming soon when my time permits. Overview From a birds eye view, oscbridge provides a central "message store", to which "osc sources" can publish messages. Every time a new message arrives, each action is checked, if their trigger_chain conditions are resolving to true based on the current store. If every the trigger chain resolves to true, then the action's tasks are executed. So this is the control flow: [OSC SOURCES] -> [OSC MESSAGE STORE] -> [ACTION TRIGGER CHAIN] -> [ACTION TASK] Configuration Example configuration Below is the simplest example to showcase how the system works. Click to see YAML obs_connections: - name: "streaming_pc_obs" host: 192.168.1.75 port: 4455 password: "foobar" osc_sources: console_bridges: - name: "behringer_x32" enabled: false prefix: "" host: 192.168.2.99 port: 10023 osc_implementation: l init_command: address: /xinfo check_address: /ch/01/mix/on check_pattern: "^0|1$" subscriptions: - osc_command: address: /subscribe arguments: - type: string value: /ch/01/mix/on - type: int32 value: 10 repeat_millis: 8000 dummy_connections: - name: "behringer_x32_dummy" enabled: true prefix: "" iteration_speed_secs: 1 message_groups: - name: mic_1_on osc_commands: - address: /ch/01/mix/on comment: "headset mute (0: muted, 1: unmuted)" arguments: - type: int32 value: 1 - name: mic_1_off osc_commands: - address: /ch/01/mix/on comment: "headset mute (0: muted, 1: unmuted)" arguments: - type: int32 value: 0 actions: to_pulpit: trigger_chain: type: osc_match parameters: address: /ch/01/mix/on arguments: - index: 0 type: "int32" value: "1" tasks: - type: http_request parameters: url: "http://127.0.0.1:8888/cgi-bin/ptzctrl.cgi?ptzcmd&poscall&0&__TURN_TO_PULPIT" method: "get" timeout_secs: 1 - type: obs_scene_change parameters: scene: "PULPIT" scene_match_type: regexp target: "program" connection: "streaming_pc_obs" - type: obs_scene_change parameters: scene: "STAGE" scene_match_type: regexp target: "preview" connection: "streaming_pc_obs" to_stage: trigger_chain: type: osc_match parameters: address: /ch/01/mix/on arguments: - index: 0 type: "int32" value: "0" tasks: - type: http_request parameters: url: "http://127.0.0.1:8888/cgi-bin/ptzctrl.cgi?ptzcmd&poscall&1&__TURN_TO_STAGE" method: "get" timeout_secs: 1 - type: obs_scene_change parameters: scene: "STAGE" scene_match_type: regexp target: "program" connection: "streaming_pc_obs" - type: obs_scene_change parameters: scene: "PULPIT" scene_match_type: regexp target: "preview" connection: "streaming_pc_obs" In this configuration there are two OSC sources: * Dummy (enabled) * A Behringer X32 digital console (disabled) The dummy source acts as if someone would press Ch1's mute button every second to toggle it. Then there are two actions defined, "to_pulpit" and "to_stage". Each has a single trigger, that matches /ch/01/mix/on to be 0 or 1. Then for each action, there are three tasks: * An HTTP request that would recall a PTZ Optics camera preset (0 and 1 respectively). * An obs_scene_change to change the program scene. * An obs_scene_change to change the preview scene. You can see the results on this gif: [example_config] OBS is switching scenes based on the mute status, and at the bottom you can see the arriving requests. You can just switch from the dummy to the console one, and your mute button is then tied to OBS scenes and the camera. Actions Actions encapsulate a so called trigger_chain and a list of tasks together. This is how actions look like: actions: change_to_pulpit: trigger_chain: # ... tree of conditions tasks: # ... 1 dimensional list of tasks to be executed in order, serially change_to_stage: trigger_chain: # ... tree of conditions tasks: # ... 1 dimensional list of tasks to be executed in order, serially start_live_stream: trigger_chain: # ... tree of conditions tasks: # ... 1 dimensional list of tasks to be executed in order, serially Each action has it's own name, that is shown in the logs upon evaluation/execution. Whenever the internal store receives an update, OSCBridge checks each action's trigger_chain, the tree of conditions if they match the store or not. If the trigger_chain is evaluated to be true, then the tasks will be executed. Debouncing There is an option, that can be specified for each action, called debounce_millis, if provided then the logic changes a bit. Upon store change, if the trigger_chain resolves to true, then after the specified ammount of milliseconds the trigger_chain is re-evaluated. If it is still true, only then will the tasks be executed. For example: actions: change_to_pulpit: trigger_chain: # ... tree of conditions tasks: # ... 1 dimensional list of tasks to be executed in order, serially debounce_millis: 500 This could protect against quick transients, e.g. an accidental unmute/mute. For example here, if the trigger chain is watching for ch1's unmute, then it will only execute the tasks if it is unmute for more than 0.5seconds. This can help avoid accidents, where you accidentally unmute something but then you immediately mute it back. Trigger chain The trigger chain is a tree of conditions. Some conditions can be nested, some of them are just leafs on a tree, without any children. You can build very complex conditions into here, e.g. (in pseudo code): IF (mic1-is-muted AND mic2-is-unmuted) OR (ch10-is-unmuted AND ( ch11fader > 0.5 OR ch12fader > 0.5 ) ) THEN ... But the way to express these are a bit more complicated due to the YAML configuration we use. Conditions OSC_MATCH: Check if a single message exists The osc_match condition can nothave any children, and it is checking for a single message in the store. It can check based on address, address regexp and also based on arguments. Here is an example: actions: change_to_pulpit: trigger_chain: - type: osc_match parameters: address: /ch/01/mix/on arguments: - index: 0 type: "int32" value: "1" tasks: # ... This is a single condition on an action's trigger_chain. This checks for a message with an exact address of "/ch/01/mix/on" and with a single first argument, that is int32 and the value is 1. If such a message exists in the store, the tasks will be executed. Parameters: Parameter Default Possible Description Example value values values The value for matching /ch/01/ address none, a message's address. mix/on, / required Can be a regexp, see ch/0[0-9] next option. /mix/on address_match_type eq eq, Determines the way of regexp regexp address matching. trigger_on_change true true, See the trigger on true false change paragraph. arguments none, See the next table. List of optional arguments Arguments: Parameter Default Possible Description Example value values values index none, 0 The 0 based index for the 0, 1, 2 required argument. none, string, type required int32, The type of the argument. string float32 value none, The value of the argument. 1 required regexp, The comparison method. In value_match_type = <=,<,>,> case of regexp, the value = =,!= can be a regexp expression. Trigger on change The trigger_on_change option is a special one. Whenever a new message arrives that changes the store, every trigger_chain is checked. Now, during the execution of the trigger_chain, it is being monitored what messages those conditions accessed. By default (when trigger_on_change: true) if the trigger chain did not access the NEWLY UPDATED message, so the one that just arrived, the tasks aren't going to be executed. This avoids unneccessary re-execution just because an unrelevant message updated the store. But this is also usable, to avoid re-execution in a case when a relevant message updated the store. Practically this option decouples a condition from being a trigger. The condition is still required to match in order to execute the tasks, but that single condition's change will not trigger execution. You want to set this to false, when you don't want to re-execute the action upon the toggling of one of the parameters your trigger_chain is watching for. This is an edge case, that comes handy sometimes. For example, let's say you have the following trigger_chain (in pseudo-ish code): IF ( OBS-scene-name-contains-foobar AND OR (ch1-unmuted OR ch2-unmuted OR stage-is-muted) ) THEN ... So you want to only execute the tasks, when certain things on the console match, but don't wanna re-execute just because of an OBS scene change. But you only want to execute the tasks, when certain things on the console match AND obs scene name contains foobar. Then you can mark the OBS-scene-name-contains condition with trigger_on_change: false. That will cause the tasks to be executed when the console state changes (and obs scene contains foobar), but will not trigger if only obs changes would otherwise match. E.g. you might switch from one scene to another that contains foobar in our pseudo example, but that would not re-execute the tasks. AND: Require all children condition to resolve to true And as it's name implies requires all children to resolve to true. The following example action requires both ch1 AND ch2 to be on. actions: change_to_pulpit: trigger_chain: type: and children: - type: osc_match parameters: address: /ch/01/mix/on arguments: - index: 0 type: "int32" value: "1" - type: osc_match parameters: address: /ch/02/mix/on arguments: - index: 0 type: "int32" value: "1" tasks: # ... Now you see how conditions can be nested. OR: Require at least one children to resolve to true Or as it's name implies requires that at least one of the childrens would resolve to true. The following example action executes the tasks if ch1 OR ch2 is be on. actions: change_to_pulpit: trigger_chain: type: or children: - type: osc_match parameters: address: /ch/01/mix/on arguments: - index: 0 type: "int32" value: "1" - type: osc_match parameters: address: /ch/02/mix/on arguments: - index: 0 type: "int32" value: "1" tasks: # ... NOT: Negate the single child's result. The NOT condition simply negates it's single child's result. Here is how you would achieve this pseudo code: AND(ch1-unmuted; NOT(OR(ch10-unmuted,ch20-unmuted))) In yaml: actions: change_to_pulpit: trigger_chain: type: and children: - type: osc_match parameters: address: /ch/01/mix/on arguments: - index: 0 type: "int32" value: "1" - type: not children: - type: or children: - type: osc_match parameters: address: /ch/10/mix/on arguments: - index: 0 type: "int32" value: "1" - type: osc_match parameters: address: /ch/20/mix/on arguments: - index: 0 type: "int32" value: "1" tasks: # ... Sources Now that you know how to compose conditions, you need input sources, that would add messages to the internal store, against which you can match your trigger chains. Digital Mixing Consoles Many digital mixing consoles support a protocol called "Open Sound Control", this is a UDP based simple protocol. It is based on "Messages", where each message has an address, and 0 or more arguments, and each argument can be a string, a float, an int, etc. I have tested on Behringer X32, so most examples are based on this console. See pmalliot's excellent work here on X32's OSC implementation. In the case of X32, we need to regularly(8-10 sec) issue a /subscribe command with proper arguments, to show that we are interested in updates of a certain value from the console. Then the mixer is flooding us with the requested parameter. So below is a real world example for behringer x32 OSC connection: Click to see YAML osc_sources: console_bridges: # The name of this mixer - name: "behringer_x32" # If enabled, OSCBRIDGE will try to connect, and restart if fails. enabled: true # Prefix determines the message address prefix as it will be stored to the store. # E.g. if you'd have multiple consoles, you could prefix them "/console1", "/console2", # and you could match for /console1/ch/01/mix/on for example. prefix: "" host: 192.168.2.99 port: 10023 # The driver to use. We only have "l" for now. osc_implementation: l # This command is sent right after the connection is opened. # It can be used for authentication, or anything that is required. # X32 does not require anything, but for this it returns it's own name. init_command: address: /xinfo # You could specify arguments also. # arguments: # - type: string # value: "foobar" # There is a regular query running, for checking if the connection is still alive. # Specify an address here, and a regexp that matches the returned value. # If there is no response, or the response doesn't match, the connection is counted as broken and the app restarts. check_address: /ch/01/mix/on check_pattern: "^0|1$" # Subscriptions are commands that are sent regularly (repeat_millis) that cause the mixer to update us with the lates values for the subscribed thing. # Research your own mixer for the exact syntax, but this is how you do it for X32. subscriptions: - osc_command: # This command subscribes for channel 1's mute status. 0 is muted, 1 is unmuted. address: /subscribe arguments: - type: string value: /ch/01/mix/on - type: int32 value: 10 repeat_millis: 8000 Dummy console The dummy console implementation is just what it's name implies. It has message_groups, and each message_group contains messages. The dummy console iterates infinitely through the groups, and executes the messages in them. Between each group it waits the configured ammount of time. The below example configures two groups, called "mic_1_on" and "mic_1_off". Therefore, it provides a way to test the logic even without a real connection to a mixer. You can have a dummy emitting the same messages the real console would, and you can freely enable/disable any source, so you can test, or you can switch to the real operation mode by enabling the console connection. Click to see YAML osc_sources: dummy_connections: - name: "behringer_x32_dummy" # Use this source, or not. enabled: true # Prefix determines the message address prefix as it will be stored to the store. prefix: "" # How much delay should be between each group? iteration_speed_secs: 1 # Message groups are set of messages being emitted at once. message_groups: - name: mic_1_on osc_commands: - address: /ch/01/mix/on comment: "headset mute (0: muted, 1: unmuted)" arguments: - type: int32 value: 1 - name: mic_1_off osc_commands: - address: /ch/01/mix/on comment: "headset mute (0: muted, 1: unmuted)" arguments: - type: int32 value: 0 OBS bridges OSCBridge can be configured to connect to an OBS Studio instance via websocket, and it will subscribe to some events in OBS. These events are the following: * CurrentPreviewSceneChanged + Message: o Address: /obs/preview_scene o Argument[0]: string, value: NAME_OF_SCENE * CurrentProgramSceneChanged + Message: o Address: /obs/program_scene o Argument[0]: string, value: NAME_OF_SCENE * RecordStateChanged + Message: o Address: /obs/recording o Argument[0]: int32, value: 0 or 1 * StreamStateChanged + Message: o Address: /obs/streaming o Argument[0]: int32, value: 0 or 1 In order to configure an OBS Bridge, you'll also need to configure an OBS Connection. Click to see YAML obs_connections: - name: "streampc_obs" host: 192.168.1.75 port: 4455 password: "foobar12345" osc_sources: obs_bridges: - name: "obsbridge1" # You may choose to disable it. enabled: true # Prefix determines the message address prefix as it will be stored to the store. prefix: "" # The name of the obs connection, see above. connection: "streampc_obs" HTTP bridges HTTP Bridges in OSCBridge enables you to open a port on a network interface and start a HTTP server on them. The server can receive special HTTP GET requests, and converts them to OSC messages and stores them in the message store. Then you can write actions that check for that value, and may even execute tasks based on it. The message can be put away under some namespace by using the prefix option, but you could also use it to override an existing message. To insert an OSC Message like this: Message(address: /foo/bar/baz, arguments: [Argument(string:hello), Argument(int32:1)]) Execute a GET request like this: curl "127.0.0.1:7878/?address=/foo/bar/baz&args[]=string,hello&args[]=int32,1" Click to see YAML osc_sources: http_bridges: - name: "httpbridge1" # You may choose to disable it. enabled: true # Prefix determines the message address prefix as it will be stored to the store. prefix: "" port: 7878 host: 0.0.0.0 Tickers You can enable "Tickers", that would regularly update the store with messages representing the current date/time. The ticker publishes several packages under "/time/" (if you don't specify a prefix), with names that might be weird for the first time, if you are not familiar with how golang's time formatting works. You may see the full reference here. Currently these messages are being emitted in every iteration: Message(address: /time/rfc3339, arguments: [Argument(string:2023-11-07T08:53:06Z)]) Message(address: /time/parts/2006, arguments: [Argument(string:2023)]) Message(address: /time/parts/06, arguments: [Argument(string:23)]) Message(address: /time/parts/Jan, arguments: [Argument(string:Nov)]) Message(address: /time/parts/January, arguments: [Argument(string:November)]) Message(address: /time/parts/01, arguments: [Argument(string:11)]) Message(address: /time/parts/1, arguments: [Argument(string:11)]) Message(address: /time/parts/Mon, arguments: [Argument(string:Tue)]) Message(address: /time/parts/Monday, arguments: [Argument(string:Tuesday)]) Message(address: /time/parts/2, arguments: [Argument(string:7)]) Message(address: /time/parts/_2, arguments: [Argument(string: 7)]) Message(address: /time/parts/02, arguments: [Argument(string:07)]) Message(address: /time/parts/__2, arguments: [Argument(string:311)]) Message(address: /time/parts/002, arguments: [Argument(string:311)]) Message(address: /time/parts/15, arguments: [Argument(string:08)]) Message(address: /time/parts/3, arguments: [Argument(string:8)]) Message(address: /time/parts/03, arguments: [Argument(string:08)]) Message(address: /time/parts/4, arguments: [Argument(string:53)]) Message(address: /time/parts/04, arguments: [Argument(string:53)]) Message(address: /time/parts/5, arguments: [Argument(string:6)]) Message(address: /time/parts/05, arguments: [Argument(string:06)]) Message(address: /time/parts/PM, arguments: [Argument(string:AM)]) So if you want to match for hour:minute, then you want to match the values of /time/15 and /time/04 respectively in the trigger chain (to be explained later). Click to see YAML osc_sources: tickers: - name: "ticker1" # You may choose to disable it. enabled: true # Prefix determines the message address prefix as it will be stored to the store. prefix: "" # How often updates should occur refresh_rate_millis: 1000 Tasks Now you have actions, trigger_chains and sources, the final piece is to have tasks that will be executed if the trigger_chain evaluates to true. HTTP request The http_request task executes a specific http request upon evaluation. Parameters: Parameter Default Possible Description Example values value values none, The URL for url required the http://127.0.0.1/?foo=bar request. body empty The request {"json":"or something string body. else"} The timeout timeout_secs 30 for the 1 request. GET, The method method GET POST for the POST request. A list of headers empty "Key: - "Content-Type: text/json" value" - "X-Foo: bar" pairs. Example: actions: to_pulpit: trigger_chain: # ... tasks: - type: http_request parameters: url: "http://127.0.0.1:8888/cgi-bin/ptzctrl.cgi?ptzcmd&poscall&0&__TURN_TO_PULPIT" method: "get" timeout_secs: 1 headers: - "X-Foo: bar" - "X-Foo2: baz" body: "O HAI" The request that will be made: GET /cgi-bin/ptzctrl.cgi?ptzcmd&poscall&0&__TURN_TO_PULPIT HTTP/1.1 Host: 127.0.0.1:8888 User-Agent: Go-http-client/1.1 Content-Length: 5 X-Foo: bar X-Foo2: baz Accept-Encoding: gzip O HAI OBS Scene change The obs_scene_change task changes the live or program scene on a remote OBS instance. Parameters: Parameter Default Possible Description Example value values values none, The name of the scene PULPIT, scene required to which we need to STAGE switch. none, The name of the obs connection required connection that this streampc_obs task should use. scene_match_type exact exact, How to match the regexp regexp scene name. target none, program, Which side of OBS program required preview should be switched. Example: obs_connections: - name: "streampc_obs" host: 192.168.1.75 port: 4455 password: "foobar12345" actions: to_pulpit: trigger_chain: # ... tasks: - type: obs_scene_change parameters: scene: "PULPIT.*" scene_match_type: regexp target: "program" connection: "streaming_pc_obs" - type: obs_scene_change parameters: scene: "STAGE" scene_match_type: exact target: "preview" connection: "streaming_pc_obs" OBS Vendor message It is possible to send a VendorEvent to OBS via a websocket connection. Different plugins can listen for these events, one example is the marvelous Advanced Scene Switcher, which supports this. So given that you are listening in that plugin for "IF Websocket Message waas received: foobar_notice", you can execute macros remotely with OSCBridge: obs_connections: - name: "streampc_obs" host: 192.168.1.75 port: 4455 password: "foobar12345" actions: to_pulpit: trigger_chain: # ... tasks: - type: obs_vendor_request parameters: connection: "streampc_obs" vendorName: "AdvancedSceneSwitcher" requestType: "AdvancedSceneSwitcherMessage" requestData: message: "foobar_notice" Parameters: Parameter Default Description Example values value The name of the obs connection none, connection that streampc_obs required this task should use. vendorName none, AdvancedSceneSwitcher required requestType none, AdvancedSceneSwitcherMessage required requestData none, message: whatever required Delay The delay simply delays the serial execution of the tasks, taking up as much time as you configure. Parameters: Parameter Default Description Example values value delay_millis none, How much milliseconds to 1500 (for 1.5 required wait. second) Example: actions: to_pulpit: trigger_chain: # ... tasks: - type: delay parameters: delay_millis: 1500 Run command The run_command task simply executes the given command. Parameter Default Description Example values value none, The path to the command required binary to /usr/bin/bash execute. - "-l" arguments optional The list of - "-c" arguments. - "date > /tmp/date.txt" Whether or not the serial run_in_background false execution of tasks should wait for the command to finish. The execution directory optional folder for the command. You need to follow the classical way of specifying a binary and it's arguments. So you can not use date > /tmp/date.txt as the command, you need to specify /usr/bin/bash as the command, and then the parameters. Example: actions: to_pulpit: trigger_chain: # ... tasks: - type: run_command parameters: command: "/usr/bin/bash" arguments: [ "-l","-c","date > /tmp/date.txt" ] Send OSC message The send_osc_message sends an open sound control message through the specified connection. Currently only the console_bridges support sending a message. E.g. you can send a message back to your console. Parameter Default Description Example value values connection none, The OSC connection to use (the name behringer_x32 required from one of your console_bridges) address none, The address of the message. /ch/10/mix/on required arguments optional The arguments of the message. - type: int32 - value: 0 Example: (Unmute channel 10) actions: to_pulpit: trigger_chain: # ... tasks: - type: send_osc_message parameters: connection: "behringer_x32" address: "/ch/10/mix/on" arguments: - type: int32 value: 1 Development You'll need "make" and "docker" installed. After cloning the repository, run "make" to see the available commands. Run make dev_start to start the development environment. It'll look for a config.yml in the source root. About An advanced automation framework for audio mixer consoles, OBS, PTZ cameras and more based on the Open Sound Control protocol. Resources Readme License MIT license Activity Stars 44 stars Watchers 2 watching Forks 0 forks Report repository Releases 1 v1.0.0 Latest Nov 8, 2023 Sponsor this project * https://buymeacoffee.com/kcsaba Languages * Go 93.5% * Shell 2.3% * Dockerfile 2.2% * Makefile 2.0% Footer (c) 2024 GitHub, Inc. Footer navigation * Terms * Privacy * Security * Status * Docs * Contact * Manage cookies * Do not share my personal information You can't perform that action at this time.