help me complete a very useful script on frames and their length

MALIK wrote on 1/11/2025, 11:20 AM

I have two scripts, the first script automatically assigns all frames to 100 frames per second and slows them down by 4 times the main thing is that it automatically determines these frames on the timeline, and they do not need to be selected minus script - I can’t make them stretch along the entire length - I have to do it manually

//****************************************************************************
//*      Program: Convert59to29Media.cs
//*       Author: John Rofrano
//*  Description: This script changes the playback rate of 59.94p media to 27.97
//*      Created: July 8, 2017
//*
//*    Copyright: (c) 2017, John J. Rofrano, All Rights Reserved
//****************************************************************************
using System;
using System.Collections;
using System.Windows.Forms;
// Uncomment for Sony Vegas Pro
//using Sony.Vegas;
// Comment out for MAGIX Vegas Pro
using ScriptPortal.Vegas;


class EntryPoint
{
    public void FromVegas(Vegas vegas)
    {
        int counter = 0;
        try
        {
            foreach (Track track in vegas.Project.Tracks)
            {
                if (!track.IsVideo()) continue;

                foreach (VideoEvent videoEvent in track.Events)
                {
                    VideoStream videoStream = videoEvent.ActiveTake.MediaStream as VideoStream;
                    decimal frameRate = Math.Round((decimal)videoStream.FrameRate, 2);
            
                    // only affect 59.94fps media
                    if (frameRate == 100.00m)
                    {
                        //videoEvent.AdjustPlaybackRate(0.25, true);
            videoEvent.PlaybackRate = 0.25;
                        videoEvent.ResampleMode = VideoResampleMode.Disable;
                        counter++;
                    }
                }
            }

            // let the user know we are done
            MessageBox.Show(String.Format("{0} events changed", counter), "Complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message, "Unexpected Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
        }
    }
}

the second script - it can automatically stretch frames to a long length, but my frames need to be spread manually, and in the first script they are automatically executed and I want how to combine two scripts into one so that it works like this when the script is launched, all frames at a speed of 100 frames per second are automatically enlarged on the timeline and automatically stretched along their length (since they have slowed down 4 times)

using System;
using System.Collections.Generic;

using ScriptPortal.Vegas;  // "ScriptPortal.Vegas" for Magix Vegas Pro 14 or above, "Sony.Vegas" for Sony Vegas Pro 13 or below

namespace Test_Script
{
    public class Class
    {
        public Vegas myVegas;
        public void Main(Vegas vegas)
        {
            myVegas = vegas;

            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                if (myTrack.IsVideo())
                {
                    List<VideoEvent> eventList = new List<VideoEvent>();
                    foreach (TrackEvent evnt in myTrack.Events)
                    {
                        if (evnt.Selected)
                        {
                            eventList.Add((VideoEvent)evnt);
                        }
                    }

                    if (eventList.Count == 0)
                    {
                        continue;
                    }

                    Timecode offset = Timecode.FromNanos(0);

                    for (int i = 0; i < eventList.Count - 1; i++)
                    {
                        if (eventList[i+1].IsGrouped)
                        {
                            Timecode tc = eventList[i+1].Start - eventList[i].End;
                            foreach (TrackEvent ev in eventList[i+1].Group)
                            {
                                ev.Start -= tc;
                            }
                        }
                        else
                        {
                            eventList[i+1].Start = eventList[i].End;
                        }
                    }

                    foreach (VideoEvent vEvent in eventList)
                    {
                        double rateSave = vEvent.PlaybackRate;
                        double rate = myVegas.Project.Video.FrameRate / ((VideoStream)vEvent.ActiveTake.MediaStream).FrameRate;
                        if (rate < 0.6) {
                            rate *= 1;
                        }
                        Timecode lengthSave = vEvent.Length;
                        vEvent.Length = Timecode.FromFrames((long)(Math.Floor(lengthSave.Nanos * myVegas.Project.Video.FrameRate * rateSave / rate / 10000000)));
                        vEvent.PlaybackRate = rate;

                        vEvent.Start += offset;

                        if (vEvent.IsGrouped)
                        {
                            foreach (TrackEvent groupEvent in vEvent.Group)
                            {
                                if (groupEvent == vEvent)
                                {
                                    continue;
                                }
                                groupEvent.Start += offset;
                                rateSave = groupEvent.PlaybackRate;
                                groupEvent.PlaybackRate = vEvent.PlaybackRate;
                                groupEvent.Length = Timecode.FromNanos((long)(groupEvent.Length.Nanos * rateSave / groupEvent.PlaybackRate));
                            }
                        }
                        offset += vEvent.Length - lengthSave;
                    }
                }
            }
        }
    }
}

