logo

Live Production Software Forums


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

Notification

Icon
Error

26 Pages«<242526
Options
Go to last post Go to first unread
ajfnetwork  
#501 Posted : Saturday, March 23, 2024 2:59:16 AM(UTC)
ajfnetwork

Rank: Newbie

Groups: Registered
Joined: 3/17/2024(UTC)
Posts: 4
Venezuela
Location: San Carlos Cojedes

Originally Posted by: doggy Go to Quoted Post
Originally Posted by: ajfnetwork Go to Quoted Post
Hello colleagues, I hope you are well... I have the following question...

It would be possible to make a script, I don't know if it already exists, can someone advise me since I'm new to scripts...

Does it allow me to place titles every time a data source is updated by XML? If I can explain myself correctly...

That every time the XML data source is updated, the title overlay is activated.

I hope you can help me... thank you very much


Read content of title by reading the API XML or using the Input.Find() option
Compare to a previously saved content , if different perform action , save new content for next comparison. Rinse and repeat

PLS go through the multiple examples in this thread on how to read info from the api xml
go through the multiple online tutorials on programming in vb.net



Hello friend, how are you? I don't understand much of what you just told me, what is the first thing I should do? Since I don't know.
doggy  
#502 Posted : Saturday, March 23, 2024 3:23:12 AM(UTC)
doggy

Rank: Advanced Member

Groups: Registered
Joined: 12/27/2012(UTC)
Posts: 5,202
Belgium
Location: Belgium

Thanks: 291 times
Was thanked: 953 time(s) in 788 post(s)
Originally Posted by: ajfnetwork Go to Quoted Post
Originally Posted by: doggy Go to Quoted Post
Originally Posted by: ajfnetwork Go to Quoted Post
Hello colleagues, I hope you are well... I have the following question...

It would be possible to make a script, I don't know if it already exists, can someone advise me since I'm new to scripts...

Does it allow me to place titles every time a data source is updated by XML? If I can explain myself correctly...

That every time the XML data source is updated, the title overlay is activated.

I hope you can help me... thank you very much


Read content of title by reading the API XML or using the Input.Find() option
Compare to a previously saved content , if different perform action , save new content for next comparison. Rinse and repeat

PLS go through the multiple examples in this thread on how to read info from the api xml
go through the multiple online tutorials on programming in vb.net



Hello friend, how are you? I don't understand much of what you just told me, what is the first thing I should do? Since I don't know.


as quoted:
Quote:
PLS go through the multiple examples in this thread on how to read info from the api xml
go through the multiple online tutorials on programming in vb.net
videokommando  
#503 Posted : Wednesday, March 27, 2024 6:18:12 AM(UTC)
videokommando

Rank: Advanced Member

Groups: Registered
Joined: 4/2/2013(UTC)
Posts: 53
Man
Location: Hungary

Thanks: 3 times
I have studied XML.
Why are there 8 overlay channels?

<overlay number="1">6</overlay>
<overlay number="2">7</overlay>
<overlay number="3">8</overlay>
<overlay number="4"/>
<overlay number="5"/>
<overlay number="6"/>
<overlay number="7"/>
<overlay number="8"/>

And an other question:
Can I see/read in script the last keystroke?
Is it possible to work with the midi or keyboard keystroke in script?

Thank you.
doggy  
#504 Posted : Wednesday, March 27, 2024 7:00:25 AM(UTC)
doggy

Rank: Advanced Member

Groups: Registered
Joined: 12/27/2012(UTC)
Posts: 5,202
Belgium
Location: Belgium

Thanks: 291 times
Was thanked: 953 time(s) in 788 post(s)
Originally Posted by: videokommando Go to Quoted Post
I have studied XML.
Why are there 8 overlay channels?

<overlay number="1">6</overlay>
<overlay number="2">7</overlay>
<overlay number="3">8</overlay>
<overlay number="4"/>
<overlay number="5"/>
<overlay number="6"/>
<overlay number="7"/>
<overlay number="8"/>


4 overlays and 4 stingers (can see that in the overlay settings number dropdown)

Quote:

And an other question:
Can I see/read in script the last keystroke?


No (unless you create a keylogger which is generally frowned upon)

Quote:

Is it possible to work with the midi or keyboard keystroke in script?

Thank you.


No (not that i am aware of ). Maybe Google has an answer
Video-Chopper  
#505 Posted : Wednesday, March 27, 2024 7:05:38 AM(UTC)
Video-Chopper

Rank: Member

Groups: Registered
Joined: 5/18/2023(UTC)
Posts: 16
United States
Location: Colorado

Thanks: 4 times
Was thanked: 1 time(s) in 1 post(s)
Beat me to it, Doggy!
videokommando  
#506 Posted : Wednesday, March 27, 2024 7:25:23 AM(UTC)
videokommando

Rank: Advanced Member

Groups: Registered
Joined: 4/2/2013(UTC)
Posts: 53
Man
Location: Hungary

Thanks: 3 times
Originally Posted by: doggy Go to Quoted Post
Originally Posted by: videokommando Go to Quoted Post
I have studied XML.
4 overlays and 4 stingers (can see that in the overlay settings number dropdown)
Quote:

And an other question:
Can I see/read in script the last keystroke?


No (unless you create a keylogger which is generally frowned upon)

Quote:

Is it possible to work with the midi or keyboard keystroke in script?

Thank you.


No (not that i am aware of ). Maybe Google has an answer



There isn't dropdown if I don't use stinger. But I understand this.

I will use DynamicValue instead of keystrokes.

Thank you.
doggy  
#507 Posted : Tuesday, April 23, 2024 5:44:48 AM(UTC)
doggy

Rank: Advanced Member

Groups: Registered
Joined: 12/27/2012(UTC)
Posts: 5,202
Belgium
Location: Belgium

Thanks: 291 times
Was thanked: 953 time(s) in 788 post(s)
Here is another fun one

