Marker to Subclip script roundoff problems

johnmeyer wrote on 1/30/2007, 11:13 AM
[Edit] I have posted later in this thread an update to this script that uses the embedded marker labels to name the subclips. While this doesn't let you sort the clips in order, it is very useful for my Workflow for Long Projects

End Edit.

I have updated John Rofrano's MediaRegions To Subclips.cs script to do exactly the same thing as his original script, but it uses embedded markers instead of regions (i.e., it creates subclips based on markers). I also converted it to Jscript (because there were several commands I couldn't figure out how to do in C#).

The problem I have, which is probably in John's original script as well, is that there is some strange rounding at frame boundaries. When I look at the Project Media view after creating subclips, about 10% of these subclips have a Timecode In, Timecode Out, and Length that do not match. For instance, here's one:

Timecode In: 00:00:12:21
Timecode Out: 00:00:25:23
Length: 00:00:13:01

As you can quickly compute, either the Length should be 13:02, not 13:01, or one of the Timecodes should be different. The 13:01 length actually appears to be correct, so I think the problem is Timecode Out. Since the Subclip command lets you set the Timecode in and the Length, but not Timecode Out, it appears that Timecode Out is somehow getting set incorrectly.

If I put the subclips on the timeline one at a time, they are all the correct length and are complete (i.e., no gaps or missing frames). However, if I drag them all to the timeline at once, I get one frame gaps between every 10-20 clips. These gaps occur immediately after each clip that has the problem I demonstrated above. Fortunately, if I move the frame to right of the gap in order to eliminate the gap, and ripple the other events, everything is just fine. Thus, this is not a huge deal, because I have a script that can eliminate all gaps with one click, but I don't like the idea of having a script that introduces errors like this.

I have copied the script below. I can't see any obvious problem here. When I run this script, I run it on a project that uses the standard NTSC DV project settings, but perhaps there is some project variable I must declare or set in order to ensure the correct timing.

/*

Script: MediaMarkers To Subclips.js
Based on scripts by Sony Media Software & John Rofrano

This script creates Subclips from markers embedded in the
selected events' media and then places them in the root mediabin.

This script is only supported by Vegas version 6.0c and above.

Converted from C# to Jscript, and modified to work with
markers instead of regions by John H. Meyer on January 29, 2007.

*/

import System;
import System.Text;
import System.Collections;
import System.Windows.Forms;
import Sony.Vegas;