public class EntryPoint
{
    public void FromVegas(Vegas vegas)
    //public void FromVegas(Vegas vegas, String scriptFile, XmlDocument scriptSettings, ScriptArgs args)
    {
        Test_Script.Class test = new Test_Script.Class();
        test.Main(vegas);
    }
}

Comments

jetdv wrote on 1/12/2025, 7:16 AM

In the first script, you already have:

videoEvent.PlaybackRate = 0.25;

So you KNOW the new length will be 4x the current length since you're setting the playback rate to .25. So you could just do:

videoEvent.PlaybackRate = 0.25;
videoEvent.Length = Timecode.FromMilliseconds(videoEvent.Length.ToMilliseconds() * 4);

Will that not do what you're wanting?

MALIK wrote on 1/12/2025, 9:50 AM

In the first script, you already have:

videoEvent.PlaybackRate = 0.25;

So you KNOW the new length will be 4x the current length since you're setting the playback rate to .25. So you could just do:

videoEvent.PlaybackRate = 0.25;
videoEvent.Length = Timecode.FromMilliseconds(videoEvent.Length.ToMilliseconds() * 4);

Will that not do what you're wanting?

yes, now it automatically detects and stretches all the frames, but the problem now is that the frames overlap each other, but should go sequentially (as in the second script, which I indicated as an example)

How can I make them go sequentially and not overlap each other?

i need like this result - "It nicely cuts off the end of each changed event and aligns it to a frame in the Timeline. During subsequent cutting, there are no gaps and everything fits perfectly without gaps."

 

 

it is in this script that he does it (in second script)

 

using System;
using System.Collections.Generic;

using ScriptPortal.Vegas;  // "ScriptPortal.Vegas" for Magix Vegas Pro 14 or above, "Sony.Vegas" for Sony Vegas Pro 13 or below

namespace Test_Script
{
    public class Class
    {
        public Vegas myVegas;
        public void Main(Vegas vegas)
        {
            myVegas = vegas;

            foreach (Track myTrack in myVegas.Project.Tracks)
            {
                if (myTrack.IsVideo())
                {
                    List<VideoEvent> eventList = new List<VideoEvent>();
                    foreach (TrackEvent evnt in myTrack.Events)
                    {
                        if (evnt.Selected)
                        {
                            eventList.Add((VideoEvent)evnt);
                        }
                    }

                    if (eventList.Count == 0)
                    {
                        continue;
                    }

                    Timecode offset = Timecode.FromNanos(0);

                    for (int i = 0; i < eventList.Count - 1; i++)
                    {
                        if (eventList[i+1].IsGrouped)
                        {
                            Timecode tc = eventList[i+1].Start - eventList[i].End;
                            foreach (TrackEvent ev in eventList[i+1].Group)
                            {
                                ev.Start -= tc;
                            }
                        }
                        else
                        {
                            eventList[i+1].Start = eventList[i].End;
                        }
                    }

                    foreach (VideoEvent vEvent in eventList)
                    {
                        double rateSave = vEvent.PlaybackRate;
                        double rate = myVegas.Project.Video.FrameRate / ((VideoStream)vEvent.ActiveTake.MediaStream).FrameRate;
                        if (rate < 0.6) {
                            rate *= 1;
                        }
                        Timecode lengthSave = vEvent.Length;
                        vEvent.Length = Timecode.FromFrames((long)(Math.Floor(lengthSave.Nanos * myVegas.Project.Video.FrameRate * rateSave / rate / 10000000)));
                        vEvent.PlaybackRate = rate;

                        vEvent.Start += offset;

                        if (vEvent.IsGrouped)
                        {
                            foreach (TrackEvent groupEvent in vEvent.Group)
                            {
                                if (groupEvent == vEvent)
                                {
                                    continue;
                                }
                                groupEvent.Start += offset;
                                rateSave = groupEvent.PlaybackRate;
                                groupEvent.PlaybackRate = vEvent.PlaybackRate;
                                groupEvent.Length = Timecode.FromNanos((long)(groupEvent.Length.Nanos * rateSave / groupEvent.PlaybackRate));
                            }
                        }
                        offset += vEvent.Length - lengthSave;
                    }
                }
            }
        }
    }
}