displaying Instant Replay Event Tags during replays

Code:
'Display Tag(s) of instant replay(s) playing

'ReplayStartStopRecording  to update XML after adding tags (vMix BUG), or open/close  IR configuration!!
'run script and do a replay , tag will be displayed in title
'made for 4K license ( one replay angle)

' Setup : Edit accordingly =========================
dim RFolder as string = "E:\Replay"           ' Instant Replay Folder 
dim TagTitle as string = "Blue.gtzip"          ' Title name or Input number to display Tag on
dim TagText as string = "Headline.Text"       ' Title TextBlock to hold the Tag
dim EvenText as string = "Description.Text"   ' Title TextBlock to hold the Event name
' ==================================================

dim x as new system.xml.xmldocument
Dim document As XmlDocument = New XmlDocument()

do while true 
    x.loadxml(API.XML())

    'get the events number (to select list )
    dim events as string = x.SelectSingleNode("//input[@type='Replay']//replay/@events").value
    'get the channelmode used 
    dim mode AS string = x.SelectSingleNode("//input[@type='Replay']//replay/@channelMode").value

    dim Rinput as string
    if mode = "B"  'which channel is one using 
       Rinput = "ReplayPreview"
    else
       Rinput = "Replay"
    end if
   
    document.Load(RFolder & "\replay2.xml")  'get XML for retrieving tags

    Dim nodeList As XmlNodeList = document.SelectNodes("//list[" & events & "]/event")
    Dim count As Integer = nodeList.Count
    dim z as integer

    do while true
        x.loadxml(API.XML())
        dim state as string = x.SelectSingleNode("//input[@type='" & Rinput & "']/@state").value  'get the state of replay (Running or Paused), mode dependent

        if state = "Running"

            '********************** Optional  Comment out if not needed *************
            dim eventname as string =document.SelectSingleNode("//list[" & events & "]/@name").innertext
            if eventname = "" 
                eventname= events 'if not name show events number
            end if
            ' Display the EVENTNAME
            API.Function("SetText",Input:=TagTitle,SelectedName:=EvenText,Value:=eventname ) 
            '***********************************

            dim pos as string = x.SelectSingleNode("//input[@type='" & Rinput & "']/@position").value   
            for z  = 1 to count
                dim ins as string = (document.SelectSingleNode("//list[" & events & "]/event["& z & "]/inPoint").innertext)\10000 
                dim outs as string = (document.SelectSingleNode("//list[" & events & "]/event["& z & "]/outPoint").innertext)\10000 
                if (pos > ins) and (pos < outs)
                    dim tag as string = document.SelectSingleNode("//list[" & events & "]/event["& z & "]/description[1]").innertext  
                    API.Function("SetText",Input:=TagTitle,SelectedName:=TagText,Value:=tag )  'display the TAG
                end if 
            next
        else
            API.Function("SetText",Input:=TagTitle,SelectedName:=TagText,Value:=" stopped " )  'clear/done title
            Exit do 
        end if
        sleep(200)
    loop
    sleep(500)
loop
WaltG12  
#508 Posted : Wednesday, April 24, 2024 8:00:15 AM(UTC)
WaltG12

Rank: Advanced Member

Groups: Registered
Joined: 7/4/2021(UTC)
Posts: 285
United States

Thanks: 7 times
Was thanked: 35 time(s) in 31 post(s)
I know absolutely nothing about VB.net scripting.

But, over the years, I’ve been able to piece together scripts and knowledge from here and elsewhere.

So I thought I’d post here to help out anyone having difficulty with figuring out how to check a single element’s status and act based on that element.

Now, again, I know nothing on this subject. These scripts have worked for me, but if there’s a cleaner or better way to achieve the same goal, I’m most open to being corrected.

The API reports status in the form of input numbers for:

active
preview
overlay
mix (active and preview)

The API reports status in the form of “True”/”False” for:

fadeToBlack
recording
external
streaming
playList
multiCorder
fullscreen

(There are probably others in both categories, but these are the ones I worked with. This should be modular enough to adapt easily to others.)

The process of getting and acting based off an input number alone is the exact same as getting and acting based off a True/False status.

The script I use for that is this:

Code:
dim xml as string = API.XML()
dim GetInputNumber as string = ""

dim x as new system.xml.xmldocument
x.loadxml(xml)

GetInputNumber = (x.SelectSingleNode("/vmix/active").InnerText)


if GetInputNumber = "1"

API.Function("Cut")

end if



This is a script you’ve probably seen already.

But I want to break it down to help you modify it.

Code:
GetInputNumber


is a user-defined variable. You can make It what you want it to be, as long as you change it everywhere it comes up to the same thing.

Where it says

Code:
/vmix/active


is what defines which node on the API XML you’re looking at. It can be changed.

If you want to get the input number of the preview, that would be

Code:
/vmix/preview


If you want to get the input number assigned to a specific Overlay channel, that would be

Code:
//overlays/overlay[1]


where the number in brackets corresponds to which instance of nodes called “overlay” under the parent “overlays” you’re looking up.

1 is going to the the first on the list. 8 is going to be last on the list. 2-7 are, obviously, everything in between.

Mix inputs are similar to Overlays, but they’re a little less intuitive.

To get the preview of a Mix input, that’s

Code:
//mix[1]/preview


For the active (output) on a Mix input, just swap the word “active” where it says “preview”.

The number in the brackets corresponds to the instances of nodes called “mix”.

That means that the first Mix input, which calls itself Mix 2 and appears on the API as

Quote:
<mix number="2">


will actually be mix[1] under this system. And on up from there.

In a way this actually helps, because the numbering here reflects the same “one less” numbering used by API function shortcuts that these scripts fire.

Just as a reminder, this only returns input numbers.

So what you’re checking against has to be the input number—not the name or anything else.

Code:
if GetInputNumber = "1"


is a basic “if” statement. It can be followed by “elseif” or “else” statements above the “end if” for more granular control.

