Copy link to clipboard
Copied
I'm aware this is part of the QE DOM which isn't (for some reason) officially supported - shame because it seems to be able to do a lot of useful things!
I want a script I can run which will iterate through the current timeline, and for any track items whose name includes "preview", output a thumbnail frame of that clip to a folder. (I'm working with a lot of temp stock, and when the time comes to swap out all the items the client's chosen, it's a huge drag to compile a list manually that I can send to the person who's buying the stock. I want thumbnails not just names, to minimise the problem of them buying the wrong clip.)
QE seems to have a exportFramePNG() function, referenced here. That code suggests it takes two parameters: a timecode, in the format HH_MM_SS_FF, and a file path. So I'd expect something like this to work, on Windows - but it doesn't.
function secsToTimecode(sq, tm, d) { // hacky way to return a timecode with underscores
if (d == '') d = ":";
tps = 254016000000;
tb = sq.timebase; // ticks per frame
fps = tps/tb;
// frames
ff = Math.round((tm - Math.floor(tm)) * fps);
if (ff < 10) ff = '0' + ff;
// secs
ss = Math.floor(tm)%60;
if (ss < 10) ss = '0' + ss;
// mins
mm = Math.floor(tm/60)%60;
if (mm < 10) mm = '0' + mm;
// hrs
hh = Math.floor(tm/3600)%60;
if (hh < 10) hh = '0' + hh;
return hh + d + mm + d + ss + d + ff;
}
app.enableQE();
sqq = qe.project.getActiveSequence(); // QE version!
op = sqq.outPoint;
sq = app.project.activeSequence;
videoTracks = sq.videoTracks;
var outputPath = new File("C:\Users\Username\Desktop\frames");
for (i = 0; i < videoTracks.numTracks; i++) {
trk = videoTracks[i];
for(j = 0; j < trk.clips.numItems; j++) {
nm = trk.clips[j].name ;
if (nm.toUpperCase().indexOf("PREVIEW") != -1) { // Preview clip
if (trk.clips[j].start.seconds < op.secs) { // ignore any clips after end of work area
$.writeln(nm + ", T: " + trk.clips[j].start.seconds + ", Dur: " + trk.clips[j].duration.seconds); // This works as expected
tm = secsToTimecode(sq, trk.clips[j].start.seconds + (trk.clips[j].duration.seconds/2), '_'); // pick an export point that's halfway through the clip
sqq.exportFramePNG(tm, outputPath.fsName + '\\' + nm + ".png"); // This does nothing!
}
}
}
}
I reached out directly to Nick, with some questions and suggestions.
Copy link to clipboard
Copied
PProPanel has replaced QE DOM usage with 'vanilla' DOM usage:
https://github.com/Adobe-CEP/Samples/blob/e60d6a22ef44d8eb4cca3904c35a0c050576b697/PProPanel/jsx/PPR...
Copy link to clipboard
Copied
Thanks Bruce. I can't make that work, though. Here's the adapted (hacky as hell) code, but although it looks like it's stepping through the timeline and adjusting the in/out points as it goes, it's not outputting anything:
sq = app.project.activeSequence;
videoTracks = sq.videoTracks;
op = sq.getOutPointAsTime();
tps = 254016000000;
tb = sq.timebase;
oneframe = tb/tps; // should be the duration of one frame, in seconds
$.writeln("End: " + op.seconds);
var outputPath = new File("C:\Users\Username\Desktop\frames");
var oldInPoint = sq.getInPointAsTime();
var oldOutPoint = sq.getOutPointAsTime();
for (i = 0; i < videoTracks.numTracks; i++) {
trk = videoTracks[i];
for(j = 0; j < trk.clips.numItems; j++) {
nm = trk.clips[j].name ;
if (nm.toUpperCase().indexOf("PREVIEW") != -1) {
if (trk.clips[j].start.seconds < op.seconds) {
$.writeln(nm + ", T: " + trk.clips[j].start.seconds + ", Dur: " + trk.clips[j].duration.seconds);
tm = secsToTimecode(sq, trk.clips[j].start.seconds + (trk.clips[j].duration.seconds/2), '_');
sq.setInPoint(trk.clips[j].start.seconds + (trk.clips[j].duration.seconds/2));
sq.setOutPoint(trk.clips[j].start.seconds + (trk.clips[j].duration.seconds/2));
var removeUponCompletion = 0;
var startQueueImmediately = true;
var jobID_InToOut = app.encoder.encodeSequence(sq, outputPath.fsName + '\\' + nm + ".png", "C:\Users\Username\Documents\Adobe\Adobe Media Encoder\23.0\Presets\jpeg-frame.epr", app.encoder.ENCODE_IN_TO_OUT, removeUponCompletion, startQueueImmediately);
}
}
}
}
sq.setInPoint(oldInPoint.seconds);
sq.setOutPoint(oldOutPoint.seconds);
The .epr file is one I made for this, so it exists.
Copy link to clipboard
Copied
also this looks like it'll encode via AME? Or will it come direct from Premiere? (In some ways I'd rather it comes direct from Premiere and locks the program up for a minute or two, rather than exporting dozens of queue items to AME.)
Copy link to clipboard
Copied
That second part is easier; PProPanel shows how to render in PPro instead of AME, if you'd like to pay your editors to watch progress bars. 😉
https://github.com/Adobe-CEP/Samples/blob/e60d6a22ef44d8eb4cca3904c35a0c050576b697/PProPanel/jsx/PPR...
Copy link to clipboard
Copied
I reached out directly to Nick, with some questions and suggestions.
Copy link to clipboard
Copied
Still work, but there is a small mistak in github example.
I have revised the mistake and the following code will work.
exportCurrentFrameAsPNG();
function exportCurrentFrameAsPNG() {
app.enableQE();
var activeSequence = qe.project.getActiveSequence();
if (activeSequence) {
var time = activeSequence.CTI.timecode; // CTI = Current Time Indicator.
var removeThese = /:|;/ig; // Why? Because Windows chokes on colons in file names.
var timewin = time.replace(removeThese, '_'); //defei revised
var outputPath = new File("~/Desktop");
var outputFileName = outputPath.fsName + getSep() + timewin + '_' + activeSequence.name; //defei revised
activeSequence.exportFramePNG(time, outputFileName);
} else {
alert("No active sequence.");
}
}
function getSep() {
if (Folder.fs === 'Macintosh') {
return '/';
} else {
return '\\';
}
}
Copy link to clipboard
Copied
Classic mistake here. I didn't escape the backslashes, so the outputPath should have been
"C:\\Users\\Username\\Desktop\\frames"
Changing the rest of the code to conform with what's in PProPanel means it now works.
Copy link to clipboard
Copied
Still work, but there is a small mistak in github example.
I have revised the mistake and the following code will work.
exportCurrentFrameAsPNG();
function exportCurrentFrameAsPNG() {
app.enableQE();
var activeSequence = qe.project.getActiveSequence();
if (activeSequence) {
var time = activeSequence.CTI.timecode; // CTI = Current Time Indicator.
var removeThese = /:|;/ig; // Why? Because Windows chokes on colons in file names.
var timewin = time.replace(removeThese, '_'); //defei revised
var outputPath = new File("~/Desktop");
var outputFileName = outputPath.fsName + getSep() + timewin + '_' + activeSequence.name; //defei revised
activeSequence.exportFramePNG(time, outputFileName);
} else {
alert("No active sequence.");
}
}
function getSep() {
if (Folder.fs === 'Macintosh') {
return '/';
} else {
return '\\';
}
}