public class EntryPoint
{
    public void FromVegas(Vegas vegas)
    //public void FromVegas(Vegas vegas, String scriptFile, XmlDocument scriptSettings, ScriptArgs args)
    {
        Test_Script.Class test = new Test_Script.Class();
        test.Main(vegas);
    }
}


 

jetdv wrote on 1/12/2025, 1:37 PM

So... You're wanting everything after that event to move to the right the same distance? That's doable too.

jetdv wrote on 1/13/2025, 9:06 AM

@MALIK, try something like this:

            Timecode oldLength = videoEvent.Length;
            videoEvent.PlaybackRate = 0.25;
            videoEvent.Length = Timecode.FromMilliseconds(videoEvent.Length.ToMilliseconds() * 4);
            Timecode moveDist = videoEvent.Length - oldLength;

            for (int i = track.Events.Count - 1; i > videoEvent.Index; i--)
            {
                VideoEvent moveEvent = (VideoEvent)track.Events[i];
                moveEvent.Start = moveEvent.Start + moveDist;
            }

This will get difference between the old length and the new length and then move everything to the right of that event that distance.

MALIK wrote on 1/14/2025, 11:54 AM

@MALIK, try something like this:

            Timecode oldLength = videoEvent.Length;
            videoEvent.PlaybackRate = 0.25;
            videoEvent.Length = Timecode.FromMilliseconds(videoEvent.Length.ToMilliseconds() * 4);
            Timecode moveDist = videoEvent.Length - oldLength;

            for (int i = track.Events.Count - 1; i > videoEvent.Index; i--)
            {
                VideoEvent moveEvent = (VideoEvent)track.Events[i];
                moveEvent.Start = moveEvent.Start + moveDist;
            }

This will get difference between the old length and the new length and then move everything to the right of that event that distance.

