Remove Gaps Across Multiple Tracks

Jayboy75 wrote on 12/8/2022, 11:32 PM

I edit a podcast with four co-hosts, each of whom records their own audio track and sends it to me for post-production. I've been looking for ways to speed up my editing time, and just started playing around with the trial version of Vegasaur, which appears to do a good job at cutting out silences.

But now I have four separate tracks of audio with time gaps that need to be closed while maintaining the synchronization of the audio across all tracks. I've done a bunch of research and have found lots of ways to close gaps in a single track, but nothing about how I can close them across multiple tracks.

Basically, I need to write (or find) a script that says (in pseudo-code): If no one is talking, close the gap (red areas shown in the image below).



Anyone know of an existing script or extension that does this?

Comments

jetdv wrote on 12/9/2022, 9:30 AM

@Jayboy75 That can certainly be done. The hardest part may be in finding the "red areas" - I suppose they'd be really easy to find if you marked them as regions on the timeline but then you'd need to manually find them. What I would do is search for the red areas, and then move everything on every track after that red area left the size of the red area. Then look for another red area and repeat always moving only everything after the red area. Repeat until no more red areas are found.

I do not know of an existing script to do this but could certainly take a look at this for a tutorial.

Jayboy75 wrote on 12/9/2022, 12:20 PM

I've started playing around with scripts (I'm a JS dev by trade), but I'm used to writing ES6+ which Vegas doesn't appear to support, so I'm resorting to the old syntax ('for' loops, ugh...)

Iterating recursively through Track > Event > Event.Selected feels somewhat mind-boggling considering that using this method, each event's ending timecode would need to be compared to the starting timecode of the nearest events on each track containing a selected event (to determine the amount of blank space present at each interval). There's got to be a better way, but I'm a n00b when it comes to the Vegas API, so certainly any pointers you can offer would be helpful.

EdiTools wrote on 12/9/2022, 12:56 PM

You can use the Auto Ripple feature to speed up the editing a bit.

But if your project is too long, you can use other features of Vegasaur as an alternative way.

I would also love to have a script that does this, as I've needed this feature many times.

Jayboy75 wrote on 12/9/2022, 1:16 PM

@EdiTools That first method is essentially what I do during my usual editing process, which is the reason I'm looking for some type of automation (closing gaps over an hour-long podcast is time-consuming, to say the least).

Your second method is an interesting workaround. A bit tedious, but it could still potentially save me a significant amount of time if a more automated solution isn't possible.

Still interested in exploring whether there's some way from a scripting perspective that @jetdv or another experienced scripter could work a little magic on.

jetdv wrote on 12/9/2022, 4:54 PM

@Jayboy75, haven't had time to look at it yet but I need to remind myself to look at this. It's definitely doable. Like I said, the toughest part is finding the "red areas". Once that's found, everything else would be simple.

In fact, I think it would be best to have a loop that just said:
 

While looking for a red area
{
  look for a red area
  if  a red area is found 
     {
          move everything on every track after that red area the length of the red area
     } else { 
          no longer looking
     }
}

Like I said, the hard part is "look for a red area".

But the GOOD news is that on the subsequent "look for a red area" calls, you can start looking where you found the previous one instead of starting at the beginning. And it can be made "smarter" by knowing if there's an event at this location, move to the end of this event before looking at the other tracks.

Jayboy75 wrote on 12/9/2022, 7:36 PM

Finding the gaps with no events def feels like the hardest part. That's where your superior familiarity with the API likely comes in. And in terms of how the 'look for' piece is written, I don't know whether it's easier to say

Look for the next red area across all selected Tracks

or

Look for the next red area among all selected Events

 

EdiTools wrote on 12/9/2022, 10:23 PM

@Jayboy75 In Premiere, technically the way the Close Gaps option works across tracks is correct. It would be really nice to have an option like that in VEGAS too. @VEGASDerek

While a script does not come out, see my screen record bellow and try this. Your doubt forced me to look for a solution and thanks to it I now know the answer.

.

@jetdv See if my screen recording helps in creating a scrypt that automates the steps. The script syntax would look something like this:
1.Create Regions in selected events
2.Join Regions
3.Invert Regions
4.Delete events inside Regions on selected tracks
5.Auto Riple in All Tracks, Markers and Regions
6.Delete Regions

You are one of the most skilled scripting people I know. As you know, I understand very little about scripting. So that's the only way I can help.

jetdv wrote on 12/10/2022, 8:14 AM