The VB.net operator for equivalent is

Code:
=


That means that the input number you’re asking the script to check is the same as the one you specified.

The VB.net operator for inequivalent is

Code:
<>


That means that the script returns anything other than the input number you specified.

So if you only want it to fire the command if the input number returned is NOT 1, you’d use

Code:
if GetInputNumber <> "1"


On items that the API XML shows as empty and self closing (such as overlays), you can specify “nothing” where, instead of checking against a specific input number, you check to see if there’s an input assigned at all, and fire based on that.

The syntax for that is

Code:
if GetInputNumber = nothing


As I previously said, the elements that return True/False values are checked the exact same way, but they return either “True” or “False” instead of a number.

So, using the same variable name for the sake of simplicity, it would be

Code:
if GetInputNumber = "True"


Or, of course, “False” can be substituted for “True”.

Here’s the syntax for all of those, as well as everything previously listed just to put it all in one box.

Code:
//fadeToBlack
//recording
//external
//streaming
//playList
//multiCorder
//fullscreen
/vmix/active
/vmix/preview
//overlays/overlay[1]
//mix[1]/preview
//mix[1]/active


Now, personally, I like working with input names, because I give each input a unique and specific name. Others like working with the GUID/key.

You can get either of these, as well as others, from the same script by adding an extra step.

Here’s the full script I use for that.

Code:
dim xml as string = API.XML()
dim GetInputNumber as string = ""
dim GetInputName as string = ""

dim x as new system.xml.xmldocument
x.loadxml(xml)

GetInputNumber = (x.SelectSingleNode("/vmix/active").InnerText)

GetInputName = (x.SelectSingleNode("//input[@number='"& GetInputNumber &"']/@title").Value)


if GetInputName = "MyVideo"

API.Function("Cut")

end if


You’ll notice this is the same script, just with an additional user-defined variable and an extra step.

You’ll also notice that the name of the previous variable to get the input number is used within that second step, so make sure you also change it there if you change it.

What this is doing is getting the “title” attribute from the specified input node.

That means that you can get any other input attribute by replacing the word “title” with the name of your desired attribute.

These vary by input type, and there are quite a few of them, so I won’t list them all, but I’ll provide a few examples to give you an idea of what you’re looking for. (For the sake of simplicity, I’m going to maintain the same variable name.)

Code:
GetInputName = (x.SelectSingleNode("//input[@number='"& GetInputNumber &"']/@type").Value)


will give you the input type. For example: Mix, Colour, AudioFile, Video, Capture, etc.

So if you want to do something if check if the active input (output) is a camera, you’d use that line, combined with

Code:
if GetInputName = "Capture"


If you want to know if an input is playing or paused

Code:
GetInputName = (x.SelectSingleNode("//input[@number='"& GetInputNumber &"']/@state").Value)


will return either “Paused” or “Running”.

Code:
@loop
@muted
@solo


will all return either “True” or “False”.

There are a lot of options, and, again, they vary by input type. Check out the API—those examples should give you an idea of what you’re looking for.

If you know the input number, and don’t want to fetch it from elsewhere, you can adapt this script to that too.

Code:
dim xml as string = API.XML()
dim GetInputName as string = ""

dim x as new system.xml.xmldocument
x.loadxml(xml)

GetInputName = (x.SelectSingleNode("//input[1]/@title").Value)


if GetInputName = "MyVideo"

API.Function("Cut")

end if


As with above, the number in brackets (which was previously filled by the variable fetched in the previous step) corresponds to where on the list of nodes called “input” the requested element falls.

And, again, you can change the “title” attribute to any attribute within the element node.

(Special thanks to doggy and others for providing the backbone for my being able to scrape this knowledge together.)

WaltG12  
#509 Posted : Friday, April 26, 2024 3:22:24 PM(UTC)
WaltG12

Rank: Advanced Member

Groups: Registered
Joined: 7/4/2021(UTC)
Posts: 285
United States

Thanks: 7 times
Was thanked: 35 time(s) in 31 post(s)
I wanted to share my new script using the new “ZoomSelectParticipantByName” shortcut, in conjunction with Dynamic Input 1 and vMix Social, to automatically add Zoom guests to the next available Zoom input.

First, a few caveats:

1) This only works if you add every guest by using it. If you keep the first at “Default” or manually add people using the Zoom Manager, this script will do more harm than good.

2) As I mentioned in other posting above, I give my inputs unique names and prefer to use scripts that utilize those. This is one of them, and it explicitly requires that your first two Zoom inputs have unique and defined names.

3) This script, as you can tell by reading it, requires your Zoom inputs be right next to each other in order to function on the first run(s).

4) Make sure your vMix Social title mapping is correct. If you’re using Social for its intended purpose, you can adapt the script to that, but in doing so, you’ll probably want to curate your feed manually and add a step that wipes/otherwise resets the title.

Unless/until vMix adds more Zoom info to the API XML, this is the best I can think to do.

Code:
dim xml as string = API.XML()
dim CurrentDynamicInput1 as string = ""
dim SecondZoomInputNumber as string = ""

‘ In quotes is the name of the title input that contains the guest name(s)
dim GuestNameTitle as string = "GuestNameTitle"

‘ In quotes is the name of the text field in the title input that contains the guest name you want to assign to the Zoom input
dim GuestNameTextField as string = "GuestNameTextField.Text"

‘ In quotes is the unique name for your first Zoom input
dim FirstZoomInput as string = "Zoom1"

‘ In quotes is the unique name for your second Zoom input, no need to identify beyond that
dim SecondZoomInput as string = "Zoom2"

dim x as new system.xml.xmldocument
x.loadxml(xml)

CurrentDynamicInput1 = (x.SelectSingleNode("//dynamic/input1").InnerText)

dim GuestName as string = Input.Find(GuestNameTitle).Text(GuestNameTextField)