try {
var processedClipCount : int = 0;
var trackEnum = new Enumerator(Vegas.Project.Tracks);

while (!trackEnum.atEnd()) { // Go through all tracks

var track : Track = Track(trackEnum.item());
var eventEnum = new Enumerator(track.Events);
if (!track.IsVideo()) { // Only process video tracks
trackEnum.moveNext();
continue;
}
while (!eventEnum.atEnd() ) { // Go through each event on this track
var evnt : TrackEvent = TrackEvent(eventEnum.item());

if (!evnt.Selected) { // Only process selected events
eventEnum.moveNext();
continue;
}

var activeTake : Take = evnt.ActiveTake;

if (null == activeTake) { // Only process events with active takes.
eventEnum.moveNext();
continue;
}

var media : Media = activeTake.Media;
if (null == media) {
eventEnum.moveNext();
continue;
}

// Initialize variables
var eventStart : Timecode = evnt.Start;
var eventEnd : Timecode = eventStart + evnt.Length;
var takeOffset : Timecode = activeTake.Offset;
var position : Timecode;
var lastposition : Timecode = eventStart;
var labelprefix : String;

// Interate over through the embedded markers and make subclips
var markerEnum = new Enumerator(media.Markers); // Start going through all the markers
var PrevMarker = markerEnum.item(); // Remember first marker

while (!markerEnum.atEnd()) { // Keep going until last marker
var mm = markerEnum.item();
var clipName : String = System.IO.Path.GetFileName(media.FilePath);

if (mm.Position != ( lastposition - eventStart ) ) { // Don't process if marker is at event start
position = mm.Position + eventStart - takeOffset;
if ( (position < eventStart) || (position > eventEnd) ) {
markerEnum.moveNext();
continue;
}
// Append counter to media name and pad with leading zeros so media can be sorted in MediaBin.
// If you want four digit leading numbers, change "3" to "4" in the next line
labelprefix = RepeatedConcat("0",3-processedClipCount.ToString().length) /
+ processedClipCount.ToString() + " - " + clipName;

// Create the Subclip
var clip = new Subclip(media.FilePath, lastposition, mm.Position-lastposition, false, labelprefix);
Vegas.Project.MediaPool.RootMediaBin.Add(clip);
processedClipCount++;
} // End if mm.Position

lastposition = mm.Position; // Remember this marker position to create next subclip
markerEnum.moveNext(); // Get next marker

} // End While Marker

// Create final subclip if there was no marker at exact end of media
if (lastposition != eventEnd) {
labelprefix = RepeatedConcat("0",3-processedClipCount.ToString().length) /
+ processedClipCount.ToString() + " - " + clipName;
clip = new Subclip(media.FilePath, lastposition, evnt.Length-lastposition, false, labelprefix);
Vegas.Project.MediaPool.RootMediaBin.Add(clip);
processedClipCount++;
}

eventEnum.moveNext();
} // End While Eventenum

trackEnum.moveNext();
} // End While TrackEnum

MessageBox.Show(processedClipCount.toString() + " markers/subclips processed.");

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

function RepeatedConcat(concatStr,intCount) {
var arrTmp = new Array(intCount+1);
return arrTmp.join(concatStr);
}


/* END OF SCRIPT */

Comments

jetdv wrote on 1/30/2007, 1:07 PM
You sure it's not the result of a "dropped frame" in a SMTPE drop-frame timeline?
johnmeyer wrote on 1/30/2007, 1:44 PM
You sure it's not the result of a "dropped frame" in a SMTPE drop-frame timeline?

Not sure what that means in this context. I think everything is set for 29.97. Are you suggesting that there is a preference I need to change that toggles between drop frame and non-drop?
jetdv wrote on 1/30/2007, 2:22 PM
If the ruler is set to drop frame, it can "appear" that the count is off when, instead, it's going across a dropped frame. So the length is accurate, the beginning is accurate, the end is accurate, but because of the dropped frame it does not appear to be accurate.

Right-click the timecode on the main timeline and choose something other than the SMPTE drop-frame. Does that change things?
johnmeyer wrote on 1/30/2007, 2:34 PM
Ed,

I right clicked, and it isn't set for SMPT anything, but instead is set to Time&Frames. Just for grins I changed it to Seconds ran the script, dropped the subclips on the timeline, but there wasn't any difference. I've run into this before with Vegas -- something about the internal precision. Normally it only shows up when you try to compare two things within a script that should be equal, but they are instead different by a few microseconds. However, I've never seen it show up on the timeline like this.
johnmeyer wrote on 2/16/2007, 6:53 PM
Here is a revision of the script that labels the subclips using the embedded marker labels. This is useful for consolidating media using nested VEG files (see this post: Worflow for Large Projects

/*

Script: MediaMarkers To Subclips.js
Based on scripts by Sony Media Software & John Rofrano

This script creates Subclips from markers embedded in the
selected events' media and then places them in the root mediabin.

This script is only supported by Vegas version 6.0c and above.

Converted from C# to Jscript, and modified to work with
markers instead of regions by John H. Meyer on January 29, 2007.
Updated on February 15, 2007 to use marker names for the subclip names.

*/

import System;
import System.Text;
import System.Collections;
import System.Windows.Forms;
import Sony.Vegas;

try {
var processedClipCount : int = 0;
var trackEnum = new Enumerator(Vegas.Project.Tracks);

while (!trackEnum.atEnd()) { // Go through all tracks

var track : Track = Track(trackEnum.item());
var eventEnum = new Enumerator(track.Events);
if (!track.IsVideo()) { // Only process video tracks
trackEnum.moveNext();
continue;
}
while (!eventEnum.atEnd() ) { // Go through each event on this track
var evnt : TrackEvent = TrackEvent(eventEnum.item());

if (!evnt.Selected) { // Only process selected events
eventEnum.moveNext();
continue;
}

var activeTake : Take = evnt.ActiveTake;

if (null == activeTake) { // Only process events with active takes.
eventEnum.moveNext();
continue;
}

var media : Media = activeTake.Media;
if (null == media) {
eventEnum.moveNext();
continue;
}

// Initialize variables
var eventStart : Timecode = evnt.Start;
var eventEnd : Timecode = eventStart + evnt.Length;
var takeOffset : Timecode = activeTake.Offset;
var position : Timecode;
var lastposition : Timecode = eventStart;
var labelprefix : String = "First Event";

// Interate over through the embedded markers and make subclips
var markerEnum = new Enumerator(media.Markers); // Start going through all the markers
var PrevMarker = markerEnum.item(); // Remember first marker

while (!markerEnum.atEnd()) { // Keep going until last marker
var mm = markerEnum.item();

var clipName : String = System.IO.Path.GetFileName(media.FilePath);
if (mm.Position != ( lastposition - eventStart ) ) { // Don't process if marker is at event start

position = mm.Position + eventStart - takeOffset;
if ( (position < eventStart) || (position > eventEnd) ) {
markerEnum.moveNext();
continue;
}

// Create the Subclip

var clip = new Subclip(media.FilePath, lastposition, mm.Position-lastposition, false, labelprefix);
Vegas.Project.MediaPool.RootMediaBin.Add(clip);
processedClipCount++;
} // End if mm.Position
else {
labelprefix = mm.Label; // If marker at beginning, use this name for first region
markerEnum.moveNext();
continue;
}

lastposition = mm.Position; // Remember this marker position to create next subclip
labelprefix = mm.Label;
markerEnum.moveNext(); // Get next marker

} // End While Marker

// Create final subclip if there was no marker at exact end of media
if (lastposition != eventEnd) {
clip = new Subclip(media.FilePath, lastposition, evnt.Length-lastposition, false, labelprefix);
Vegas.Project.MediaPool.RootMediaBin.Add(clip);
processedClipCount++;
}

eventEnum.moveNext();
} // End While Eventenum

trackEnum.moveNext();
} // End While TrackEnum

MessageBox.Show(processedClipCount.toString() + " markers/subclips processed.");

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

function RepeatedConcat(concatStr,intCount) {
var arrTmp = new Array(intCount+1);
return arrTmp.join(concatStr);
}


/* END OF SCRIPT */