Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Does exportFramePNG() still work??

Contributor ,
Mar 23, 2023 Mar 23, 2023

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

 

 

TOPICS
Export , SDK
639
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Adobe Employee , Mar 23, 2023 Mar 23, 2023

I reached out directly to Nick, with some questions and suggestions. 

Translate
Adobe Employee ,
Mar 23, 2023 Mar 23, 2023
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Mar 23, 2023 Mar 23, 2023

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.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Mar 23, 2023 Mar 23, 2023

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.)

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Employee ,
Mar 23, 2023 Mar 23, 2023

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...

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Employee ,
Mar 23, 2023 Mar 23, 2023

I reached out directly to Nick, with some questions and suggestions. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jan 31, 2024 Jan 31, 2024
LATEST

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 '\\';
    }
}
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Mar 24, 2023 Mar 24, 2023

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.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jan 31, 2024 Jan 31, 2024

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 '\\';
    }
}
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines