Comments

jetdv wrote on 1/18/2022, 4:27 PM

Here's a really, really old one: SlideshowToMarkers2.js (I didn't write this one and it will take some updates to run in current versions of VEGAS. This one was for Vegas 4. I start by changing import SonicFoundry.Vegas; from "SonicFoundry" to "ScriptPortal". It would probably run after that.

// Assuming there is an audio track with appropriate number of numbered and
// unnumbered markers, and a bin in Media Pool with images, automate image
// sequence to timeline at markers. Apply default transition/dissolve in the
// process.
// Maybe pick images from directory in future versions.

import System.Windows.Forms;
import SonicFoundry.Vegas;
import Microsoft.Win32;

// This is for convenience in comparison and assignment.
var zeroMark = new Timecode(0);
// These are default values for parameters in a dialog.
// Half-time of dissolve. Half because we add it to both dissolving clips.
var overlap: Timecode;
// Region that is subject to script. By default it is entire project.
var begin: Timecode, end: Timecode;
// Default name for bin holding our slides.
var binName;
// 0 - entire project, 1 - from cursor to the end of project, 2 - loop region.
var regionType;

try {
  // Last snapshot file name is stored in Windows registry.
  var regKey = Registry.CurrentUser.CreateSubKey("Software\\Sonic Foundry\\Scripts\\SlideshowToMarkers");
  binName = regKey.GetValue("Bin name", "Slides");
  overlap = new Timecode(regKey.GetValue("Overlap", "00:00:01:29")); // Approximately 2 seconds.
  regionType = regKey.GetValue("Region", 1);

  var dialog = new SlideshowDialog(binName, overlap, regionType);
  var dialogResult = dialog.ShowDialog();

  // if the OK button was pressed...
  if (System.Windows.Forms.DialogResult.OK == dialogResult) {
    binName = dialog.binNameBox.Text;
    overlap = new Timecode(dialog.overlapBox.Text);
    regionType = dialog.regionBox.SelectedIndex;
    switch (regionType) {
      case 0: begin = zeroMark; end = Vegas.Project.Length; break;
      // If there's no selection then SelectionLength is 0 (zero).
      case 2: begin = Vegas.SelectionStart; end = begin + Vegas.SelectionLength; break;
      default: begin = Vegas.Cursor; end = Vegas.Project.Length;
    }
    // Write settings back to Registry.
    regKey.SetValue("Bin name", binName);
    regKey.SetValue("Overlap", overlap.ToString());
    regKey.SetValue("Region", regionType);

    // If event is shorter than this then its all just transition.
    // That will look bad aestethically.
    var threshold = overlap + overlap;

    // Although it is called audio track here, it does not matter, since markers
    // are global to progect and there is nothing specific to audio track that
    // we use below.
    var audioTrack = FindSelectedTrack();
    // Hardcoded name of the new track.
    var videoTrack = new VideoTrack(audioTrack.DisplayIndex, "Slideshow");
    Vegas.Project.Tracks.Add(videoTrack);

    var mrkEnum = new Enumerator(Vegas.Project.Markers);
    // Two variables to identify start and end of created event.
    var prevMark: Timecode = begin, currMark: Timecode = begin;

    // Find the bin containing slides.
    var bin = FindMediaBin(Vegas.Project.MediaPool.RootMediaBin, binName);
    if (bin == null) {
      MessageBox.Show("Could not find '" + binName + "' bin in Media Pool.");
    } else {
      // Position on first image in the bin.
      var imgEnum = new Enumerator(bin);

      // Smart code below is to advance currMark until the length of event will
      // be greater than threshold. Then subsequent slide is put on the timeline
      // thus creating an event.
      while (!mrkEnum.atEnd()) {
        currMark = Marker(mrkEnum.item()).Position;
        if ((currMark > begin) && ((currMark - prevMark) > threshold)) {
          PlaceImageOnTimeline(imgEnum, prevMark, currMark);
          prevMark = currMark;
        }
        if (currMark >= end) break; // To avoid extra looping after we reach end of processing region.
        mrkEnum.moveNext();
      }
      // The last marker may not mark the end of processing region.
      // This special case is handled by code below. Notice that we compare to
      // overlap here because for the last event dissolve is applied on one side
      // only. Would be good to handle the first event in similar way ...
      currMark = end;
      if ((currMark - prevMark) > overlap) {
        PlaceImageOnTimeline(imgEnum, prevMark, currMark);
      }
    }
  }
} catch (e) {
  MessageBox.Show(e);
}

