logo

Live Production Software Forums


Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Options
Go to last post Go to first unread
CyaSteve  
#1 Posted : Thursday, May 1, 2025 8:51:45 AM(UTC)
CyaSteve

Rank: Newbie

Groups: Registered
Joined: 5/1/2025(UTC)
Posts: 5
United States
Location: CA

4box with one main section in 4:3 resolution

Hey all,

I'm looking to figure out if there's a way that I can script or maybe there's a setting that turns on audio from only the first layer in a input.

Four layers in an input, want only the 1st one to play audio

My 4 inputs are OBS1, OBS2, OBS3, and OBS4. At any given time any of these 4 can be in the "main larger box" and then the other 3 options are on the side in the smaller views.

It's simple to set up triggers to hard code which audio comes on, but what I'm looking to do is rotate through them. The way that I have it set up is I have two identical inputs that I merge between to move the scenes around.
So it could be
Input one:
Main: OBS1 (With Audio)
Sidebar: OBS2, OBS3, OBS4 (All Muted)

Input two:
Main: OBS3 (With Audio)
Sidebar: OBS1, OBS2, OBS4 (All Muted)

So is there a way when I transition to a scene that VMix looks at what the first layer is, turns that audio on and turns all other layers in the scene off?

Thanks in advance for any ideas!
nikosman88  
#2 Posted : Thursday, May 1, 2025 10:56:02 AM(UTC)
nikosman88

Rank: Advanced Member

Groups: Registered
Joined: 12/24/2021(UTC)
Posts: 652
Greece
Location: athens

Thanks: 155 times
Was thanked: 85 time(s) in 81 post(s)
Hi there exist at least 2 ways to do it
1.vmix scripting that will check what input is on layer 1 to your input and do the action
2.Bitfocus companion triggers like "on condition become true"-->check internal value-->layer name on the specific input, do the action
CyaSteve  
#3 Posted : Thursday, May 1, 2025 12:52:12 PM(UTC)
CyaSteve

Rank: Newbie

Groups: Registered
Joined: 5/1/2025(UTC)
Posts: 5
United States
Location: CA

Originally Posted by: nikosman88 Go to Quoted Post
Hi there exist at least 2 ways to do it
1.vmix scripting that will check what input is on layer 1 to your input and do the action
2.Bitfocus companion triggers like "on condition become true"-->check internal value-->layer name on the specific input, do the action


Love to hear that, can you think of any scripts that might be close to what I'm asking for? I'll start digging in the meantime!

Thanks!
CyaSteve  
#4 Posted : Thursday, May 1, 2025 2:19:18 PM(UTC)
CyaSteve

Rank: Newbie

Groups: Registered
Joined: 5/1/2025(UTC)
Posts: 5
United States
Location: CA

Ok after some searching the main thing I seem to be getting stuck on is simply how to pull what is on each layer. It seems very simple to set things to layers but much more complex to have the system tell me what's on the layer. Seems like there's some XML solutions so I'll start learning that but it seems like a convoluted solve.
CyaSteve  
#5 Posted : Thursday, May 1, 2025 4:29:11 PM(UTC)
CyaSteve

Rank: Newbie

Groups: Registered
Joined: 5/1/2025(UTC)
Posts: 5
United States
Location: CA

Originally Posted by: CyaSteve Go to Quoted Post
Ok after some searching the main thing I seem to be getting stuck on is simply how to pull what is on each layer. It seems very simple to set things to layers but much more complex to have the system tell me what's on the layer. Seems like there's some XML solutions so I'll start learning that but it seems like a convoluted solve.


Code:
dim xml = API.XML()
dim x as new system.xml.xmldocument
x.loadxml(xml)

dim previewInput as string
dim output as String
dim prevNodeString as String
dim childNode as xml.XmlNode
dim prevNode as xml.XmlNode

'Get what input Preview is looking at
previewInput = (x.selectSingleNode("//preview").InnerText)
Console.WriteLine(previewInput)

'Go to the node in XML
prevNodeString = "//input[@number=" & previewInput & "]"
Console.WriteLine(prevNodeString)
prevNode = (x.selectSingleNode(prevNodeString))