@Jayboy75 I think "across" would be the better terminology. @EdiTools, I see what you were doing there. I'll play with this and see what we can come up with.

Does it matter if we create regions? Would it be better if it didn't create regions? Naturally, we'd want to delete the regions when we were finished.

I can see a couple different ways to do this. With the regions would probably be slightly faster as you wouldn't need to go through the events on any one track multiple times.

jetdv wrote on 12/10/2022, 10:27 AM

@Jayboy75 @EdiTools please test this out. If you see a project that fails, please send me that project to test and see why it's failing. Here's what I'm seeing with this version. My before:

and my after:

It is creating regions along the way so if you have regions on the timeline, it will mess things up. Here's the code so you can test it. A full tutorial will be released early next year but I wanted you to be able to test the code now. Just copy this into Notepad and save it as something like "RemoveHoles.cs" and put it into [My Documents]\Vegas Script Menu
 

using System;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Drawing;
using System.Runtime;
using System.Xml;
using ScriptPortal.Vegas;

namespace Test_Script
{
    public class Class1
    {
        public Vegas myVegas;

        public void Main(Vegas vegas)
        {
            myVegas = vegas;

            placeRegionsAroundAudio();
            reverseRegions();
            closeGaps();
        }

        private void placeRegionsAroundAudio()
        {
            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                foreach (TrackEvent evnt in myTrack.Events)
                {
                    AddRegion(evnt);
                }
            }
        }

        private void AddRegion(TrackEvent evnt)
        {
            bool eventUnderRegion = false;

            foreach (ScriptPortal.Vegas.Region myRegion in myVegas.Project.Regions)
            {
                Timecode regionEnd = myRegion.Position + myRegion.Length;

                if (evnt.Start >= myRegion.Position && evnt.Start <= regionEnd)
                {
                    eventUnderRegion = true;
                }
                if (evnt.End >= myRegion.Position && evnt.End <= regionEnd)
                {
                    eventUnderRegion = true;
                }

                if (eventUnderRegion)
                {
                    if (evnt.Start < myRegion.Position)
                    {
                        myRegion.Position = evnt.Start;
                        myRegion.Length = regionEnd - evnt.Start;
                    }
                    if (evnt.End > regionEnd)
                    {
                        myRegion.Length = evnt.End - myRegion.Position;
                        if (myVegas.Project.Regions[myRegion.Index + 1].Position < evnt.End)
                        {
                            Timecode newEnd = myVegas.Project.Regions[myRegion.Index + 1].Position + myVegas.Project.Regions[myRegion.Index + 1].Length;
                            myRegion.Length = newEnd - myRegion.Position;
                            myVegas.Project.Regions.Remove(myVegas.Project.Regions[myRegion.Index + 1]);
                        }
                    }
                    break;
                }
            }

            if (!eventUnderRegion)
            {
                ScriptPortal.Vegas.Region newRegion = new ScriptPortal.Vegas.Region(evnt.Start, evnt.Length, "Audio Present");
                myVegas.Project.Regions.Add(newRegion);
            }
        }

        private void reverseRegions()
        {
            ArrayList RegionStart = new ArrayList();
            ArrayList RegionLength = new ArrayList();

            foreach (ScriptPortal.Vegas.Region myRegion in myVegas.Project.Regions)
            {
                RegionStart.Add(myRegion.Position);
                RegionLength.Add(myRegion.Length);
            }

            for (int i=myVegas.Project.Regions.Count - 1; i>=0; i--)
            {
                myVegas.Project.Regions.Remove(myVegas.Project.Regions[i]);
            }

            Timecode nextStart = new Timecode(0);
            for (int i = 0; i < RegionStart.Count; i++)
            {
                if (i==0)
                {
                    if ((Timecode)RegionStart[i] > Timecode.FromFrames(0))
                    {
                        addRegion(Timecode.FromFrames(0), (Timecode)RegionStart[i]);
                    }
                }
                else
                {
                    addRegion(nextStart, (Timecode)RegionStart[i] - nextStart);
                }
                nextStart = (Timecode)RegionStart[i] + (Timecode)RegionLength[i];
            }
        }

        private void addRegion(Timecode regStart, Timecode regLen)
        {
            ScriptPortal.Vegas.Region newRegion = new ScriptPortal.Vegas.Region(regStart, regLen, "Audio Absent");
            myVegas.Project.Regions.Add(newRegion);
        }