// Retrieve the next available image and create event on timeline.
function PlaceImageOnTimeline(images: Enumerator, from: Timecode, to: Timecode): void {
  // Advance to next image.
  var imgStream: MediaStream = FindNextImage(images);
  if (imgStream == null)
    return;
  // Add handles for dissolve. Transition is centered on marker.
  // Keep timecodes withing the range of audio track.
  from -= overlap;
  if (from < begin) from = begin;
  to += overlap;
  if (to > end) to = end;
  // Create the new video event and add it to the track.
  var evnt = new VideoEvent(from, to - from);
  videoTrack.Events.Add(evnt);
  // Create a new take using the video stream.
  var takeName = null;
  evnt.Takes.Add(new Take(imgStream, true, takeName));
}

// Walk the bin tree recursively until the 'name' is found.
// If several bins on different levels have the same name, first one will be
// returned.
function FindMediaBin(parent: MediaBin, name: String): MediaBin {
  if (String.Compare(parent.Name, name) == 0) {
    return parent;
  }
  var binEnum = new Enumerator(parent);
  while (!binEnum.atEnd()) {
    var abin = binEnum.item();
    if ((abin instanceof MediaBin) && (abin.Name != parent.Name)) {
      // Recurse here.
      abin = FindMediaBin(abin, name);
      if (abin != null)
        return abin;
    }
    binEnum.moveNext();
  }
  return null;
}

// Get next available media as video stream. There is no check if this is
// slide/image. Any media containing video is acceptable.
function FindNextImage(mediaEnum: Enumerator): MediaStream {
  while (!mediaEnum.atEnd()) {
    var img = mediaEnum.item();
    mediaEnum.moveNext();
    if ((img instanceof Media) && Media(img).HasVideo()) {
      return img.Streams.GetItemByMediaType(MediaType.Video, 0);
    }
  }
  return null;
}

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;
}


// Form subclass that is the dialog box for this script
class SlideshowDialog extends Form {
  var binNameBox;
  var overlapBox;
  var regionBox;

  function SlideshowDialog(binName, overlap, region) {

    this.Text = "Create Slideshow";
    this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
    this.MaximizeBox = false;
    this.StartPosition = FormStartPosition.CenterScreen;
    this.Width = 300;

    var buttonWidth = 80;

    binNameBox = addTextControl("Bin Name", 10, 200, 10, binName);
    overlapBox = addTextControl("Overlap Time", 10, 140, binNameBox.Bottom + 16, overlap.ToString());

    var label = new Label();
    label.AutoSize = true;
    label.Text = "Region:";
    label.Left = 10;
    label.Top = overlapBox.Bottom + 20;
    Controls.Add(label);
    regionBox = new ComboBox();
    regionBox.DropDownWidth = 100;
    regionBox.Left = label.Right;
    regionBox.Top = overlapBox.Bottom + 16;
    regionBox.Items.Add("Entire Timeline");
    regionBox.Items.Add("From Cursor");
    regionBox.Items.Add("Loop Region");
    regionBox.SelectedIndex = region;
    Controls.Add(regionBox);

    var buttonTop = regionBox.Bottom + 16;

    var okButton = new Button();
    okButton.Text = "OK";
    okButton.Left = this.Width - (2*(buttonWidth+10));
    okButton.Top = buttonTop;
    okButton.Width = buttonWidth;
    okButton.Height = okButton.Font.Height + 12;
    okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
    AcceptButton = okButton;
    Controls.Add(okButton);

    var cancelButton = new Button();
    cancelButton.Text = "Cancel";
    cancelButton.Left = this.Width - (1*(buttonWidth+10));
    cancelButton.Top = buttonTop;
    cancelButton.Height = cancelButton.Font.Height + 12;
    cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
    CancelButton = cancelButton;
    Controls.Add(cancelButton);

    var titleHeight = this.Height - this.ClientSize.Height;
    this.Height = titleHeight + okButton.Bottom + 8;
  }

  function addTextControl(labelName, left, width, top, defaultValue) {
    var label = new Label();
    label.AutoSize = true;
    label.Text = labelName + ":";
    label.Left = left;
    label.Top = top + 4;
    Controls.Add(label);

    var textbox = new TextBox();
    textbox.Multiline = false;
    textbox.Left = label.Right;
    textbox.Top = top;
    textbox.Width = width - (label.Width);
    textbox.Text = defaultValue;
    Controls.Add(textbox);

    return textbox;
  }

}

 

Grazie wrote on 1/18/2022, 4:32 PM

@jetdv - Ah, yes. However I did use your Excalibur. It takes Stills already on a Track and places them at Marker/s. I was also looking for some form of fade for each Transition.

jetdv wrote on 1/18/2022, 4:40 PM

If they don't have overlaps, you can use the "Overlap Previous Event" tool to create the overlaps. Then the "Apply Transitions" tool can be used to add one or more transitions over the various events. Both of those are on the "Event" tab.