A very nice simple Script!

Thiago_Sase wrote on 8/21/2024, 5:07 PM

Hi Folks, this script may be useful to someone.

It does similar what "Multicamera Editing mode does by holding Ctrl+Click"; but now you just have to select any event, video or audio, grouped or not.

It does;
1º - It creates a Marker at cursor position;
2º - It makes a Split;
3º - It makes a crossfade of 1 second;
4º - Then, it deletes the marker.

It can be useful in a lot of scenarios.

 

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using ScriptPortal.Vegas;

namespace Test_Script
{
    public class Class1
    {
        public Vegas myVegas;
        private Marker cursorMarker;

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

            // Add a marker at the current cursor position and keep track of it
            AddMarkerAtCursor();

            // Split events at marker positions
            foreach (Marker myMarker in myVegas.Project.Markers)
            {
                foreach (Track myTrack in myVegas.Project.Tracks)
                {
                    foreach (TrackEvent evnt in myTrack.Events)
                    {
                        if (evnt.Selected)
                        {
                            if (evnt.Start < myMarker.Position && evnt.End > myMarker.Position)
                            {
                                Timecode splitPoint = myMarker.Position - evnt.Start;
                                evnt.Split(splitPoint);

                                // Extend the event before the split by 1 second
                                ExtendEventLength(evnt, 1, "Seconds");
                            }
                        }
                    }
                }
            }

            // Delete the marker after all operations
            RemoveMarker();
        }