        private void closeGaps()
        {
            for (int i = myVegas.Project.Regions.Count - 1; i >= 0; i--)
            {
                Timecode regStart = myVegas.Project.Regions[i].Position;
                Timecode regLen = myVegas.Project.Regions[i].Length;

                foreach (Track myTrack in myVegas.Project.Tracks)
                {
                    foreach(TrackEvent evnt in myTrack.Events)
                    {
                        if (evnt.Start > regStart)
                        {
                            evnt.Start = evnt.Start - regLen;
                        }
                    }
                }
                myVegas.Project.Regions.Remove(myVegas.Project.Regions[i]);
            }
        }


    }
}

public class EntryPoint
{
    public void FromVegas(Vegas vegas)
    {
        Test_Script.Class1 test = new Test_Script.Class1();
        test.Main(vegas);
    }
}

 

EdiTools wrote on 12/10/2022, 1:56 PM

@jetdv I tested your script on three small projects. It worked great on two. The problem with creating regions you mentioned occurred in only one of the projects. See my screen recording.

The projects I used in the tests can be downloaded from this link: https://drive.google.com/file/d/1wdAt3tx1exFxnIc7l77OQCCRE7gCR5lV/view?usp=sharing

Jayboy75 wrote on 12/10/2022, 2:20 PM

Awesome! I'll test out this script in my project when I sit down to edit this evening.

jetdv wrote on 12/10/2022, 3:10 PM

@EdiTools, so it was Test3 where it died? I do see a crash on that one so I'll research it.

jetdv wrote on 12/10/2022, 3:24 PM

@EdiTools, this one fixes the issue with "Test3".
@Jayboy75, please test with this version.

using System;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Drawing;
using System.Runtime;
using System.Xml;
using ScriptPortal.Vegas;

namespace Test_Script
{
    public class Class1
    {
        public Vegas myVegas;

        public void Main(Vegas vegas)
        {
            myVegas = vegas;

            placeRegionsAroundAudio();
            reverseRegions();
            closeGaps();
        }

        private void placeRegionsAroundAudio()
        {
            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                foreach (TrackEvent evnt in myTrack.Events)
                {
                    AddRegion(evnt);
                }
            }
        }

        private void AddRegion(TrackEvent evnt)
        {
            bool eventUnderRegion = false;

            foreach (ScriptPortal.Vegas.Region myRegion in myVegas.Project.Regions)
            {
                Timecode regionEnd = myRegion.Position + myRegion.Length;

                if (evnt.Start >= myRegion.Position && evnt.Start <= regionEnd)
                {
                    eventUnderRegion = true;
                }
                if (evnt.End >= myRegion.Position && evnt.End <= regionEnd)
                {
                    eventUnderRegion = true;
                }

                if (eventUnderRegion)
                {
                    if (evnt.Start < myRegion.Position)
                    {
                        myRegion.Position = evnt.Start;
                        myRegion.Length = regionEnd - evnt.Start;
                    }
                    if (evnt.End > regionEnd)
                    {
                        myRegion.Length = evnt.End - myRegion.Position;
                        if (myRegion.Index + 1 != myVegas.Project.Regions.Count)
                        {
                            if (myVegas.Project.Regions[myRegion.Index + 1].Position < evnt.End)
                            {
                                Timecode newEnd = myVegas.Project.Regions[myRegion.Index + 1].Position + myVegas.Project.Regions[myRegion.Index + 1].Length;
                                myRegion.Length = newEnd - myRegion.Position;
                                myVegas.Project.Regions.Remove(myVegas.Project.Regions[myRegion.Index + 1]);
                            }
                        }
                    }
                    break;
                }
            }

            if (!eventUnderRegion)
            {
                ScriptPortal.Vegas.Region newRegion = new ScriptPortal.Vegas.Region(evnt.Start, evnt.Length, "Audio Present");
                myVegas.Project.Regions.Add(newRegion);
            }
        }

        private void reverseRegions()
        {
            ArrayList RegionStart = new ArrayList();
            ArrayList RegionLength = new ArrayList();

            foreach (ScriptPortal.Vegas.Region myRegion in myVegas.Project.Regions)
            {
                RegionStart.Add(myRegion.Position);
                RegionLength.Add(myRegion.Length);
            }

            for (int i=myVegas.Project.Regions.Count - 1; i>=0; i--)
            {
                myVegas.Project.Regions.Remove(myVegas.Project.Regions[i]);
            }

            Timecode nextStart = new Timecode(0);
            for (int i = 0; i < RegionStart.Count; i++)
            {
                if (i==0)
                {
                    if ((Timecode)RegionStart[i] > Timecode.FromFrames(0))
                    {
                        addRegion(Timecode.FromFrames(0), (Timecode)RegionStart[i]);
                    }
                }
                else
                {
                    addRegion(nextStart, (Timecode)RegionStart[i] - nextStart);
                }
                nextStart = (Timecode)RegionStart[i] + (Timecode)RegionLength[i];
            }
        }

