Phase 2: services/premiere-plugin/jsx/premiere.jsx
This commit is contained in:
parent
c78433aa14
commit
227d951d6d
1 changed files with 412 additions and 0 deletions
412
services/premiere-plugin/jsx/premiere.jsx
Normal file
412
services/premiere-plugin/jsx/premiere.jsx
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
/**
|
||||
* Wild Dragon MAM - Premiere Pro ExtendScript
|
||||
*
|
||||
* This file contains ExtendScript functions that interact with Premiere Pro
|
||||
* to import media files and manage the timeline.
|
||||
*
|
||||
* ExtendScript is Adobe's implementation of JavaScript that runs in the
|
||||
* Premiere Pro host application context.
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// Core Import Functions
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Imports a media file into the active Premiere Pro project
|
||||
* @param {string} filePath - Full path to the file to import
|
||||
* @returns {string} JSON string with success status and message
|
||||
*/
|
||||
function importFileToProject(filePath) {
|
||||
var result = {
|
||||
success: false,
|
||||
message: "",
|
||||
itemID: null
|
||||
};
|
||||
|
||||
try {
|
||||
// Check if project is open
|
||||
if (!app.project) {
|
||||
result.message = "No active Premiere Pro project";
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
// Check if file exists
|
||||
var file = new File(filePath);
|
||||
if (!file.exists) {
|
||||
result.message = "File does not exist: " + filePath;
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
// Import the file into the project
|
||||
app.project.importFiles([filePath]);
|
||||
|
||||
result.success = true;
|
||||
result.message = "File imported successfully";
|
||||
|
||||
return JSON.stringify(result);
|
||||
} catch (error) {
|
||||
result.message = "Error importing file: " + error.message;
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the active sequence in the project
|
||||
* @returns {string} JSON string with sequence name or null
|
||||
*/
|
||||
function getActiveSequence() {
|
||||
var result = {
|
||||
sequenceName: null,
|
||||
sequenceID: null
|
||||
};
|
||||
|
||||
try {
|
||||
if (!app.project) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
var activeSequence = app.project.activeSequence;
|
||||
if (activeSequence) {
|
||||
result.sequenceName = activeSequence.name;
|
||||
result.sequenceID = activeSequence.sequenceID;
|
||||
}
|
||||
|
||||
return JSON.stringify(result);
|
||||
} catch (error) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a clip into the active sequence at the playhead position
|
||||
* @param {string} filePath - Full path to the media file
|
||||
* @param {number} trackIndex - Video track index (1-based)
|
||||
* @returns {string} JSON string with success status
|
||||
*/
|
||||
function insertClipToSequence(filePath, trackIndex) {
|
||||
var result = {
|
||||
success: false,
|
||||
message: ""
|
||||
};
|
||||
|
||||
try {
|
||||
if (!app.project) {
|
||||
result.message = "No active project";
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
var sequence = app.project.activeSequence;
|
||||
if (!sequence) {
|
||||
result.message = "No active sequence";
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
// Import the file
|
||||
app.project.importFiles([filePath]);
|
||||
|
||||
// Find the imported item in the project
|
||||
var projectItem = null;
|
||||
var file = new File(filePath);
|
||||
var fileName = file.displayName;
|
||||
|
||||
// Search through project items for the imported file
|
||||
var rootBin = app.project.rootItem;
|
||||
projectItem = findProjectItemByName(rootBin, fileName);
|
||||
|
||||
if (!projectItem) {
|
||||
result.message = "Could not find imported file in project";
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
// Get the track at the specified index
|
||||
if (trackIndex < 1 || trackIndex > sequence.videoTracks.numTracks) {
|
||||
result.message = "Invalid track index: " + trackIndex;
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
var track = sequence.videoTracks[trackIndex - 1];
|
||||
var playheadTime = sequence.getTime();
|
||||
|
||||
// Create a clip from the project item
|
||||
var clip = projectItem.getMedia();
|
||||
if (!clip) {
|
||||
result.message = "Could not get media from project item";
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
// Insert at playhead position
|
||||
// Note: This is a simplified version. Real timeline editing requires
|
||||
// more sophisticated handling of clips and tracks
|
||||
var trackItem = track.insertClip(projectItem, playheadTime);
|
||||
|
||||
if (trackItem) {
|
||||
result.success = true;
|
||||
result.message = "Clip inserted at track " + trackIndex;
|
||||
} else {
|
||||
result.message = "Failed to insert clip into track";
|
||||
}
|
||||
|
||||
return JSON.stringify(result);
|
||||
} catch (error) {
|
||||
result.message = "Error inserting clip: " + error.message;
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current project file path
|
||||
* @returns {string} JSON string with project path
|
||||
*/
|
||||
function getProjectPath() {
|
||||
var result = {
|
||||
projectPath: null,
|
||||
projectName: null
|
||||
};
|
||||
|
||||
try {
|
||||
if (!app.project) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
var projectFile = app.project.path;
|
||||
if (projectFile && projectFile.exists) {
|
||||
result.projectPath = projectFile.fsName;
|
||||
result.projectName = projectFile.displayName;
|
||||
}
|
||||
|
||||
return JSON.stringify(result);
|
||||
} catch (error) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about all video tracks in the active sequence
|
||||
* @returns {string} JSON string with track information
|
||||
*/
|
||||
function getSequenceTracks() {
|
||||
var result = {
|
||||
tracks: []
|
||||
};
|
||||
|
||||
try {
|
||||
if (!app.project) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
var sequence = app.project.activeSequence;
|
||||
if (!sequence) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
for (var i = 0; i < sequence.videoTracks.numTracks; i++) {
|
||||
var track = sequence.videoTracks[i];
|
||||
result.tracks.push({
|
||||
index: i + 1,
|
||||
name: track.name || ("V" + (i + 1)),
|
||||
type: "video"
|
||||
});
|
||||
}
|
||||
|
||||
return JSON.stringify(result);
|
||||
} catch (error) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current playhead position in the active sequence
|
||||
* @returns {string} JSON string with playhead time in seconds
|
||||
*/
|
||||
function getPlayheadPosition() {
|
||||
var result = {
|
||||
timeInSeconds: 0,
|
||||
timeCode: ""
|
||||
};
|
||||
|
||||
try {
|
||||
if (!app.project) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
var sequence = app.project.activeSequence;
|
||||
if (!sequence) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
var time = sequence.getTime();
|
||||
result.timeInSeconds = time.seconds;
|
||||
|
||||
// Format as timecode
|
||||
var ticks = time.ticks;
|
||||
var ticksPerFrame = sequence.timebase;
|
||||
var frameNumber = Math.floor(ticks / ticksPerFrame);
|
||||
var fps = sequence.timebase / 254016000000;
|
||||
|
||||
var hours = Math.floor(frameNumber / (fps * 3600));
|
||||
var minutes = Math.floor((frameNumber % (fps * 3600)) / (fps * 60));
|
||||
var seconds = Math.floor((frameNumber % (fps * 60)) / fps);
|
||||
var frames = frameNumber % Math.floor(fps);
|
||||
|
||||
result.timeCode = pad(hours, 2) + ":" + pad(minutes, 2) + ":" +
|
||||
pad(seconds, 2) + ":" + pad(frames, 2);
|
||||
|
||||
return JSON.stringify(result);
|
||||
} catch (error) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Helper Functions
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Recursively searches for a project item by name
|
||||
* @param {Bin} bin - The bin to search in
|
||||
* @param {string} name - The name to search for
|
||||
* @returns {ProjectItem} The found project item or null
|
||||
*/
|
||||
function findProjectItemByName(bin, name) {
|
||||
if (!bin || !bin.children) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (var i = 0; i < bin.children.numItems; i++) {
|
||||
var item = bin.children[i];
|
||||
|
||||
// Check if this item matches
|
||||
if (item.name === name) {
|
||||
return item;
|
||||
}
|
||||
|
||||
// If it's a bin, search recursively
|
||||
if (item.type === "bin") {
|
||||
var found = findProjectItemByName(item, name);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads a number with leading zeros
|
||||
* @param {number} num - The number to pad
|
||||
* @param {number} digits - The number of digits to pad to
|
||||
* @returns {string} The padded number
|
||||
*/
|
||||
function pad(num, digits) {
|
||||
var str = "" + num;
|
||||
while (str.length < digits) {
|
||||
str = "0" + str;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets basic project information
|
||||
* @returns {string} JSON string with project info
|
||||
*/
|
||||
function getProjectInfo() {
|
||||
var result = {
|
||||
projectName: "",
|
||||
projectPath: "",
|
||||
videoSequenceCount: 0,
|
||||
audioSequenceCount: 0
|
||||
};
|
||||
|
||||
try {
|
||||
if (!app.project) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
result.projectName = app.project.name;
|
||||
|
||||
var projectFile = app.project.path;
|
||||
if (projectFile) {
|
||||
result.projectPath = projectFile.fsName;
|
||||
}
|
||||
|
||||
// Count sequences
|
||||
var rootBin = app.project.rootItem;
|
||||
if (rootBin && rootBin.children) {
|
||||
for (var i = 0; i < rootBin.children.numItems; i++) {
|
||||
var item = rootBin.children[i];
|
||||
if (item.type === "sequence") {
|
||||
// Check sequence type by checking tracks
|
||||
if (item.videoTracks && item.videoTracks.numTracks > 0) {
|
||||
result.videoSequenceCount++;
|
||||
}
|
||||
if (item.audioTracks && item.audioTracks.numTracks > 0) {
|
||||
result.audioSequenceCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JSON.stringify(result);
|
||||
} catch (error) {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the current sequence to a specified location
|
||||
* @param {string} outputPath - The path where the file should be exported
|
||||
* @param {string} presetName - The export preset name (e.g., "Apple ProRes 422 HQ")
|
||||
* @returns {string} JSON string with export status
|
||||
*/
|
||||
function exportSequence(outputPath, presetName) {
|
||||
var result = {
|
||||
success: false,
|
||||
message: ""
|
||||
};
|
||||
|
||||
try {
|
||||
if (!app.project) {
|
||||
result.message = "No active project";
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
var sequence = app.project.activeSequence;
|
||||
if (!sequence) {
|
||||
result.message = "No active sequence";
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
var outputFile = new File(outputPath);
|
||||
|
||||
// Get the export preset
|
||||
// Note: This requires the preset to be available in Premiere Pro
|
||||
var preset = app.getExportPreset(presetName);
|
||||
|
||||
if (!preset) {
|
||||
result.message = "Export preset not found: " + presetName;
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
// Export the sequence
|
||||
app.project.exportSequenceToFile(sequence, outputFile, preset);
|
||||
|
||||
result.success = true;
|
||||
result.message = "Export completed";
|
||||
|
||||
return JSON.stringify(result);
|
||||
} catch (error) {
|
||||
result.message = "Error exporting: " + error.message;
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Initialization
|
||||
// ============================================================================
|
||||
|
||||
// Log that the script has loaded
|
||||
if (typeof(alert) !== "undefined") {
|
||||
// alert("Wild Dragon MAM ExtendScript loaded");
|
||||
}
|
||||
Loading…
Reference in a new issue