'Get the first child of the node (Hoping it will be layer 1 inside the input.)
childNode = prevNode.FirstChild


'dim ns = childNode.GetNamespaceOfPrefix("key")  -- This was a shot in the dark I don't think it did anything.

'Debug line
Console.WriteLine(childNode.OuterXML)


This is as far as I've gotten so far, from what I can tell I think I've accidentally janked my way into something partially correct. It looks like what's happening is I can look at what the preview sees, get the input reference number from the innertext between the <> <>. After, I use that to do a single node select to find the node that preview is looking at, then I try to figure out what layers are inside of that node and since I'm only looking for the top layer I'm calling the FirstChild function in hopes that it will give me the <overlay id="#" key="afddfhdafhadfhadfhafhafh"> info but it stalls there. No matter what I do I can't manage to get the GUID out of the first child.

Edit: to be super clear trying to get to this key so I can reference it elsewhere.
UserPostedImage
CyaSteve  
#6 Posted : Thursday, May 1, 2025 7:35:46 PM(UTC)
CyaSteve

Rank: Newbie

Groups: Registered
Joined: 5/1/2025(UTC)
Posts: 5
United States
Location: CA

Code:
dim xml = API.XML()
dim x as new system.xml.xmldocument
x.loadxml(xml)
dim previewInput as string
dim prevNodeString as String
dim Obs1 = "daae386f-674f-4743-b9db-5472f90225a4"
dim Obs1Trim = "a615e862-44a5-48a5-9cb9-04d4af0e2c3c"
dim Obs2 = "64ee059f-c6a6-4515-8d91-13b927ef3ef0"
dim Obs2Trim = "654a3147-58ae-43de-a3c7-1fa1709d3304"
dim Obs3 = "2f0f4e57-4773-40bc-bb7d-0159da84ec26"
dim Obs3Trim = "cc87689c-2ec7-4033-9739-a0653d993758"
dim Obs4 = "a3d713e0-59c7-42ec-b656-3863aec6d6b7" 
dim Obs4Trim = "fd0d07db-c472-4953-a276-31bfd59e6483"
dim audioUp as String

'Get what is on preview
previewInput = (x.selectSingleNode("//preview").InnerText)
Console.WriteLine(previewInput)

'Get the node that preview is looking at then go one step further to its first child node
prevNodeString = "//input[@number=" & previewInput & "]/overlay[@index=0]"
Console.WriteLine(prevNodeString)

dim prevNode as xml.XmlNode
prevNode = (x.selectSingleNode(prevNodeString))

'Set evaluator to the GUID of the first child node - 1st layer in the preview file
audioup = prevNode.Attributes("key").value

'Turn audio on if equal to relevant feed.  Obs#trim and Obs# are used because part of what I'm building has a 4:3 resolution show built inside of a 16:9 show, so the 4box uses the 4:3 virtual feeds but the audio is actually on the lines that are simply labeled Obs#

if audioup = obs1trim then
API.Function("AudioOn",input:=Obs1)
API.Function("AudioOff",input:=Obs2)
API.Function("AudioOff",input:=Obs3)
API.Function("AudioOff",input:=Obs4)

elseif audioup = obs2trim then
API.Function("AudioOn",input:=Obs2)
API.Function("AudioOff",input:=Obs1)
API.Function("AudioOff",input:=Obs3)
API.Function("AudioOff",input:=Obs4)

elseif audioup = obs3trim then

API.Function("AudioOn",input:= Obs3)
API.Function("AudioOff",input:=Obs1)
API.Function("AudioOff",input:=Obs2)
API.Function("AudioOff",input:=Obs4)

elseif audioup = obs4trim then
API.Function("AudioOn",input:=Obs4)
API.Function("AudioOff",input:=Obs1)
API.Function("AudioOff",input:=Obs2)
API.Function("AudioOff",input:=Obs3)
else
end if

API.Function("Merge",Duration:= 1000)