        private void addRegion(Timecode regStart, Timecode regLen)
        {
            ScriptPortal.Vegas.Region newRegion = new ScriptPortal.Vegas.Region(regStart, regLen, "Audio Absent");
            myVegas.Project.Regions.Add(newRegion);
        }

        private void closeGaps()
        {
            for (int i = myVegas.Project.Regions.Count - 1; i >= 0; i--)
            {
                Timecode regStart = myVegas.Project.Regions[i].Position;
                Timecode regLen = myVegas.Project.Regions[i].Length;

                foreach (Track myTrack in myVegas.Project.Tracks)
                {
                    foreach(TrackEvent evnt in myTrack.Events)
                    {
                        if (evnt.Start > regStart)
                        {
                            evnt.Start = evnt.Start - regLen;
                        }
                    }
                }
                myVegas.Project.Regions.Remove(myVegas.Project.Regions[i]);
            }
        }


    }
}

public class EntryPoint
{
    public void FromVegas(Vegas vegas)
    {
        Test_Script.Class1 test = new Test_Script.Class1();
        test.Main(vegas);
    }
}

Here's what I actually changed to make it work. The first "if" statement here was added.

                        if (myRegion.Index + 1 != myVegas.Project.Regions.Count)
                        {
                            if (myVegas.Project.Regions[myRegion.Index + 1].Position < evnt.End)
                            {
                                Timecode newEnd = myVegas.Project.Regions[myRegion.Index + 1].Position + myVegas.Project.Regions[myRegion.Index + 1].Length;
                                myRegion.Length = newEnd - myRegion.Position;
                                myVegas.Project.Regions.Remove(myVegas.Project.Regions[myRegion.Index + 1]);
                            }
                        }

In short, it was trying to access a region that did not exist which is why it died. Let me know if you see any other issues with this.

EdiTools wrote on 12/10/2022, 3:53 PM

@jetdv Now everything is working properly here. This script will go down among my favorites. Really very helpful. Your job is AWESOME!

jetdv wrote on 12/10/2022, 4:26 PM

I'll have a tutorial on this script in February on my site.

EdiTools wrote on 12/10/2022, 7:02 PM

@jetdv I'm still doing some tests with the script. See my screen recording. I encountered this little problem.

The project is in this link. https://drive.google.com/file/d/1NLPAOA6QMgkIq1QyVG1Mx4x7LzyoAUJL/view?usp=sharing

jetdv wrote on 12/10/2022, 7:44 PM

@EdiTools @Jayboy75 Thanks for the project. Please test out this version...
 

using System;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Drawing;
using System.Runtime;
using System.Xml;
using ScriptPortal.Vegas;

namespace Test_Script
{
    public class Class1
    {
        public Vegas myVegas;

        public void Main(Vegas vegas)
        {
            myVegas = vegas;

            placeRegionsAroundAudio();

            checkOverlappedRegions();

            reverseRegions();

            closeGaps();
        }

        private void placeRegionsAroundAudio()
        {
            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                foreach (TrackEvent evnt in myTrack.Events)
                {
                    AddRegion(evnt);
                }
            }
        }

        private void AddRegion(TrackEvent evnt)
        {
            bool eventUnderRegion = false;

            foreach (ScriptPortal.Vegas.Region myRegion in myVegas.Project.Regions)
            {
                Timecode regionEnd = myRegion.Position + myRegion.Length;

                if (evnt.Start >= myRegion.Position && evnt.Start <= regionEnd)
                {
                    eventUnderRegion = true;
                }
                if (evnt.End >= myRegion.Position && evnt.End <= regionEnd)
                {
                    eventUnderRegion = true;
                }

                if (eventUnderRegion)
                {
                    if (evnt.Start < myRegion.Position)
                    {
                        myRegion.Position = evnt.Start;
                        myRegion.Length = regionEnd - evnt.Start;
                    }
                    if (evnt.End > regionEnd)
                    {
                        myRegion.Length = evnt.End - myRegion.Position;
                        if (myRegion.Index + 1 != myVegas.Project.Regions.Count)
                        {
                            if (myVegas.Project.Regions[myRegion.Index + 1].Position < evnt.End)
                            {
                                Timecode newEnd = myVegas.Project.Regions[myRegion.Index + 1].Position + myVegas.Project.Regions[myRegion.Index + 1].Length;
                                myRegion.Length = newEnd - myRegion.Position;
                                myVegas.Project.Regions.Remove(myVegas.Project.Regions[myRegion.Index + 1]);
                            }
                        }
                    }
                    break;
                }
            }

            if (!eventUnderRegion)
            {
                ScriptPortal.Vegas.Region newRegion = new ScriptPortal.Vegas.Region(evnt.Start, evnt.Length, "Audio Present");
                myVegas.Project.Regions.Add(newRegion);
            }
        }