If CurrentDynamicInput1 = nothing OrElse CurrentDynamicInput1 = FirstZoomInput
API.Function("ZoomSelectParticipantByName",Input:=FirstZoomInput,Value:=GuestName)
Sleep(200)
SecondZoomInputNumber = (x.SelectSingleNode("//input[@title='"& SecondZoomInput &"']/@number").Value)
Sleep(100)
API.Function("SetDynamicInput1",Value:=SecondZoomInputNumber)

Else

API.Function("ZoomSelectParticipantByName",Input:=”Dynamic1”,Value:=GuestName)
Sleep(200)
dim NewDynamicInput1 as integer = cint(CurrentDynamicInput1)
NewDynamicInput1 +=1
API.Function("SetDynamicInput1",Value:=NewDynamicInput1)


End if


EDIT:

I just did another one that I like a bit better.

This one uses DynamicValues to track guest names, so it’ll be best for those with smaller productions (up to 4 guests) who aren’t already using Dynamic Values.

It can be adapted to use Titles instead of DynamicValues, to the same end, but it does require that every Zoom input be explicitly identified to work. So, again, it’s best for smaller productions.

But it does have the added benefit of double checking to make sure that a guest isn’t already in an input before adding them, which is why I prefer it to the other one.

It also accounts for if you accidentally run it before sending the guest name to the title by ruling out the placeholder text.

As the API XML doesn’t have any particular Zoom-specific information, you do still need to use it to add everyone in order for it to work properly, since it only knows who was added to an input because it logs who it adds to an input.


Code:
dim xml as string = API.XML()
dim DynamicValue1 as string = ""
dim DynamicValue2 as string = ""
dim DynamicValue3 as string = ""
dim DynamicValue4 as string = ""

‘ In quotes is the name of the title input that contains the guest name(s)
dim GuestNameTitle as string = "GuestNameTitle"

‘ In quotes is the name of the text field in the title input that contains the guest name you want to assign to the Zoom input
dim GuestNameTextField as string = "GuestNameText.Text"

‘ In quotes is the unique name for your first Zoom input
dim FirstZoomInput as string = "Zoom1"

‘ In quotes is the unique name for your second Zoom input
dim SecondZoomInput as string = "Zoom2"

‘ In quotes is the unique name for your third Zoom input
dim ThirdZoomInput as string = "Zoom3"

‘ In quotes is the unique name for your fourth Zoom input
dim FourthZoomInput as string = "Zoom4"

dim x as new system.xml.xmldocument
x.loadxml(xml)

dim GuestName as string = Input.Find(GuestNameTitle).Text(GuestNameTextField)

DynamicValue1 = (x.SelectSingleNode("//dynamic/value1").InnerText)

DynamicValue2 = (x.SelectSingleNode("//dynamic/value2").InnerText)

DynamicValue3 = (x.SelectSingleNode("//dynamic/value3").InnerText)

DynamicValue4 = (x.SelectSingleNode("//dynamic/value4").InnerText)

‘ I use the words Guest Name for the placeholder text in my title

If DynamicValue1 = nothing OrElse DynamicValue1 = GuestName OrElse DynamicValue1 = “Guest Name”
API.Function("SetDynamicValue1",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=FirstZoomInput,Value:=GuestName)

Elseif DynamicValue2 = nothing OrElse DynamicValue2 = GuestName OrElse DynamicValue2 = “Guest Name”
API.Function("SetDynamicValue2",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=SecondZoomInput,Value:=GuestName)

Elseif DynamicValue3 = nothing OrElse DynamicValue3 = GuestName OrElse DynamicValue3 = “Guest Name”
API.Function("SetDynamicValue3",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=ThirdZoomInput,Value:=GuestName)

Elseif DynamicValue4 = nothing OrElse DynamicValue4 = GuestName OrElse DynamicValue4 = “Guest Name”
API.Function("SetDynamicValue4",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=FourthZoomInput,Value:=GuestName)

End if


EDIT 2:

Here's an updated version of the above script, which loops & has a more complex name analysis:

Code:
Do while true

dim xml as string = API.XML()
dim DynamicValue1 as string = ""
dim DynamicValue2 as string = ""
dim DynamicValue3 as string = ""
dim DynamicValue4 as string = ""

‘ In quotes is the name of this script
dim ScriptName as string = "ZoomInputAutofillFromGuestNameTitle"

‘ In quotes is the name of your Zoom Chat data source
dim DataSourceName as string = "ZoomChat"

‘ In quotes is the name of the title input that contains the guest name(s)
dim GuestNameTitle as string = "ZoomChat"

‘ In quotes is the name of the text field in the title input that contains the guest name you want to assign to the Zoom input
dim GuestNameTextField as string = "UserName.Text"

‘ In quotes is the unique name for your first Zoom input
dim FirstZoomInput as string = "Zoom1"

‘ In quotes is the unique name for your second Zoom input
dim SecondZoomInput as string = "Zoom2"

‘ In quotes is the unique name for your third Zoom input
dim ThirdZoomInput as string = "Zoom3"

‘ In quotes is the unique name for your fourth Zoom input
dim FourthZoomInput as string = "Zoom4"

‘ In quotes is the amount of time in milliseconds between loops; status checks are only updated when the script loops
dim LoopDuration as integer = "5000"

dim x as new system.xml.xmldocument
x.loadxml(xml)

dim GuestName as string = Input.Find(GuestNameTitle).Text(GuestNameTextField)

DynamicValue1 = (x.SelectSingleNode("//dynamic/value1").InnerText)

DynamicValue2 = (x.SelectSingleNode("//dynamic/value2").InnerText)

DynamicValue3 = (x.SelectSingleNode("//dynamic/value3").InnerText)

DynamicValue4 = (x.SelectSingleNode("//dynamic/value4").InnerText)

API.Function("DataSourceAutoNextOff",Value:=DataSourceName)