where i must it add? can you please write full script? (((

jetdv wrote on 1/14/2025, 12:12 PM

In the very first script you posted you have this:

                    // only affect 59.94fps media
                    if (frameRate == 100.00m)
                    {
                        //videoEvent.AdjustPlaybackRate(0.25, true);
            videoEvent.PlaybackRate = 0.25;
                        videoEvent.ResampleMode = VideoResampleMode.Disable;
                        counter++;

This line will be the same in both of them:

videoEvent.PlaybackRate = 0.25;

So put this before it:

Timecode oldLength = videoEvent.Length;

and this after it:

videoEvent.Length = Timecode.FromMilliseconds(videoEvent.Length.ToMilliseconds() * 4); 
Timecode moveDist = videoEvent.Length - oldLength; 
for (int i = track.Events.Count - 1; i > videoEvent.Index; i--) 
{ 
    VideoEvent moveEvent = (VideoEvent)track.Events[i]; 
    moveEvent.Start = moveEvent.Start + moveDist; 
}

 

jetdv wrote on 1/14/2025, 12:16 PM

So this:

                    if (frameRate == 100.00m)
                    {
                        //videoEvent.AdjustPlaybackRate(0.25, true);
                        videoEvent.PlaybackRate = 0.25;
                        videoEvent.ResampleMode = VideoResampleMode.Disable;
                        counter++;
                    }

Becomes:

                    if (frameRate == 100.00m)
                    {
                        //videoEvent.AdjustPlaybackRate(0.25, true);
                        Timecode oldLength = videoEvent.Length;
                        videoEvent.PlaybackRate = 0.25;
                        videoEvent.Length = Timecode.FromMilliseconds(videoEvent.Length.ToMilliseconds() * 4);
                        Timecode moveDist = videoEvent.Length - oldLength; 
                        for (int i = track.Events.Count - 1; i > videoEvent.Index; i--) 
                        { 
                            VideoEvent moveEvent = (VideoEvent)track.Events[i]; 
                            moveEvent.Start = moveEvent.Start + moveDist; 
                        }
                        videoEvent.ResampleMode = VideoResampleMode.Disable;
                        counter++;
                    }

 

MALIK wrote on 1/14/2025, 12:19 PM

So this:

                    if (frameRate == 100.00m)
                    {
                        //videoEvent.AdjustPlaybackRate(0.25, true);
                        videoEvent.PlaybackRate = 0.25;
                        videoEvent.ResampleMode = VideoResampleMode.Disable;
                        counter++;
                    }

Becomes:

                    if (frameRate == 100.00m)
                    {
                        //videoEvent.AdjustPlaybackRate(0.25, true);
                        Timecode oldLength = videoEvent.Length;
                        videoEvent.PlaybackRate = 0.25;
                        videoEvent.Length = Timecode.FromMilliseconds(videoEvent.Length.ToMilliseconds() * 4);
                        Timecode moveDist = videoEvent.Length - oldLength; 
                        for (int i = track.Events.Count - 1; i > videoEvent.Index; i--) 
                        { 
                            VideoEvent moveEvent = (VideoEvent)track.Events[i]; 
                            moveEvent.Start = moveEvent.Start + moveDist; 
                        }
                        videoEvent.ResampleMode = VideoResampleMode.Disable;
                        counter++;
                    }

 

yeah, thanks - its work, but audio not fixed by the video (((

Is there a way to do something so that the audio is under your video?

jetdv wrote on 1/14/2025, 1:49 PM

That would be correct. You're not selecting the audio in the script so it is not touched. It also won't be slowed down either.

jetdv wrote on 1/14/2025, 1:58 PM

You could try this instead - which takes some elements from the second script you listed:

            if (frameRate == 100.00m)
            {
                //videoEvent.AdjustPlaybackRate(0.25, true);
                Timecode oldLength = videoEvent.Length;
                videoEvent.PlaybackRate = 0.25;
                videoEvent.Length = Timecode.FromMilliseconds(videoEvent.Length.ToMilliseconds() * 4);
                Timecode moveDist = videoEvent.Length - oldLength;
                for (int i = track.Events.Count - 1; i > videoEvent.Index; i--)
                {
                    VideoEvent moveEvent = (VideoEvent)track.Events[i];
                    moveEvent.Start = moveEvent.Start + moveDist;
                    // As you move events on the timeline, move the grouped events too...
                    foreach (TrackEvent groupEvent in moveEvent.Group)
                    {
                        if (groupEvent == moveEvent)
                        {
                            continue;
                        }
                        groupEvent.Start = moveEvent.Start;
                    }
                }
                // Adjust the playback rate and length of the events grouped with the event being adjusted
                foreach (TrackEvent groupEvent in videoEvent.Group)
                {
                    if (groupEvent == videoEvent)
                    {
                        continue;
                    }
                    groupEvent.PlaybackRate = videoEvent.PlaybackRate;
                    groupEvent.Length = videoEvent.Length;
                }
                videoEvent.ResampleMode = VideoResampleMode.Disable;
                counter++;
            }

 

jetdv wrote on 1/14/2025, 2:00 PM

This will work fine if the audio is properly grouped with the video - as it is by default - but if you've created other groups - either on purpose or inadvertently - it could possibly cause issues.

MALIK wrote on 1/14/2025, 3:28 PM

This will work fine if the audio is properly grouped with the video - as it is by default - but if you've created other groups - either on purpose or inadvertently - it could possibly cause issues.

yeah, thanks so much
its work perfect