        private void checkOverlappedRegions()
        {
            bool foundoverlap = true;
            Timecode prevStart = new Timecode(0);
            Timecode prevEnd = new Timecode(0);

            while (foundoverlap)
            {
                for (int i = 0; i < myVegas.Project.Regions.Count; i++)
                {
                    foundoverlap = false;
                    ScriptPortal.Vegas.Region myRegion = myVegas.Project.Regions[i];
                    if (i == 0)
                    {
                        prevStart = myRegion.Position;
                        prevEnd = myRegion.Position + myRegion.Length;
                    }
                    else
                    {
                        Timecode regStart = myRegion.Position;
                        Timecode regEnd = myRegion.Position + myRegion.Length;

                        if (regStart >= prevStart && regStart <= prevEnd)
                        {
                            MessageBox.Show("Inside found overlap");
                            foundoverlap = true;
                            if (prevEnd < regEnd)
                            {
                                myVegas.Project.Regions[i - 1].Length = regEnd - prevStart;
                                myVegas.Project.Regions.Remove(myRegion);
                                break;
                            }
                            else
                            {
                                myVegas.Project.Regions.Remove(myRegion);
                                break;
                            }
                        }
                    }

                }
            }
        }

        private void reverseRegions()
        {
            ArrayList RegionStart = new ArrayList();
            ArrayList RegionLength = new ArrayList();

            foreach (ScriptPortal.Vegas.Region myRegion in myVegas.Project.Regions)
            {
                RegionStart.Add(myRegion.Position);
                RegionLength.Add(myRegion.Length);
            }

            for (int i = myVegas.Project.Regions.Count - 1; i >= 0; i--)
            {
                myVegas.Project.Regions.Remove(myVegas.Project.Regions[i]);
            }

            Timecode nextStart = new Timecode(0);
            for (int i = 0; i < RegionStart.Count; i++)
            {
                if (i == 0)
                {
                    if ((Timecode)RegionStart[i] > Timecode.FromFrames(0))
                    {
                        addRegion(Timecode.FromFrames(0), (Timecode)RegionStart[i]);
                    }
                }
                else
                {
                    addRegion(nextStart, (Timecode)RegionStart[i] - nextStart);
                }
                nextStart = (Timecode)RegionStart[i] + (Timecode)RegionLength[i];
            }
        }

        private void addRegion(Timecode regStart, Timecode regLen)
        {
            ScriptPortal.Vegas.Region newRegion = new ScriptPortal.Vegas.Region(regStart, regLen, "Audio Absent");
            myVegas.Project.Regions.Add(newRegion);
        }

        private void closeGaps()
        {
            for (int i = myVegas.Project.Regions.Count - 1; i >= 0; i--)
            {
                Timecode regStart = myVegas.Project.Regions[i].Position;
                Timecode regLen = myVegas.Project.Regions[i].Length;

                foreach (Track myTrack in myVegas.Project.Tracks)
                {
                    foreach (TrackEvent evnt in myTrack.Events)
                    {
                        if (evnt.Start > regStart)
                        {
                            evnt.Start = evnt.Start - regLen;
                        }
                    }
                }
                myVegas.Project.Regions.Remove(myVegas.Project.Regions[i]);
            }
        }


    }
}

public class EntryPoint
{
    public void FromVegas(Vegas vegas)
    {
        Test_Script.Class1 test = new Test_Script.Class1();
        test.Main(vegas);
    }
}

 

EdiTools wrote on 12/10/2022, 8:02 PM

@jetdv See my screen record. You can use the last project (Test 5) to reproduce this.

jetdv wrote on 12/10/2022, 8:31 PM