If DynamicValue1 <> nothing AndAlso DynamicValue2 <> nothing AndAlso DynamicValue3 <> nothing AndAlso DynamicValue4 <> nothing
Console.WriteLine(“All slots full”)
Sleep(200)
API.Function("ScriptStop",Value:=ScriptName)

Elseif DynamicValue1 = GuestName OrElse DynamicValue2 = GuestName OrElse DynamicValue3 = GuestName OrElse DynamicValue4 = GuestName
Console.WriteLine(“Participant already assigned to input”)

‘ I use Text as the placeholder text in my title; this is also the line where you can add the names of colleagues you do not want pulled in, if necessary

‘ You can also flip the operator to a <> to form a whitelist

Elseif GuestName = “Text”
Console.WriteLine(“No participant named”)

Elseif DynamicValue1 = nothing
API.Function("SetDynamicValue1",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=FirstZoomInput,Value:=GuestName)

Elseif DynamicValue2 = nothing
API.Function("SetDynamicValue2",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=SecondZoomInput,Value:=GuestName)

Elseif DynamicValue3 = nothing
API.Function("SetDynamicValue3",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=ThirdZoomInput,Value:=GuestName)

Elseif DynamicValue4 = nothing
API.Function("SetDynamicValue4",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=FourthZoomInput,Value:=GuestName)

End if

Sleep(200)
API.Function("DataSourceNextRow",Value:=DataSourceName)

Sleep(LoopDuration)
loop


EDIT 3:

Here's another Zoom script. This one is manual--trigger it with a shortcut & pair it with a vMix Social, "DataSourceNextRow" shortcut, or Data Source autonext feature.

For this script, you don't need to identify any of the Zoom inputs that you want to assign participants too--just use the default input name of "Zoom".

Additionally, the Zoom inputs can be anywhere in your production--they don't need to be right next to each other.

They just, again, need to have the default input name of "Zoom", as this script will mark them used after assigning a participant to them by changing the name to "Zoom Guest Name" similar to vMix Call.

This also still uses Dynamic Values, or a title, to ensure that you aren't assigning a participant to multiple inputs, in case a name repeats in the title & you don't notice.

This script does still work when there are Zoom inputs that still have their default name, but no spaces left for name tracking, so there's a clear delineation of where you should draw the line, depending on which one you want to rule the day (or if you just don't want name tracking at all).

Code:
dim xml as string = API.XML()
dim DynamicValue1 as string = ""
dim DynamicValue2 as string = ""
dim DynamicValue3 as string = ""
dim DynamicValue4 as string = ""

‘ In quotes is the name of the title input that contains the guest name(s)
dim GuestNameTitle as string = "ZoomChat"

‘ In quotes is the name of the text field in the title input that contains the guest name you want to assign to the Zoom input
dim GuestNameTextField as string = "UserName.Text"


dim x as new system.xml.xmldocument
x.loadxml(xml)


dim inputsNode As XmlNode = x.SelectSingleNode("/vmix/inputs")

' This provides the total number of inputs, which is also the input number of the last input
dim LastInput = inputsNode.ChildNodes.Count()

For Each inputNode As XmlNode In inputsNode.ChildNodes
dim InputNumber As Integer = inputNode.Attributes("number").value
dim InputType as String = inputNode.Attributes("type").value
dim InputName as String = inputNode.Attributes("title").value


If InputType = "Zoom" AndAlso InputName = "Zoom"


dim GuestName as string = Input.Find(GuestNameTitle).Text(GuestNameTextField)
dim NewInputName as string = "Zoom" & " " & GuestName
DynamicValue1 = (x.SelectSingleNode("//dynamic/value1").InnerText)
DynamicValue2 = (x.SelectSingleNode("//dynamic/value2").InnerText)
DynamicValue3 = (x.SelectSingleNode("//dynamic/value3").InnerText)
DynamicValue4 = (x.SelectSingleNode("//dynamic/value4").InnerText)

If DynamicValue1 = GuestName OrElse DynamicValue2 = GuestName OrElse DynamicValue3 = GuestName OrElse DynamicValue4 = GuestName
Console.WriteLine(“Participant already assigned to input”)
Exit for

Elseif DynamicValue1 <> nothing AndAlso DynamicValue2 <> nothing AndAlso DynamicValue3 <> nothing AndAlso DynamicValue4 <> nothing
Console.WriteLine(“No available tracking values”)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=InputNumber,Value:=GuestName)
Sleep(200)
API.Function("SetInputName",Input:=InputNumber,Value:=NewInputName)
Sleep(200)
Exit for

Elseif DynamicValue1 = nothing
API.Function("SetDynamicValue1",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=InputNumber,Value:=GuestName)
Sleep(200)
API.Function("SetInputName",Input:=InputNumber,Value:=NewInputName)
Sleep(200)
Exit for

Elseif DynamicValue2 = nothing
API.Function("SetDynamicValue2",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=InputNumber,Value:=GuestName)
Sleep(200)
API.Function("SetInputName",Input:=InputNumber,Value:=NewInputName)
Sleep(200)
Exit for

Elseif DynamicValue3 = nothing
API.Function("SetDynamicValue3",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=InputNumber,Value:=GuestName)
Sleep(200)
API.Function("SetInputName",Input:=InputNumber,Value:=NewInputName)
Sleep(200)
Exit for

Elseif DynamicValue4 = nothing
API.Function("SetDynamicValue4",Value:=GuestName)
Sleep(200)
API.Function("ZoomSelectParticipantByName",Input:=InputNumber,Value:=GuestName)
Sleep(200)
API.Function("SetInputName",Input:=InputNumber,Value:=NewInputName)
Sleep(200)
Exit for

End if


Elseif InputNumber = LastInput


Console.WriteLine("No more Zoom inputs")
Exit for


End if

Next


If/when vMix is updated to allow the "AddInput" shortcut to open additional Zoom inputs, you'll want to take the part that says

Code:
Elseif InputNumber = LastInput