So I got to this point after a whole day. It works about 60% of the time. One of the two scenes I use seems to work almost every time. The other one seems to either always default to Obs1 turning on or doing what the logic says it should. If I put obs3 up on that scene then call it and it turns obs1 on, then the fix is to put a different scene in preview then put the exact scene that's already on program back in preview and then hit the script again and it will choose the right audio. Idk I'm beat and I'll look at this fresh in the morning. <3 if you throw any suggestions my way while I sleep!
nikosman88  
#7 Posted : Thursday, May 1, 2025 8:36:55 PM(UTC)
nikosman88

Rank: Advanced Member

Groups: Registered
Joined: 12/24/2021(UTC)
Posts: 652
Greece
Location: athens

Thanks: 155 times
Was thanked: 85 time(s) in 81 post(s)
Hi. Im not script expert or programmer by any means. Im using AI to make more complex things. So i gave to AI your code and it respond with this version
Code:

Do While True
    ' Πάρε το XML από το vMix
    Dim xml As String = API.XML()
    Sleep(100) ' λίγο χρόνο για να είναι "φρέσκο"

    Dim x As New System.Xml.XmlDocument()
    x.LoadXml(xml)

    Dim previewInputNumber As String = x.SelectSingleNode("//preview").InnerText
    Dim previewInputNode As XmlNode = x.SelectSingleNode("//input[@number='" & previewInputNumber & "']")

    ' Δηλώνουμε τα GUIDs
    Dim Obs1 = "daae386f-674f-4743-b9db-5472f90225a4"
    Dim Obs1Trim = "a615e862-44a5-48a5-9cb9-04d4af0e2c3c"
    Dim Obs2 = "64ee059f-c6a6-4515-8d91-13b927ef3ef0"
    Dim Obs2Trim = "654a3147-58ae-43de-a3c7-1fa1709d3304"
    Dim Obs3 = "2f0f4e57-4773-40bc-bb7d-0159da84ec26"
    Dim Obs3Trim = "cc87689c-2ec7-4033-9739-a0653d993758"
    Dim Obs4 = "a3d713e0-59c7-42ec-b656-3863aec6d6b7"
    Dim Obs4Trim = "fd0d07db-c472-4953-a276-31bfd59e6483"

    Dim audioUp As String = ""
    Dim overlayFound As Boolean = False

    ' Τσέκαρε τα overlay index 0 έως 2
    For i As Integer = 0 To 2
        Dim overlayNode As XmlNode = previewInputNode.SelectSingleNode("overlay[@index='" & i.ToString() & "']")
        If overlayNode IsNot Nothing Then
            audioUp = overlayNode.Attributes("key").Value
            overlayFound = True
            Exit For
        End If
    Next

    If overlayFound Then
        If audioUp = Obs1Trim Then
            API.Function("AudioOn", Input:=Obs1)
            API.Function("AudioOff", Input:=Obs2)
            API.Function("AudioOff", Input:=Obs3)
            API.Function("AudioOff", Input:=Obs4)
        ElseIf audioUp = Obs2Trim Then
            API.Function("AudioOn", Input:=Obs2)
            API.Function("AudioOff", Input:=Obs1)
            API.Function("AudioOff", Input:=Obs3)
            API.Function("AudioOff", Input:=Obs4)
        ElseIf audioUp = Obs3Trim Then
            API.Function("AudioOn", Input:=Obs3)
            API.Function("AudioOff", Input:=Obs1)
            API.Function("AudioOff", Input:=Obs2)
            API.Function("AudioOff", Input:=Obs4)
        ElseIf audioUp = Obs4Trim Then
            API.Function("AudioOn", Input:=Obs4)
            API.Function("AudioOff", Input:=Obs1)
            API.Function("AudioOff", Input:=Obs2)
            API.Function("AudioOff", Input:=Obs3)
        Else
            ' Αν υπάρχει overlay αλλά δεν είναι κάποιο από τα γνωστά
            API.Function("SetText", Input:="AUDIO STATUS", SelectedName:="Message.Text", Value:="Άγνωστο overlay στο preview")
        End If
    Else
        ' Αν δεν βρέθηκε overlay σε καμία layer
        API.Function("SetText", Input:="AUDIO STATUS", SelectedName:="Message.Text", Value:="Κανένα overlay στο preview")
    End If

    ' Προαιρετικά: Μετάβαση
    API.Function("Merge", Duration:=1000)

    Sleep(1000) ' αναμονή 1 δευτερόλεπτο