        private void AddMarkerAtCursor()
        {
            try
            {
                Timecode cursorPosition = myVegas.Transport.CursorPosition;
                cursorMarker = new Marker(cursorPosition, "Cursor Marker");
                myVegas.Project.Markers.Add(cursorMarker);
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    "Failed to add marker: " + ex.Message,
                    "Error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void RemoveMarker()
        {
            try
            {
                if (cursorMarker != null)
                {
                    myVegas.Project.Markers.Remove(cursorMarker);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    "Failed to remove marker: " + ex.Message,
                    "Error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void ExtendEventLength(TrackEvent trackEvent, double extendValue, string timecodeType)
        {
            try
            {
                switch (timecodeType)
                {
                    case "Frames":
                        // Calculate the length in frames for 1 second
                        double framesPerSecond = trackEvent.Length.FrameRate;
                        long lengthInFrames = (long)(1 * framesPerSecond);
                        trackEvent.Length = Timecode.FromFrames(trackEvent.Length.FrameCount + lengthInFrames);
                        break;
                    case "Seconds":
                        // Extend by 1 second
                        trackEvent.Length = Timecode.FromSeconds(trackEvent.Length.ToMilliseconds() / 1000.0 + extendValue);
                        break;
                    default:
                        MessageBox.Show("Invalid timecode type selected.");
                        break;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    "Something went wrong: " + ex.Message,
                    "Error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }
    }

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

 

Comments

jetdv wrote on 8/21/2024, 8:54 PM

@Thiago_Sase, why does it need to add and remove the marker? If you're doing it at the cursor position, why not just use the cursor position as the location and then get rid of the "for each marker" loop - unless you're going to process a BUNCH of markers at once (which is what Excalibur does.)

This should do exactly the same thing without messing with markers:
 

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using ScriptPortal.Vegas;

namespace Test_Script
{
    public class Class1
    {
        public Vegas myVegas;
        private Marker cursorMarker;

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

            Timecode cursorPosition = myVegas.Transport.CursorPosition;

            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                foreach (TrackEvent evnt in myTrack.Events)
                {
                    if (evnt.Selected)
                    {
                        if (evnt.Start < cursorPosition && evnt.End >cursorPosition)
                        {
                            Timecode splitPoint = cursorPosition - evnt.Start;
                            evnt.Split(splitPoint);
                            // Extend the event before the split by 1 second
                            ExtendEventLength(evnt, 1, "Seconds");
                        }
                    }
                }
            }
        }

        private void ExtendEventLength(TrackEvent trackEvent, double extendValue, string timecodeType)
        {
            try
            {
                switch (timecodeType)
                {
                    case "Frames":
                        // Calculate the length in frames for 1 second
                        double framesPerSecond = trackEvent.Length.FrameRate;
                        long lengthInFrames = (long)(1 * framesPerSecond);
                        trackEvent.Length = Timecode.FromFrames(trackEvent.Length.FrameCount + lengthInFrames);
                        break;
                    case "Seconds":
                        // Extend by 1 second
                        trackEvent.Length = Timecode.FromSeconds(trackEvent.Length.ToMilliseconds() / 1000.0 + extendValue);
                        break;
                    default:
                        MessageBox.Show("Invalid timecode type selected.");
                        break;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    "Something went wrong: " + ex.Message,
                    "Error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }
    }

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

 

jetdv wrote on 8/21/2024, 8:58 PM

Additionally, you could also get rid of:

        private void ExtendEventLength(TrackEvent trackEvent, double extendValue, string timecodeType)
        {
            try
            {
                switch (timecodeType)
                {
                    case "Frames":
                        // Calculate the length in frames for 1 second
                        double framesPerSecond = trackEvent.Length.FrameRate;
                        long lengthInFrames = (long)(1 * framesPerSecond);
                        trackEvent.Length = Timecode.FromFrames(trackEvent.Length.FrameCount + lengthInFrames);
                        break;
                    case "Seconds":
                        // Extend by 1 second
                        trackEvent.Length = Timecode.FromSeconds(trackEvent.Length.ToMilliseconds() / 1000.0 + extendValue);
                        break;
                    default:
                        MessageBox.Show("Invalid timecode type selected.");
                        break;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(
                    "Something went wrong: " + ex.Message,
                    "Error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

and just change:

ExtendEventLength(evnt, 1, "Seconds");

to:

evnt.Length = evnt.Length + Timecode.FromSeconds(1);

 

Thiago_Sase wrote on 8/22/2024, 3:46 AM

@jetdv

why does it need to add and remove the marker?

I did that because I was getting a lot of errors of how to make the split happens at cursor position. After many tries I thought on that "Split at marker solution" since its action is too fast that even it can't be seen the creation of the marker, and it's removal.

But the solution you showed it's cleaner, reads better and is more efficient. Thank you for that.

Additionally, you could also get rid of:

Now looks better. A lot of lines changed just by one. Very clever, thank you for that too.

I also added a curveType for the audio event. I do not like the default one. Furthermore, I really wanted the first crossfade type, linear in and linear out, but I couldn't find a way for Vegas to choose that one, I mean, I wrote linear in and out, but Vegas did not pick up the first crossfade curveType option. Anyway, the slow curveType fits good.

using System;
using System.Windows.Forms;
using ScriptPortal.Vegas;

namespace Test_Script
{
    public class Class1
    {
        public Vegas myVegas;

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

            Timecode cursorPosition = myVegas.Transport.CursorPosition;

            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                foreach (TrackEvent evnt in myTrack.Events)
                {
                    if (evnt.Selected)
                    {
                        if (evnt.Start < cursorPosition && evnt.End > cursorPosition)
                        {
                            Timecode splitPoint = cursorPosition - evnt.Start;
                            TrackEvent newEvent = evnt.Split(splitPoint);

                            // Extend the event before the split by 1 second
                            ExtendEventLength(evnt, 1);

                            // Adjust fade curves for the crossfade
                            AdjustCrossfadeCurves(evnt, newEvent, CurveType.Slow);  // Change CurveType to your desired curve
                        }
                    }
                }
            }
        }

        private void ExtendEventLength(TrackEvent trackEvent, double extendValue)
        {
            trackEvent.Length = trackEvent.Length + Timecode.FromSeconds(extendValue);
        }

        private void AdjustCrossfadeCurves(TrackEvent eventBeforeSplit, TrackEvent eventAfterSplit, CurveType curveType)
        {

            AudioEvent aEventBefore = eventBeforeSplit as AudioEvent;
            AudioEvent aEventAfter = eventAfterSplit as AudioEvent;

            if (aEventBefore != null && aEventAfter != null)
            {
                // Adjust fade-out curve for the event before the split
                aEventBefore.FadeOut.Curve = curveType;

                // Adjust fade-in curve for the event after the split
                aEventAfter.FadeIn.Curve = curveType;
            }

        }
    }

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

 

 

Last changed by Thiago_Sase on 8/22/2024, 3:56 AM, changed a total of 5 times.

OS: Windows 10 22H2
CPU: Intel Core I7 12700
MEMORY: 32GB DDR4 3200MHz
GHAPHIC CARD: RTX 3060 8GB
HARD DRIVES: SSD for System and M.2 for Media Files

jetdv wrote on 8/22/2024, 8:10 AM

Here's the different options you can pick for curvetype. "Linear" is one of them.

Thiago_Sase wrote on 8/22/2024, 8:30 AM

@jetdv When I try to use the "None" always gives an error. And any of those options match this crossfade here, even if I do different combinations;

Maybe I'm doing something wrong. Maybe is not possible to choose that crossfade type.

Last changed by Thiago_Sase on 8/22/2024, 8:32 AM, changed a total of 1 times.

OS: Windows 10 22H2
CPU: Intel Core I7 12700
MEMORY: 32GB DDR4 3200MHz
GHAPHIC CARD: RTX 3060 8GB
HARD DRIVES: SSD for System and M.2 for Media Files

jetdv wrote on 8/22/2024, 8:43 AM

I would not try "none". That's probably there just as a fail-safe - just like I wouldn't try "invalid"...

Those images show a combination of Fade Out on the left event and "Fade In" on the right event. The one you have circled looks like Linear out and Linear in. So you would need to change both the "Out" and "In" in order to get all of those images. Look at this way, the "Rows" are the "fade out" combinations (I could be incorrect in the namings below without testing)

  • Row 1: Linear
  • Row 2: Fast
  • Row 3: Slow
  • Row 4: Sharp
  • Row 5: Smooth

Then the "Columns" are the "fade in" combinations the same as the rows above.

So by adjusting the Fade Out of the left event and the Fade In on the right event, you can achieve all 25 combinations (5 x 5 = 25).

Thiago_Sase wrote on 8/22/2024, 9:03 AM

@jetdv I did some changes, but still not getting that type of crossfade.

 

using System;
using System.Windows.Forms;
using ScriptPortal.Vegas;

namespace Test_Script
{
    public class Class1
    {
        public Vegas myVegas;

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

            Timecode cursorPosition = myVegas.Transport.CursorPosition;

            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                foreach (TrackEvent evnt in myTrack.Events)
                {
                    if (evnt.Selected)
                    {
                        if (evnt.Start < cursorPosition && evnt.End > cursorPosition)
                        {
                            Timecode splitPoint = cursorPosition - evnt.Start;
                            TrackEvent newEvent = evnt.Split(splitPoint);

                            ExtendEventLength(evnt, 1);

                            AdjustCrossfadeCurves(evnt, newEvent);
                        }
                    }
                }
            }
        }

        private void ExtendEventLength(TrackEvent trackEvent, double extendValue)
        {
            trackEvent.Length = trackEvent.Length + Timecode.FromSeconds(extendValue);
        }

        private void AdjustCrossfadeCurves(TrackEvent eventBeforeSplit, TrackEvent eventAfterSplit)
        {
            
            eventBeforeSplit.FadeOut.Curve = CurveType.Linear;
            eventAfterSplit.FadeIn.Curve = CurveType.Linear;
        }
    }

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

 

jetdv wrote on 8/22/2024, 1:21 PM

@Thiago_Sase, here's how this works. You don't need to worry about the "left" event, only the "right" one.

  • On the "FadeIn", set the "Curve" to be the transition type INTO the right event.
  • On the "FadeIn", set the "ReciprocalCurve" to be the transition type OUT of the left event.

So in the above, change

            eventBeforeSplit.FadeOut.Curve = CurveType.Linear;
            eventAfterSplit.FadeIn.Curve = CurveType.Linear;

to be:

            eventAfterSplit.FadeIn.Curve = CurveType.Linear; 
            eventAfterSplit.FadeIn.ReciprocalCurve = CurveType.Linear;

 

jetdv wrote on 8/22/2024, 1:28 PM

Create you a project, put TWO events on the timeline overlapping, and change the fade to what you want it to be. Then run this script and it will tell you the two settings to use. Once again, you're only worried about the RIGHT event.


 

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;

            TrackEvent evnt = myVegas.Project.Tracks[0].Events[1]; // The "RIGHT" event

            MessageBox.Show("Curve = " + evnt.FadeIn.Curve + "   ReciprocalCurve = " + evnt.FadeIn.ReciprocalCurve);
            
        }

    }
}

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

 

Thiago_Sase wrote on 8/22/2024, 2:17 PM

 

On the "FadeIn", set the "ReciprocalCurve" to be the transition type OUT of the left event.

@jetdv This is really a cool new learning for me, it's a very interesting solution. The 25 possible combinations of Curves now is possible. That subject of "Curve" and "ReciprocalCurve" would be a very nice tutorial in the future. Thank you again Sir for the solution and knowledge.

jetdv wrote on 8/22/2024, 2:20 PM

That subject of "Curve" and "ReciprocalCurve" would be a very nice tutorial in the future. Thank you again Sir for the solution and knowledge.

Already added to the list of tutorials to make! :-)

Thiago_Sase wrote on 8/28/2024, 7:02 PM

@jetdv Hello Sir, please, if possible, and of course when you have free time for this.
The actual script does the split correct. And the crossfade is done by extending the event to the right direction. Ok, it works. But it would be very nice the possibility of the crossfade be created in the center of the cursor position, a crossfade of 42 frames duration. I tried a lot of methods, but I have failed on all possible way.

jetdv wrote on 8/28/2024, 7:09 PM

You might see if this helps...

Thiago_Sase wrote on 8/28/2024, 9:18 PM

@jetdv Thank you, Sir, I watched the tutorial and it helped a lot. In the end, I got this;

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using ScriptPortal.Vegas;

namespace Test_Script
{
    public class Class1
    {
        public Vegas myVegas;

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

            // Get the cursor position (playhead position)
            Timecode cursorPosition = myVegas.Transport.CursorPosition;

            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                foreach (TrackEvent evnt in myTrack.Events)
                {
                    if (evnt.Selected)
                    {
                        // Split at the cursor position if it is within the event's duration
                        if (cursorPosition > evnt.Start && cursorPosition < evnt.End)
                        {
                            Timecode splitPoint = cursorPosition - evnt.Start;
                            TrackEvent newEvent = evnt.Split(splitPoint);
                        }

                        // Check if the offset is greater than the extendLength
                        Timecode extendLength = Timecode.FromFrames(10);
                        if (evnt.ActiveTake.Offset > extendLength)
                        {
                            evnt.ActiveTake.Offset = evnt.ActiveTake.Offset - extendLength;
                            evnt.Start = evnt.Start - extendLength;
                            evnt.Length = evnt.Length + extendLength;
                        }

                        // Check if extending the length won't exceed the media's length
                        if (evnt.ActiveTake.Offset + evnt.Length + extendLength < evnt.ActiveTake.Media.Length)
                        {
                            evnt.Length = evnt.Length + extendLength;
                        }
                    }
                }
            }

            // Show a message box to confirm the script ran
            MessageBox.Show("Script executed successfully.");
        }
    }
}

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

The first Split is perfect, it is in the center of the cursor position and does the crossfade in the center as well.

But if I do another Split on the same event, the previous split will extend. I'm trying to find a way, if I do multiple Splits on the same event, the previous one will not have their length altered.

Last changed by Thiago_Sase on 8/28/2024, 9:22 PM, changed a total of 1 times.

OS: Windows 10 22H2
CPU: Intel Core I7 12700
MEMORY: 32GB DDR4 3200MHz
GHAPHIC CARD: RTX 3060 8GB
HARD DRIVES: SSD for System and M.2 for Media Files

jetdv wrote on 8/29/2024, 9:54 AM

Show in a video what is happening.

Thiago_Sase wrote on 8/29/2024, 10:11 AM

@jetdv Here's the Video Sir;

jetdv wrote on 8/29/2024, 10:35 AM

It's being extended because it's "selected". Change this section:

                        if (evnt.ActiveTake.Offset > extendLength) 
                        { 
                            evnt.ActiveTake.Offset = evnt.ActiveTake.Offset - extendLength; 
                            evnt.Start = evnt.Start - extendLength; 
                            evnt.Length = evnt.Length + extendLength; 
                        }

You want it to work on newEvent instead

                       if (newEvent.ActiveTake.Offset > extendLength)  
                       { 
                            newEvent.ActiveTake.Offset = newEvent.ActiveTake.Offset - extendLength; 
                            newEvent.Start = newEvent.Start - extendLength; 
                            newEvent.Length = newEvent.Length + extendLength; 
                        }

Then I would "break" out of the loop after processing this split

                        if (evnt.ActiveTake.Offset + evnt.Length + extendLength < evnt.ActiveTake.Media.Length) 
                        { 
                            evnt.Length = evnt.Length + extendLength; 
                        } 
                        break;

 

Thiago_Sase wrote on 8/29/2024, 10:58 AM

@jetdv It worked Sir! Thank you very much. Now, this script acts like "Multicamera Editing mode by holding Ctrl+Click".

Thiago_Sase wrote on 8/29/2024, 11:18 AM

The complete code;

 

using System;
using System.Windows.Forms;
using ScriptPortal.Vegas;

namespace Test_Script
{
    public class Class1
    {
        public Vegas myVegas;

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

            // Define the duration to extend in seconds (1 second)
            double extendSeconds = 1.0; 
            Timecode extendLength = Timecode.FromSeconds(extendSeconds);

            Timecode cursorPosition = myVegas.Transport.CursorPosition;

            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                foreach (TrackEvent evnt in myTrack.Events)
                {
                    if (evnt.Selected)
                    {
                        TrackEvent newEvent = null;

                        // Split at the cursor position if it is within the event's duration
                        if (cursorPosition > evnt.Start && cursorPosition < evnt.End)
                        {
                            Timecode splitPoint = cursorPosition - evnt.Start;
                            newEvent = evnt.Split(splitPoint);
                        }

                        // Ensure newEvent is not null before using it
                        if (newEvent != null)
                        {
                            // Check if the offset is greater than the extendLength
                            if (newEvent.ActiveTake.Offset > extendLength)
                            {
                                newEvent.ActiveTake.Offset -= extendLength;
                                newEvent.Start -= extendLength;
                                newEvent.Length += extendLength;
                            }
                        }

                        // Check if extending the length won't exceed the media's length
                        if (evnt.ActiveTake.Offset + evnt.Length + extendLength < evnt.ActiveTake.Media.Length)
                        {
                            evnt.Length += extendLength;
                        }

                        break; // Exit loop after processing the selected event
                    }
                }
            }
        }

        private void ExtendEventLength(TrackEvent trackEvent, double extendValue)
        {
            trackEvent.Length += Timecode.FromSeconds(extendValue);
        }
    }

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