@EdiTools Ok, this one fixes that issue. (and I got rid of the message I accidentally left in the previous one.
 

using System;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Drawing;
using System.Runtime;
using System.Xml;
using ScriptPortal.Vegas;

namespace Test_Script
{
    public class Class1
    {
        public Vegas myVegas;

        public void Main(Vegas vegas)
        {
            myVegas = vegas;

            placeRegionsAroundAudio();
            checkOverlappedRegions();
            reverseRegions();
            closeGaps();
        }

        private void placeRegionsAroundAudio()
        {
            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                foreach (TrackEvent evnt in myTrack.Events)
                {
                    AddRegion(evnt);
                }
            }
        }

        private void AddRegion(TrackEvent evnt)
        {
            bool eventUnderRegion = false;

            foreach (ScriptPortal.Vegas.Region myRegion in myVegas.Project.Regions)
            {
                Timecode regionEnd = myRegion.Position + myRegion.Length;

                if (evnt.Start >= myRegion.Position && evnt.Start <= regionEnd)
                {
                    eventUnderRegion = true;
                }
                if (evnt.End >= myRegion.Position && evnt.End <= regionEnd)
                {
                    eventUnderRegion = true;
                }

                if (eventUnderRegion)
                {
                    if (evnt.Start < myRegion.Position)
                    {
                        myRegion.Position = evnt.Start;
                        myRegion.Length = regionEnd - evnt.Start;
                    }
                    if (evnt.End > regionEnd)
                    {
                        myRegion.Length = evnt.End - myRegion.Position;
                        if (myRegion.Index + 1 != myVegas.Project.Regions.Count)
                        {
                            if (myVegas.Project.Regions[myRegion.Index + 1].Position < evnt.End)
                            {
                                Timecode newEnd = myVegas.Project.Regions[myRegion.Index + 1].Position + myVegas.Project.Regions[myRegion.Index + 1].Length;
                                myRegion.Length = newEnd - myRegion.Position;
                                myVegas.Project.Regions.Remove(myVegas.Project.Regions[myRegion.Index + 1]);
                            }
                        }
                    }
                    break;
                }
            }

            if (!eventUnderRegion)
            {
                ScriptPortal.Vegas.Region newRegion = new ScriptPortal.Vegas.Region(evnt.Start, evnt.Length, "Audio Present");
                myVegas.Project.Regions.Add(newRegion);
            }
        }

        private void checkOverlappedRegions()
        {
            bool foundoverlap = true;

            while (foundoverlap)
            {
                for (int i = 0; i < myVegas.Project.Regions.Count; i++)
                {
                    foundoverlap = false;
                    ScriptPortal.Vegas.Region myRegion = myVegas.Project.Regions[i];

                    Timecode regStart = myRegion.Position;
                    Timecode regEnd = myRegion.Position + myRegion.Length;

                    foreach(ScriptPortal.Vegas.Region thisRegion in myVegas.Project.Regions)
                    {
                        if (myRegion.Index != thisRegion.Index)
                        {
                            Timecode thisStart = thisRegion.Position;
                            Timecode thisEnd = thisRegion.Position + thisRegion.Length;

                            if (regStart >= thisStart && regStart <= thisEnd)
                            {
                                foundoverlap = true;
                                if (thisEnd < regEnd)
                                {
                                    thisRegion.Length = regEnd - thisStart;
                                    myVegas.Project.Regions.Remove(myRegion);
                                    break;
                                }
                                else
                                {
                                    myVegas.Project.Regions.Remove(myRegion);
                                    break;
                                }
                            }
                        }
                    }

                    if (foundoverlap)
                    {
                        break;
                    }
                }
            }
        }

        private void reverseRegions()
        {
            ArrayList RegionStart = new ArrayList();
            ArrayList RegionLength = new ArrayList();

            foreach (ScriptPortal.Vegas.Region myRegion in myVegas.Project.Regions)
            {
                RegionStart.Add(myRegion.Position);
                RegionLength.Add(myRegion.Length);
            }

            for (int i = myVegas.Project.Regions.Count - 1; i >= 0; i--)
            {
                myVegas.Project.Regions.Remove(myVegas.Project.Regions[i]);
            }

            Timecode nextStart = new Timecode(0);
            for (int i = 0; i < RegionStart.Count; i++)
            {
                if (i == 0)
                {
                    if ((Timecode)RegionStart[i] > Timecode.FromFrames(0))
                    {
                        addRegion(Timecode.FromFrames(0), (Timecode)RegionStart[i]);
                    }
                }
                else
                {
                    addRegion(nextStart, (Timecode)RegionStart[i] - nextStart);
                }
                nextStart = (Timecode)RegionStart[i] + (Timecode)RegionLength[i];
            }
        }

        private void addRegion(Timecode regStart, Timecode regLen)
        {
            ScriptPortal.Vegas.Region newRegion = new ScriptPortal.Vegas.Region(regStart, regLen, "Audio Absent");
            myVegas.Project.Regions.Add(newRegion);
        }

        private void closeGaps()
        {
            for (int i = myVegas.Project.Regions.Count - 1; i >= 0; i--)
            {
                Timecode regStart = myVegas.Project.Regions[i].Position;
                Timecode regLen = myVegas.Project.Regions[i].Length;

                foreach (Track myTrack in myVegas.Project.Tracks)
                {
                    foreach (TrackEvent evnt in myTrack.Events)
                    {
                        if (evnt.Start > regStart)
                        {
                            evnt.Start = evnt.Start - regLen;
                        }
                    }
                }
                myVegas.Project.Regions.Remove(myVegas.Project.Regions[i]);
            }
        }


    }
}