Loop

And another one version that may help you
Code:

Do While True
    Dim xml As String = API.XML()
    Dim doc As New System.Xml.XmlDocument()
    doc.LoadXml(xml)

    ' Τα input keys που θέλεις να ελέγχεις
    Dim inputKey1 As String = "ca353050-f012-4b9f-8e68-5519bd46e2b3"
    Dim inputKey2 As String = "83f6b1c7-a937-425c-a67d-9a137b3dfbac"

    ' Ποιο input είναι το ενεργό (active)
    Dim activeInputNumber As String = doc.SelectSingleNode("/vmix/active").InnerText

    ' Εντοπίζουμε τον κόμβο input που είναι ενεργός
    Dim activeInputNode As XmlNode = doc.SelectSingleNode("/vmix/inputs/input[@number='" & activeInputNumber & "']")

    If activeInputNode IsNot Nothing Then
        Dim activeInputKey As String = activeInputNode.Attributes("key").Value

        ' Αν το ενεργό input είναι ένα από τα δύο που μας ενδιαφέρουν
        If activeInputKey = inputKey1 Or activeInputKey = inputKey2 Then
            Dim overlayNode As XmlNode = activeInputNode.SelectSingleNode("overlay[@index='0']")
            If overlayNode IsNot Nothing Then
                Dim overlayKey As String = overlayNode.Attributes("key").Value

                Select Case overlayKey
                    Case "4f432bca-487a-48e1-bbf7-613196debff8"
                        API.Function("SetText", Input:="AUDIO STATUS", SelectedName:="Message.Text", Value:="Audio In 1")
                        API.Function("AudioBusOn", Input:="OBS1", Value:="M")
                        API.Function("AudioBusOff", Input:="OBS2", Value:="M")
                        API.Function("AudioBusOff", Input:="OBS3", Value:="M")
                        API.Function("AudioBusOff", Input:="OBS4", Value:="M")
                    Case "4357ace2-0c1c-4c41-9562-e468fb1e32b2"
                        API.Function("SetText", Input:="AUDIO STATUS", SelectedName:="Message.Text", Value:="Audio In 2")
                        API.Function("AudioBusOff", Input:="OBS1", Value:="M")
                        API.Function("AudioBusOn", Input:="OBS2", Value:="M")
                        API.Function("AudioBusOff", Input:="OBS3", Value:="M")
                        API.Function("AudioBusOff", Input:="OBS4", Value:="M")
                    Case "903d28fa-4b88-416f-9344-fc9807427428"
                        API.Function("SetText", Input:="AUDIO STATUS", SelectedName:="Message.Text", Value:="Audio In 3")
                        API.Function("AudioBusOff", Input:="OBS1", Value:="M")
                        API.Function("AudioBusOff", Input:="OBS2", Value:="M")
                        API.Function("AudioBusOn", Input:="OBS3", Value:="M")
                        API.Function("AudioBusOff", Input:="OBS4", Value:="M")
                    Case Else
                        API.Function("SetText", Input:="AUDIO STATUS", SelectedName:="Message.Text", Value:="Unknown overlay στο Layer 1")
                End Select
            Else
                API.Function("SetText", Input:="AUDIO STATUS", SelectedName:="Message.Text", Value:="Δεν βρέθηκε overlay index 0")
            End If
        Else
            API.Function("SetText", Input:="AUDIO STATUS", SelectedName:="Message.Text", Value:="Active input δεν είναι τα 2 που μας νοιάζουν")
        End If
    Else
        API.Function("SetText", Input:="AUDIO STATUS", SelectedName:="Message.Text", Value:="Δεν βρέθηκε active input")
    End If

    Sleep(1000)
Loop

In the 2nd script here Dim inputKey1 As String = "ca353050-f012-4b9f-8e68-5519bd46e2b3"
Dim inputKey2 As String = "83f6b1c7-a937-425c-a67d-9a137b3dfbac" we setup the first input key and the 2nd input key meaning the 2 "multiview windows" we use to merge and script checks what is on the first layer and if this input is active and it proceed further.
Hope this helps
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.