Keyframe offset strange results

johnmeyer wrote on 4/25/2006, 9:17 PM
I have spent way too much time on this. I've looked at other scripts, and none of the keyframe motion commands seems to make any sense. In the script below,
I have the offset command:

key2.MoveBy(offset);

The "offset" variable is a constant. I would expect this to either move each subsequent keyframe to the same location, or else move it by the same amount relative to the previous keyframe. Instead, it moves the keyframes one way, and then the other. I'm having the same problem with the ByScale command. I've read some of Ed's tutorials, looked at JohnyRoy's examples, and read the API doc a dozen times. Something sure seems screwy.

Any help would be appreciated.

/** 
* This script will assign 20 keyframes to the each selected event on the first timeline.
* It assigns these events
*
* Copyright 2006 - John H. Meyer
* Last revision, April 25, 2006
*
**/

import System;
import System.Collections;
import System.Text;
import System.IO;
import System.Drawing;
import System.Windows.Forms;
import Sony.Vegas;
var evnt : TrackEvent;
var zero : int = 0;
var max : int = 10;

try {

//Find the selected event
var track = FindSelectedTrack();
if (null == track) // Must select a track
throw "no selected track";
var eventEnum = new Enumerator(track.Events);
if (track.IsVideo()) { // Track must be a video track
while (!eventEnum.atEnd()) {
evnt = TrackEvent(eventEnum.item());
if (evnt.Selected) {
var vevnt = VideoEvent(evnt);
var EventLength = evnt.Length.ToMilliseconds();
var LogLength = System.Math.Exp((System.Math.Log(EventLength)/max));
var keycollection = vevnt.VideoMotion.Keyframes;

// Check if there is only one keyframe


var videoWidth : int=Vegas.Project.Video.Width;
var offset = new VideoMotionVertex(float(videoWidth/max), float(0));

for (var i=0; i <=max; i++) {
// var NewKeyTimecode = new Timecode(Timecode.FromMilliseconds(int(1 + EventLength - Math.pow(LogLength,i) - i/max)));
var NewKeyTimecode = new Timecode(Timecode.FromMilliseconds(EventLength - EventLength * i/max) );
var key2 = new VideoMotionKeyframe(NewKeyTimecode);
// add the new key frame
vevnt.VideoMotion.Keyframes.Add(key2);
key2.MoveBy(offset);

//MessageBox.Show(int(1 + EventLength - Math.pow(LogLength,i) - i/max));

//MessageBox.Show(int(Math.pow(LogLength,i) ));
}
} //End if keyframes
} //End if selected
eventEnum.moveNext();
} // End While eventEnum
} // End If track.IsVideo

else {
MessageBox.Show("You must select a video track");
}


} catch (e) {
MessageBox.Show(e);
}



function FindSelectedTrack() : Track {
var trackEnum = new Enumerator(Vegas.Project.Tracks);
while (!trackEnum.atEnd()) {
var track : Track = Track(trackEnum.item());
if (track.Selected) {
return track;
}
trackEnum.moveNext();
}
return null;

Comments

JohnnyRoy wrote on 4/27/2006, 5:52 AM
I spent some time with this last night John and I really can’t explain the results. I’ve only moved a single keyframe and the offset has always worked for me. It is very odd that while adding multiple, the delta distance gets less and less until it is finally reverse. Very strange indeed.

~jr
SonyPJM wrote on 4/27/2006, 8:07 AM
What happens for you when you run this script:


import System;
import Sony.Vegas;


var width = Vegas.Project.Video.Width;
var vtrack : VideoTrack = VideoTrack(Vegas.Project.Tracks[0]);
var vevent : VideoEvent = VideoEvent(vtrack.Events[0]);
var offset : VideoMotionVertex = new VideoMotionVertex((width/10), 0);
for (var i = 1; i < 10; i++)
{
var keyTime : Timecode = Timecode.FromFrames(i*(vevent.Length.FrameCount/10));
var kf : VideoMotionKeyframe = new VideoMotionKeyframe(keyTime);
vevent.VideoMotion.Keyframes.Add(kf);
kf.MoveBy(offset);
}


For me, it creates 9 new keyframes and moves the image more and more to the left. This is what I would expect since each new keyframe assumes the position of the previous one and then it is moved further by a constant amount. The image appears to move to the left because the verticies of a keyframe define the "view" in to the event... positive values will move the image to the left and negative values will move it to the right.

I have not been able to reproduce the back-and-forth results you describe.
SonyPJM wrote on 4/27/2006, 8:25 AM
Ok, now I've been able to reproduce the back-and-forth / non-constant movement. I changed my sample script to count down rather than count up:


import System;
import Sony.Vegas;


var width = Vegas.Project.Video.Width;
var vtrack : VideoTrack = VideoTrack(Vegas.Project.Tracks[0]);
var vevent : VideoEvent = VideoEvent(vtrack.Events[0]);
var offset : VideoMotionVertex = new VideoMotionVertex((width/10), 0);
for (var i = 10; i > 0; i--)
{
var keyTime : Timecode = Timecode.FromFrames(i*(vevent.Length.FrameCount/10));
var kf : VideoMotionKeyframe = new VideoMotionKeyframe(keyTime);
vevent.VideoMotion.Keyframes.Add(kf);
kf.MoveBy(offset);
}


The key is the position the keyframe has when it is added to the list... it assumes the position it would have had were it not there in the first place. Since your script and my revised sample script insert keyframes at times before the previous, their start positions are effected by the previously added keyframe and the first keyframe (at time 0). So when each keyframe is moved, it is moved by a constant amount but the start positions are variable.
johnmeyer wrote on 4/27/2006, 9:34 AM
Since your script and my revised sample script insert keyframes at times before the previous, their start positions are effected by the previously added keyframe and the first keyframe (at time 0). So when each keyframe is moved, it is moved by a constant amount but the start positions are variable.

Bingo! Makes perfect sense, now that I understand that "offset" is relative to the previous keyframe rather than an absolute setting. That would be a useful addition to any future revision of the API document.

Also, the undocumented Script view in Vegas that was revealed in the Vegas forum a few weeks back has saved TONS of time debugging. You need to work that into the help menu in future releases.

Thanks for the help. The script does exactly what I originally envisioned. Now all I need to do is come up with a UI for specifying the path and acceleration.