Console.WriteLine("No more Zoom inputs")
Exit for


and replace it with

Code:
Elseif InputNumber = LastInput


InputNumber +=1

'Followed by the new AddInput shortcut

'Followed by everything in the script, unchanged, between the first if and the first end if, including both
richardgatarski  
#510 Posted : Friday, June 28, 2024 8:41:34 AM(UTC)
richardgatarski

Rank: Advanced Member

Groups: Registered
Joined: 2/18/2014(UTC)
Posts: 1,837
Location: Stockholm

Thanks: 144 times
Was thanked: 297 time(s) in 250 post(s)
Here is a "dummy" script that illustrates how to send commands to Companion.

Code:
' Example, setting variables to something in Companion via TCP
' Illustrates how Companion can be commanded many times in a single client session
' By Richard Gatarski, 2024-06-28

' Prepare for TCP
    Dim tcpCompanionIP as string = "127.0.0.1"
    Dim tcpCompanionPort as integer = "16759"
    Dim client As New System.Net.Sockets.TcpClient(tcpCompanionIP, tcpCompanionPort)
    Dim stream As System.Net.Sockets.NetworkStream = client.GetStream()

' Define variables
    Dim content As String = "Default"
    Dim numberOfTimes as Integer = 4

' Loop a number of times
    For aNumber as Integer = 1 to numberOfTimes
        Dim customVariableName As String = "Var" & aNumber.ToString()
        Dim companionCommand as String = "CUSTOM-VARIABLE " & customVariableName  & " SET-VALUE " & content
        Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(companionCommand & Environment.NewLine)
        stream.Write(data, 0, data.Length)
    Next

' Close TCP
    stream.Close()
    client.Close()
thanks 1 user thanked richardgatarski for this useful post.
doggy on 6/28/2024(UTC)
ferex.media  
#511 Posted : Monday, August 19, 2024 7:57:22 PM(UTC)
ferex.media

Rank: Newbie

Groups: Registered
Joined: 1/14/2023(UTC)
Posts: 6
Man
Kazakhstan
Location: Astana

Thanks: 2 times
Hello !!!
Is it possible to change recording filename before start recording by a script ?
doggy  
#512 Posted : Monday, August 19, 2024 9:25:12 PM(UTC)
doggy

Rank: Advanced Member

Groups: Registered
Joined: 12/27/2012(UTC)
Posts: 5,202
Belgium
Location: Belgium

Thanks: 291 times
Was thanked: 953 time(s) in 788 post(s)
Originally Posted by: ferex.media Go to Quoted Post
Hello !!!
Is it possible to change recording filename before start recording by a script ?


No, renaming the recording after is the option

Use this script with adaptation as a guide https://www.vmix.com/kno...ding-to-vmix-as-an-input
thanks 1 user thanked doggy for this useful post.
ferex.media on 8/19/2024(UTC)
crnaman77  
#513 Posted : Saturday, September 14, 2024 12:48:26 PM(UTC)
crnaman77

Rank: Newbie

Groups: Registered
Joined: 2/22/2024(UTC)
Posts: 5
United States
Location: State

Thanks: 1 times
Hello, I'm having trouble with the syntax for a script that will directly send hex code to an ip address:port number to be run as a script in vmix.
ip address = 10.0.1.249
port number = 5678
hex code = 81 01 04 2C 03 FF
Hidden window please
And code to cleanup after if necessary.


I've been at this for two days now and made a little progress, there is a previous post not to far up from here describing how to send something to companion over tcp/ip. Not quite what I'm after, but I think it's close.
If anyone could help with the script that would be much appreciated. Thanks.
WaltG12  
#514 Posted : Monday, September 23, 2024 8:45:01 AM(UTC)
WaltG12

Rank: Advanced Member

Groups: Registered
Joined: 7/4/2021(UTC)
Posts: 285
United States

Thanks: 7 times
Was thanked: 35 time(s) in 31 post(s)
Since I have a bit of time today, I thought I'd expand on my earlier post and share a bit about error handling.

As noted in my earlier post, I still know pretty much nothing about VB.net scripting, but this is info I've cobbled together, and it works, so I figured I'd share it.

Let's start with a basic script to check the output numbers on the first 4 Mix inputs.

Code:
dim xml as string = API.XML()
dim GetMix1ActiveInputNumber as string = ""
dim GetMix2ActiveInputNumber as string = ""
dim GetMix3ActiveInputNumber as string = ""
dim GetMix4ActiveInputNumber as string = ""



dim x as new system.xml.xmldocument
x.loadxml(xml)

GetMix1ActiveInputNumber = (x.SelectSingleNode("//mix[1]/active").InnerText)

GetMix2ActiveInputNumber = (x.SelectSingleNode("//mix[2]/active").InnerText)

GetMix3ActiveInputNumber = (x.SelectSingleNode("//mix[3]/active").InnerText)

GetMix4ActiveInputNumber = (x.SelectSingleNode("//mix[4]/active").InnerText)



Console.WriteLine(GetMix1ActiveInputNumber)

Console.WriteLine(GetMix2ActiveInputNumber)

Console.WriteLine(GetMix3ActiveInputNumber)

Console.WriteLine(GetMix4ActiveInputNumber)



Now this script won't actually do anything in vMix itself besides report the numbers in the Scripting status window.

As I mentioned in my other post (linked above), you can use API Functions to call shortcuts based on those variables, but since I did go into that in my other post, and the point of this one is error handling, I figured I'd just keep it simple.

If you run that script with at least 4 mix inputs open, it'll give you the numbers in that status window, with no issues.

However, because the vMix API XML only reports mix inputs when the mix input is open, if you run that script with only 1, 2, or 3 mix inputs open, it'll error out and stop the script as soon as it tries to retrieve the status of a non-existent mix input, before it gives you any feedback.

So let's fix that.

The first way is extremely basic.