public class EntryPoint
{
    public void FromVegas(Vegas vegas)
    {
        Test_Script.Class1 test = new Test_Script.Class1();
        test.Main(vegas);
    }
}

 

EdiTools wrote on 12/11/2022, 4:40 AM

@jetdv This time I tested the script in various project scenarios to have as many variables as possible. So far I haven't found any problems. I will continue using it on a daily basis in my projects and if I find any improvement points I will let you know. Thank you very much!

jetdv wrote on 12/11/2022, 7:16 AM

@EdiTools good to hear. I'll start a series of tutorials on this to explain what everything does.

jetdv wrote on 12/11/2022, 7:53 AM

@EdiTools @Jayboy75 Here's one more update. Joelson, this takes care of the issue found in test 6.
 

using System;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Drawing;
using System.Runtime;
using System.Xml;
using ScriptPortal.Vegas;

namespace Test_Script
{
    public class Class1
    {
        public Vegas myVegas;

        public void Main(Vegas vegas)
        {
            myVegas = vegas;

            placeRegionsAroundAudio();
            checkOverlappedRegions();
            reverseRegions();
            closeGaps();
        }

        private void placeRegionsAroundAudio()
        {
            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                foreach (TrackEvent evnt in myTrack.Events)
                {
                    AddRegion(evnt);
                }
            }
        }

        private void AddRegion(TrackEvent evnt)
        {
            bool eventUnderRegion = false;

            foreach (ScriptPortal.Vegas.Region myRegion in myVegas.Project.Regions)
            {
                Timecode regionEnd = myRegion.Position + myRegion.Length;

                if (evnt.Start >= myRegion.Position && evnt.Start <= regionEnd)
                {
                    eventUnderRegion = true;
                }
                if (evnt.End >= myRegion.Position && evnt.End <= regionEnd)
                {
                    eventUnderRegion = true;
                }

                if (eventUnderRegion)
                {
                    if (evnt.Start < myRegion.Position)
                    {
                        myRegion.Position = evnt.Start;
                        if (evnt.Length > myRegion.Length)
                        {
                            myRegion.Length = evnt.Length;
                        }
                        else
                        {
                            myRegion.Length = regionEnd - evnt.Start;
                        }
                        regionEnd = myRegion.Position + myRegion.Length;
                    }
                    if (evnt.End > regionEnd)
                    {
                        myRegion.Length = evnt.End - myRegion.Position;

                        if (myRegion.Index + 1 != myVegas.Project.Regions.Count)
                        {
                            if (myVegas.Project.Regions[myRegion.Index + 1].Position < evnt.End)
                            {
                                Timecode newEnd = myVegas.Project.Regions[myRegion.Index + 1].Position + myVegas.Project.Regions[myRegion.Index + 1].Length;
                                if (newEnd > myRegion.Position + myRegion.Length)
                                {
                                    myRegion.Length = newEnd - myRegion.Position;
                                }
                                myVegas.Project.Regions.Remove(myVegas.Project.Regions[myRegion.Index + 1]);
                            }
                        }
                    }
                    break;
                }
            }

            if (!eventUnderRegion)
            {
                ScriptPortal.Vegas.Region newRegion = new ScriptPortal.Vegas.Region(evnt.Start, evnt.Length, "Audio Present");
                myVegas.Project.Regions.Add(newRegion);
            }
        }

