In my never-ending quest to find a way to smart trim my GH4 footage, I am trying to create a script that generates a text list showing media, start timecode and length. The list can then be processed with ffmpeg via a Windows batch file. The script is based on JohnnyRoy's old script, WombleExport.cs, but I have modified (= horribly butchered) it a lot.
The clips trimmed by ffmpeg decode in Vegas Pro a bit strangely at the ends. When the trimmed clips are put back on the timeline they usually have about 3 duplicate frames at the finish. At the start they are normally frame-accurate, but if the start is not being trimmed at all then there are 2 duplicate frames. If the start is trimmed by just 1 frame then there is 1 duplicate frame (I think).
To deal with this I want to add 2 frames to the start and 3 frames to the finish of all clips in this script, then subtract 2 of those added frames at the start for clips that are not being trimmed at the start, or subtract 1 of those added frames for clips that are being trimmed by just 1 frame, correspondingly compensating the length.
Then later I will use another script to trim the trimmed clips when they are put back on the timeline, by 2 frames at the start and 3 frames at the finish.
I can get the basic script working, but I am having trouble with the code to determine if the clips are not being trimmed at all or by just one frame. The problem seems to be with the "if" statement in line 72 and/or the rest of that "if -else if - else" section up to line 87.
I am not a programmer and my "cobbling together" skills are failing me. I've run out of things to try, so can anyone tell me what I've got wrong? I'd also greatly appreciate any suggestions for improvement, as I'm sure it's inelegant and bloated as it is. Also, is there a way (if necessary) of increasing the accuracy of lines 95 and 96 (e.g. from milliseconds to micro or nanoseconds)?
Thanks!
The clips trimmed by ffmpeg decode in Vegas Pro a bit strangely at the ends. When the trimmed clips are put back on the timeline they usually have about 3 duplicate frames at the finish. At the start they are normally frame-accurate, but if the start is not being trimmed at all then there are 2 duplicate frames. If the start is trimmed by just 1 frame then there is 1 duplicate frame (I think).
To deal with this I want to add 2 frames to the start and 3 frames to the finish of all clips in this script, then subtract 2 of those added frames at the start for clips that are not being trimmed at the start, or subtract 1 of those added frames for clips that are being trimmed by just 1 frame, correspondingly compensating the length.
Then later I will use another script to trim the trimmed clips when they are put back on the timeline, by 2 frames at the start and 3 frames at the finish.
I can get the basic script working, but I am having trouble with the code to determine if the clips are not being trimmed at all or by just one frame. The problem seems to be with the "if" statement in line 72 and/or the rest of that "if -else if - else" section up to line 87.
I am not a programmer and my "cobbling together" skills are failing me. I've run out of things to try, so can anyone tell me what I've got wrong? I'd also greatly appreciate any suggestions for improvement, as I'm sure it's inelegant and bloated as it is. Also, is there a way (if necessary) of increasing the accuracy of lines 95 and 96 (e.g. from milliseconds to micro or nanoseconds)?
Thanks!
/** * Program: Export ffmpeg trimlist.cs
* Author: Nick Hope
* Adapted from the script WombleExport.cs by John Rofrano
* Purpose: This script will export the first Vegas Pro video track as a list in a .txt file.
* Each line contains the name of the media file, the timecode in, and the length of the event on the timeline
* separated by spaces.
* This file can then be used by a batch file to trim the files with ffmpeg
*
* Revision Date: Sept. 27, 2015
**/
using System;
using System.IO;
using System.Windows.Forms;
using Sony.Vegas;
class EntryPoint
{
public void FromVegas(Vegas vegas)
{
Timecode oneFrame = Timecode.FromFrames(1); // Get 1 frame in timecode format to use later
Timecode startAdd = Timecode.FromFrames(2); // Change number of frames to add to start
Timecode endAdd = Timecode.FromFrames(3); // Change number of frames to add to end
// get the first video track
VideoTrack videoTrack = null;
foreach (Track track in vegas.Project.Tracks)
{
if (track.IsVideo())
{
videoTrack = (VideoTrack)track;
break;
}
}
// if we didn't find a track then tell the user we can't continue
if (videoTrack == null)
{
MessageBox.Show("You must have at least one video track in your project",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// make sure the project has a name
if (vegas.Project.FilePath == null)
{
MessageBox.Show("You must give your project a name by saving it before running this script",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string trimlistFilename = String.Format("E:\\trimlist.txt");
// Alternative to create the trim list name from the project name
//string trimlistFilename = Path.ChangeExtension(vegas.Project.FilePath, ".txt");
int eventsProcessed = 0;
StreamWriter writer = null;
try
{
writer = new StreamWriter(trimlistFilename);
for (int i = 0; i < videoTrack.Events.Count; i++)
{
VideoEvent videoEvent = (VideoEvent)videoTrack.Events[i];
// Get the input file name
string infile = videoEvent.ActiveTake.MediaPath;
// get the path and filename without the extension
string basename = Path.Combine(Path.GetDirectoryName(infile), Path.GetFileNameWithoutExtension(infile));
Timecode clipOffsetOriginal = videoEvent.ActiveTake.Offset;
// clipOffsetOriginal as a number of frames
Int64 clipOffsetOriginalFrames = videoEvent.ActiveTake.Offset.FrameCount;
Timecode clipOffset = clipOffsetOriginal - startAdd;
Timecode clipDuration = videoEvent.Length + startAdd + endAdd;
// Reset start to zero if start was not trimmed at all, and compensate length
if (clipOffsetOriginalFrames == 0)
{
int OffsetAdjusterFrames = 2;
int DurationAdjusterFrames = -2;
}
// Reset start to zero if start had been trimmed by just 1 frame, and compensate length
else if (clipOffsetOriginalFrames == 1)
{
int OffsetAdjusterFrames = 1;
int DurationAdjusterFrames = -1;
}
else
{
int OffsetAdjusterFrames = 0;
int DurationAdjusterFrames = 0;
}
Timecode OffsetAdjuster = Timecode.FromFrames(OffsetAdjusterFrames);
Timecode DurationAdjuster = Timecode.FromFrames(DurationAdjusterFrames);
Timecode clipOffsetAdjusted = clipOffset + OffsetAdjuster;
Timecode clipDurationAdjusted = clipDuration + DurationAdjuster;
// Convert start and duration from timecode to seconds
double start = clipOffsetAdjusted.ToMilliseconds() / 1000;
double duration = clipDurationAdjusted.ToMilliseconds() / 1000;
string triminfo = String.Format(basename + ".mp4 " + start + " " + duration);
writer.WriteLine(triminfo);
eventsProcessed++;
}
writer.Close();
}
catch (Exception e)
{
if (null != writer)
{
writer.Close();
}
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
MessageBox.Show("Processed: " + eventsProcessed + " events",
"Complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}