Because the script runs line by line in order, and mix inputs are sequential--you'll never have Mix #3 without Mix #2--you don't actually need the script to keep checking mix inputs after it runs into a fatal error due to a missing one.


So by simply adjusting the script to

Code:
dim xml as string = API.XML()
dim GetMix1ActiveInputNumber as string = ""
dim GetMix2ActiveInputNumber as string = ""
dim GetMix3ActiveInputNumber as string = ""
dim GetMix4ActiveInputNumber as string = ""



dim x as new system.xml.xmldocument
x.loadxml(xml)

GetMix1ActiveInputNumber = (x.SelectSingleNode("//mix[1]/active").InnerText)

Console.WriteLine(GetMix1ActiveInputNumber)

GetMix2ActiveInputNumber = (x.SelectSingleNode("//mix[2]/active").InnerText)

Console.WriteLine(GetMix2ActiveInputNumber)

GetMix3ActiveInputNumber = (x.SelectSingleNode("//mix[3]/active").InnerText)

Console.WriteLine(GetMix3ActiveInputNumber)

GetMix4ActiveInputNumber = (x.SelectSingleNode("//mix[4]/active").InnerText)

Console.WriteLine(GetMix4ActiveInputNumber)



You'll still hit a fatal error that stops the script, but it'll give you the numbers for all the existing mix inputs before that happens, and, again, the non-existent one is only ever going to be followed by non-existent ones.

But, depending on the nature of your script, that's not necessarily going to be a universal or realistically preferable method.

Luckily, VB.net has a built-in mechanism for bypassing fatal errors: "Try...Catch...Finally"

Here's that first script with some very basic "Try...Catch...Finally" error handling.


Code:
dim xml as string = API.XML()
dim GetMix1ActiveInputNumber as string = ""
dim GetMix2ActiveInputNumber as string = ""
dim GetMix3ActiveInputNumber as string = ""
dim GetMix4ActiveInputNumber as string = ""



dim x as new system.xml.xmldocument
x.loadxml(xml)

Try

GetMix1ActiveInputNumber = (x.SelectSingleNode("//mix[1]/active").InnerText)

GetMix2ActiveInputNumber = (x.SelectSingleNode("//mix[2]/active").InnerText)

GetMix3ActiveInputNumber = (x.SelectSingleNode("//mix[3]/active").InnerText)

GetMix4ActiveInputNumber = (x.SelectSingleNode("//mix[4]/active").InnerText)
    
Catch ex As Exception
' Show the exception's error message.
Console.WriteLine(ex.Message)

Finally

Console.WriteLine(GetMix1ActiveInputNumber)

Console.WriteLine(GetMix2ActiveInputNumber)

Console.WriteLine(GetMix3ActiveInputNumber)

Console.WriteLine(GetMix4ActiveInputNumber)

End try


Under "Try" is where you put whatever you expect may result in errors--in this case, that's where it's finding those mix inputs (which may or may not exist) within the API XML.

"Catch" is where you tell it what do with errors, if it finds errors. In this case, it's writing the error message returned to that status window so you can see it.

Finally, "Finally" is where you tell it what to do, whether it caught an error or not.

As I said, I know almost nothing about VB.net scripting.