        private void checkOverlappedRegions()
        {
            bool foundoverlap = true;

            while (foundoverlap)
            {
                for (int i = 0; i < myVegas.Project.Regions.Count; i++)
                {
                    foundoverlap = false;
                    ScriptPortal.Vegas.Region myRegion = myVegas.Project.Regions[i];

                    Timecode regStart = myRegion.Position;
                    Timecode regEnd = myRegion.Position + myRegion.Length;

                    foreach(ScriptPortal.Vegas.Region thisRegion in myVegas.Project.Regions)
                    {
                        if (myRegion.Index != thisRegion.Index)
                        {
                            Timecode thisStart = thisRegion.Position;
                            Timecode thisEnd = thisRegion.Position + thisRegion.Length;

                            if (regStart >= thisStart && regStart <= thisEnd)
                            {
                                foundoverlap = true;
                                if (thisEnd < regEnd)
                                {
                                    thisRegion.Length = regEnd - thisStart;
                                    myVegas.Project.Regions.Remove(myRegion);
                                    break;
                                }
                                else
                                {
                                    myVegas.Project.Regions.Remove(myRegion);
                                    break;
                                }
                            }
                        }
                    }

                    if (foundoverlap)
                    {
                        break;
                    }
                }
            }
        }

        private void reverseRegions()
        {
            ArrayList RegionStart = new ArrayList();
            ArrayList RegionLength = new ArrayList();

            foreach (ScriptPortal.Vegas.Region myRegion in myVegas.Project.Regions)
            {
                RegionStart.Add(myRegion.Position);
                RegionLength.Add(myRegion.Length);
            }

            for (int i = myVegas.Project.Regions.Count - 1; i >= 0; i--)
            {
                myVegas.Project.Regions.Remove(myVegas.Project.Regions[i]);
            }

            Timecode nextStart = new Timecode(0);
            for (int i = 0; i < RegionStart.Count; i++)
            {
                if (i == 0)
                {
                    if ((Timecode)RegionStart[i] > Timecode.FromFrames(0))
                    {
                        addRegion(Timecode.FromFrames(0), (Timecode)RegionStart[i]);
                    }
                }
                else
                {
                    addRegion(nextStart, (Timecode)RegionStart[i] - nextStart);
                }
                nextStart = (Timecode)RegionStart[i] + (Timecode)RegionLength[i];
            }
        }

        private void addRegion(Timecode regStart, Timecode regLen)
        {
            ScriptPortal.Vegas.Region newRegion = new ScriptPortal.Vegas.Region(regStart, regLen, "Audio Absent");
            myVegas.Project.Regions.Add(newRegion);
        }

        private void closeGaps()
        {
            for (int i = myVegas.Project.Regions.Count - 1; i >= 0; i--)
            {
                Timecode regStart = myVegas.Project.Regions[i].Position;
                Timecode regLen = myVegas.Project.Regions[i].Length;

                foreach (Track myTrack in myVegas.Project.Tracks)
                {
                    foreach (TrackEvent evnt in myTrack.Events)
                    {
                        if (evnt.Start > regStart)
                        {
                            evnt.Start = evnt.Start - regLen;
                        }
                    }
                }
                myVegas.Project.Regions.Remove(myVegas.Project.Regions[i]);
            }
        }


    }
}

public class EntryPoint
{
    public void FromVegas(Vegas vegas)
    {
        Test_Script.Class1 test = new Test_Script.Class1();
        test.Main(vegas);
    }
}

 

Jayboy75 wrote on 12/11/2022, 6:51 PM

I was getting some anomalous crossfades with the earlier versions of the script same as @EdiTools, but this latest iteration seems to have resolved them.

Well @jetdv, in short, this script is likely to become a game-changer (nay, a life-changer) for me. Paired with Vegasaur it will save me dozens, if not hundreds of hours in the coming year alone. I've been running this podcast for almost four years now, and my only regret is not looking into automation solutions sooner. My utmost thanks. If there's even the smallest thing I can do to repay you, please don't hesitate to let me know.

jetdv wrote on 12/11/2022, 8:51 PM

Glad you find it useful. My website is www.jetdv.com where all my tutorials and Excalibur is listed. There's also a "donate" button if you feel so inclined. Automation and multi-cam editing is why I created Excalibur. I truly believe that scripting is one of the best features of VEGAS.