This is extremely basic error handling--there are ways to expand beyond it. (I don't know or use them, because this works fine for my extremely rudimentary scripts.)

If nothing else, I figured this would make a decent tutorial of the basic steps to overcome fatal errors in scripts.
noobvmixer22  
#515 Posted : Tuesday, September 24, 2024 11:21:30 AM(UTC)
noobvmixer22

Rank: Newbie

Groups: Registered
Joined: 9/24/2024(UTC)
Posts: 2

Overlay Scripting
hi i need some help
i have a gt title input and it has 3 text fields i want to trigger it to overlayin1 then wait 4 seconds then overlayout1 when txt from name.txt changes

i tried to use chatgpt but doesnt work thanks!
WaltG12  
#516 Posted : Tuesday, September 24, 2024 12:40:38 PM(UTC)
WaltG12

Rank: Advanced Member

Groups: Registered
Joined: 7/4/2021(UTC)
Posts: 285
United States

Thanks: 7 times
Was thanked: 35 time(s) in 31 post(s)
Originally Posted by: noobvmixer22 Go to Quoted Post
Overlay Scripting
hi i need some help
i have a gt title input and it has 3 text fields i want to trigger it to overlayin1 then wait 4 seconds then overlayout1 when txt from name.txt changes

i tried to use chatgpt but doesnt work thanks!


That's pretty much the exact same thing I posted in my Zoom script above (which is why I posted it after making a post about how to adapt scripts)--no ChatGPT necessary.

Loop the script
Use a dynamic value or an additional hidden title text field to track what was in the name.txt field on the last loop
Compare that to what's currently in the name.txt field
Act accordingly

If you want it to wait 4 seconds after the data change while in, I'd use:

Console.WriteLine("name.txt changed")
Sleep(4000)
OverlayOut

Or if you just want a 4 second timer from in to out:

OverlayIn
Sleep 4000
OverlayOut
doggy  
#517 Posted : Sunday, October 20, 2024 7:12:24 PM(UTC)
doggy

Rank: Advanced Member

Groups: Registered
Joined: 12/27/2012(UTC)
Posts: 5,202
Belgium
Location: Belgium

Thanks: 291 times
Was thanked: 953 time(s) in 788 post(s)
Customize (convert) filename for split recordings

See post:
https://forums.vmix.com/...ame-for-split-recordings

Code:
'Renaming files recorded with the "New File Every" option from sequential numbering to actual creation time
'Example with new file every 1 minute
'test - 20 October 2024 - 10-42-29 AM - 00000.mp4   to   test - 20-October-2024 - 10-42-29.mp4
'test - 20 October 2024 - 10-42-29 AM - 00001.mp4   to   test - 20-October-2024 - 10-43-29.mp4
'test - 20 October 2024 - 10-42-29 AM - 00002.mp4   to   test - 20-October-2024 - 10-44-29.mp4

'Specify folder were recordings are saved
Dim di As New DirectoryInfo("D:\recordedfiles\")  'Could also be retrieved from the vMix config file (more automation) when brave ;-)

' Get file information from directory/folder
Dim fileArr As FileInfo() = di.GetFiles()
Dim fInf As FileInfo

For Each fInf In fileArr
    ' Display the name of file.
    Console.WriteLine("Filename: " + fInf.Name)  'for debug

    'trim filename
    Dim trimstring As String = (fInf.Name).Substring(0, (fInf.Name).IndexOf("-") -1)

    ' Get the creation date/time of the file
    Dim fileCreatedDate As DateTime = File.GetCreationTime(di.tostring + fInf.name)
    Console.WriteLine("file created: " + fileCreatedDate.ToString)  'for debug

    dim sourcepath as string = di.tostring +  (fInf.Name)
    'Create new  file name with properly formatted time and original file extention 
    dim destinationpath as string = di.tostring + trimstring + " - " + fileCreatedDate.tostring("dd-MMMM-yyyy - HH-mm-ss") + Path.GetExtension(fInf.name)
    console.writeline("Old: " + sourcepath)    'for debug
    console.writeline("New: " + destinationpath)  'for debug

    'Rename the file
    System.IO.File.Move(sourcePath, destinationPath)  'destination can be another folder when specified

Next fInf

'no comments version:

Dim di As New DirectoryInfo("D:\recordedfiles\")  
Dim fileArr As FileInfo() = di.GetFiles()
Dim fInf As FileInfo
For Each fInf In fileArr
    Dim trimstring As String = (fInf.Name).Substring(0, (fInf.Name).IndexOf("-") -1)
    Dim fileCreatedDate As DateTime = File.GetCreationTime(di.tostring + fInf.name)
    dim sourcepath as string = di.tostring +  (fInf.Name)
    dim destinationpath as string = di.tostring + trimstring + " - " + fileCreatedDate.tostring("dd-MMMM-yyyy - HH-mm-ss") + Path.GetExtension(fInf.name)
    System.IO.File.Move(sourcePath, destinationPath)  
Next fInf
rodberg  
#518 Posted : Sunday, November 10, 2024 7:39:50 AM(UTC)
rodberg

Rank: Newbie

Groups: Registered
Joined: 11/10/2024(UTC)
Posts: 1
Denmark
Location: copenhagen

HI guys,

I could really use some help, I am not understanding the scripting :) so im pretty lost.

I would love a script that does:

Checks the Headline.Text (from the title editor) to see if the name is "-----" IF it is, activate the command DataSourceNextRow with the value of 6...


the idea behind the script is that I am pulling titles from a google sheets (name and title) but the excel file has empty rows, so when I scroll through the titles, it will also show those empty names, SO in order to avoid that I just have a row with "-----" added after the last title is added to the google sheet...

I haven't found another way to do the same (I dont want to hardcode a specific number of titles that you are able to use, so in Excel I just add the names, and on Sheet2 it automatically puts in the names in two columns - and adds the "-----" in the row after the last name - because google sheets just adds 500 rows if I delete the excess rows and just have a formula that adds rows as needed )

sorry for that convoluted explanation, I am having a difficult time explaining it... but my main goal is to be able to scroll through the titles so each speaker can get their own title (ok now im just mansplaining) and I dont want to add a new input for every title. so I just scroll through them, but as the number of speakers will vary, I can't just put in a hardcoded number to scroll through, hence the google sheets that self populate, but the empty rows are shown in the titles as well, which is what I want to avoid - hence the magyver solution to just check for the "-----"


chatgpt hasn't been any help sadly, it keeps trying to give me c# code that vmix doesn't understand (unless I am doing something wrong)..

SO please help me obi won Kenobi , you're my only hope.

Kind Regards
Rod
WaltG12  
#519 Posted : Sunday, November 10, 2024 8:15:31 AM(UTC)
WaltG12

Rank: Advanced Member

Groups: Registered
Joined: 7/4/2021(UTC)
Posts: 285
United States

Thanks: 7 times
Was thanked: 35 time(s) in 31 post(s)
Originally Posted by: rodberg Go to Quoted Post
Checks the Headline.Text (from the title editor) to see if the name is "-----" IF it is, activate the command DataSourceNextRow with the value of 6...


https://forums.vmix.com/...g-for-Dummies#post113993

https://forums.vmix.com/...g-for-Dummies#post113944
doggy  
#520 Posted : Sunday, November 10, 2024 8:30:32 AM(UTC)
doggy

Rank: Advanced Member

Groups: Registered
Joined: 12/27/2012(UTC)
Posts: 5,202
Belgium
Location: Belgium

Thanks: 291 times
Was thanked: 953 time(s) in 788 post(s)
Originally Posted by: rodberg Go to Quoted Post
HI guys,

Checks the Headline.Text (from the title editor) to see if the name is "-----" IF it is, activate the command DataSourceNextRow with the value of 6...



There are plenty of examples in this thread showing how to retrieve content from a title
Then its just a matter of comparing the retrieved result with the "-----"string
If it matches then do a small for next loop doing 6 times the DataSourceNextRow command ( check the shortcut commands and one will notice one can not give it a value as it specifically does single next one as in the name of the command)

Quote:

chatgpt hasn't been any help sadly, it keeps trying to give me c# code that vmix doesn't understand (unless I am doing something wrong)..


First of all in order to get a proper result a basic understanding of vb.net coding is helpfull (use google ;-) )
In this case if then else statements and for next loops
If one cant explain properly to chatgtp or a living person your intention the result will be meaningless


The logic:
retrieve title Headline.Text content
if retrieved value = "----"
for count = 1 to 6
DataSourceNextRow
next
end if
Users browsing this topic
Guest (2)
26 Pages«<242526
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.