Adobe UXP 开发
时间:2026-03-22
Premiere API—UXP for Adobe Premiere
做一个可以自动导出插件
main.js
/*************************************************************************
* ADOBE CONFIDENTIAL
* ___________________
*
* Copyright 2025 Adobe
* All Rights Reserved.
*
* NOTICE: Adobe permits you to use, modify, and distribute this file in
* accordance with the terms of the Adobe license agreement accompanying
* it. If you have received this file from a source other than Adobe,
* then your use, modification, or distribution of it requires the prior
* written permission of Adobe.
*
* apidoc
* https://developer.adobe.com/premiere-pro/uxp/ppro_reference/classes/encodermanager/#exportsequence
* https://developer.adobe.com/premiere-pro/uxp/plugins/concepts/manifest/#clipboard
**************************************************************************/
// Global object.
const ppro = require("premierepro");
const { entrypoints, host, versions, shell, script } = require("uxp");
const os = require("os");
const fs = require("fs");
entrypoints.setup({
plugin: {
create() {
console.log("Plugin created");
},
destroy() {
console.log("Plugin destroyed");
}
},
panels: {
starterpanel: { // 👈 must match the id of the entrypoint
// of type "panel" from manifest.json
create(rootNode) { console.log("Panel created"); },
show(rootNode) { console.log("Panel shown"); },
hide(rootNode) { console.log("Panel hidden"); },
destroy(rootNode) { console.log("Panel destroyed"); }
}
},
commands: {
//窗口 -> UXP -> 插件 -> 命令函数
firstCommand: (evt) => {
console.log(
"函数命令被调用->", evt.type // uxpcommand
);
},
}
});
//打开项目
(async function init(){
const openOption = ppro.OpenProjectOptions()
const ss = await ppro.Project.open("E:\\developer\\pr_workspace\\kumushu_bgvideo\\枯木树背景视频_1_1.prproj",openOption);
/**
setTimeout(async ()=>{
//关闭选项用于控制是否弹出确认等
const closeOption = ppro.CloseProjectOptions();
const closeok = await ss.close(closeOption);
console.log("关闭项目是否成功=>"+closeok);
},3000)
**/
eval('alert(app.version)')
})()
// Call the Premiere Pro API to populate Application Info area.
async function populateProjectInfo() {
// Get the active project.
const project = await ppro.Project.getActiveProject();
if (!project) {
log("There is no active project found", "red");
} else {
log(`Active project: ${project.name}`);
// Get the active sequence.
const sequence = await project.getActiveSequence();
if (!sequence) {
log("There is no active sequence found", "red");
} else {
log(`Active sequence: ${sequence.name}`);
}
}
try {
const project = await ppro.Project.getActiveProject();
const sequence = await project.getActiveSequence();
//切换序列
const sequences = await project.getSequences();
sequences.forEach(async (s)=>{
if(s.name == "序列 02"){
const asequence = await project.getSequence(s.guid);
project.setActiveSequence(asequence)
}
});
// 使用 Action 机制执行修改,加锁在同一个食物中切割
project.lockedAccess(() => {
project.executeTransaction((compoundAction) => {
// 创建设置开始时间的 Action
const startAction = trackItem.createSetStartAction(ppro.TickTime.createWithSeconds(0));
compoundAction.addAction(startAction);
// 创建设置结束时间的 Action
const endAction = trackItem.createSetEndAction(ppro.TickTime.createWithSeconds(1));
compoundAction.addAction(endAction);
});
});
// 获取要插入的剪辑项
const rootItem = await project.getRootItem();
const items = await rootItem.getItems();
//找出要编辑的项目
const projectItem = items.find(item => item.name == "018.mp4");
//项目转换成剪辑选项
const clipItem = ppro.ClipProjectItem.cast(projectItem);
//当前序列编辑器
const seqEditor = await ppro.SequenceEditor.getEditor(sequence);
// 设置插入时间(3秒位置)
const insertTime = await ppro.TickTime.createWithSeconds(3);
//编码管理器
const manager = ppro.EncoderManager.getManager();
/**
* EVENT_RENDER_COMPLETE 渲染成功完成时触发。
EVENT_RENDER_CANCEL 渲染被用户取消时触发。
EVENT_RENDER_PROGRESS 渲染进行中时触发,可用于更新进度条。
EVENT_RENDER_ERROR 渲染过程中发生错误时触发。
EVENT_RENDER_QUEUE 渲染任务被添加到队列时触发。
* **/
// 2. 定义事件处理函数
function onProgress(eventData) {
// eventData 中通常包含进度百分比
console.log(`渲染进度: ${(eventData.progressAmount * 100).toFixed(2)}%`);
// 你可以在这里更新插件UI的进度条
}
async function onComplete(eventData) {
console.log('✅ 渲染完成!输出文件:', eventData.outputPath);
// 执行完成后的操作,如播放提示音、清理资源等
console.log('平台->'+os.platform());
if(os.platform() == "win32"){
const result = await shell.openPath( // external command
"C:\\Windows\\System32\\taskkill.exe /IM \"Adobe Media Encoder.exe\" /F", // ✅ will run
"kill ok" // ⚠️ result is an empty string
);
console.log('是否杀死 Adobe Media Encoder.exe =>'+result);
}
}
function onError(eventData) {
console.error('❌ 渲染错误:', eventData.error);
}
function onCancel(eventData) {
console.log('⏸️ 渲染已取消');
}
// 3. 注册事件监听器 (使用 addEventListener)
await ppro.EventManager.addEventListener(
manager,
ppro.EncoderManager.EVENT_RENDER_PROGRESS,
onProgress
);
await ppro.EventManager.addEventListener(
manager,
ppro.EncoderManager.EVENT_RENDER_COMPLETE,
onComplete
);
await ppro.EventManager.addEventListener(
manager,
ppro.EncoderManager.EVENT_RENDER_ERROR,
onError
);
await ppro.EventManager.addEventListener(
manager,
ppro.EncoderManager.EVENT_RENDER_CANCEL,
onCancel
);
console.log('事件监听器注册完成');
// 导出操作本身已封装Action,可直接调用
const ret =await manager.exportSequence(
sequence,
//ppro.Constants.ExportType.QUEUE_TO_AME,//导出到AME渲染,如果像监听导出进度必须使用这个
ppro.Constants.ExportType.IMMEDIATELY,//直接pr渲染
"d:\\output.mp4",
"E:\\developer\\pr_workspace\\uxp_plugin\\H264 - 匹配源 - 2020.epr"
,true
);
console.log("剪辑插入成功"+ret);
} catch (err) {
console.error("操作失败:", err);
}
}
// Event listener for the Populate Application Info button.
document
.querySelector("#btnPopulate")
.addEventListener("click", populateProjectInfo);
// Event listener for the Clear Application Info button.
document.querySelector("#clear-btn").addEventListener("click", () => {
document.getElementById("plugin-body").innerHTML = "";
});
// Log function to display messages in the plugin body.
function log(msg, color) {
document.getElementById("plugin-body").innerHTML += color
? `<span style='color:${color}'>${msg}</span><br />`
: `${msg}<br />`;
}
function updateTheme(theme) {
panelBody = document.getElementById("plugin-body");
panelHeading = document.getElementById("plugin-heading");
if(theme.includes("dark")) {
panelBody.style.color = "#fff";
panelHeading.style.color = "#fff";
} else {
panelBody.style.color = "#000";
panelHeading.style.color = "#000";
}
}
document.theme.onUpdated.addListener((theme) => {
updateTheme(theme);
})
const currentTheme = document.theme.getCurrent();
updateTheme(currentTheme);manifest.json
{
"id": "Playground_starter.plugin.html",
"name": "库目书",
"shortname": "3pstarterplugin",
"version": "1.0.0",
"main": "index.html",
"host": {
"app": "premierepro",
"minVersion": "25.6.0"
},
"manifestVersion": 5,
"requiredPermissions": {
"localFileSystem": "fullAccess",
"clipboard": "readAndWrite",
"launchProcess": {
"extensions": [
".exe",
".mp4",
".pdf",
""
],
"schemes": [
"https",
"mailto"
]
}
},
"entrypoints": [
{
"id": "starterpanel",
"type": "panel",
"minimumSize": {
"width": 430,
"height": 500
},
"maximumSize": {
"width": 2000,
"height": 2000
},
"preferredDockedSize": {
"width": 230,
"height": 300
},
"preferredFloatingSize": {
"width": 400,
"height": 300
},
"label": {
"default": "库目书"
},
"icons": [
{
"width": 23,
"height": 23,
"path": "icons/dark.png",
"scale": [
1,
2
],
"theme": [
"darkest",
"dark",
"medium"
]
},
{
"width": 23,
"height": 23,
"path": "icons/light.png",
"scale": [
1,
2
],
"theme": [
"lightest",
"light"
]
}
]
},
{
"type": "command",
"id": "firstCommand",
"label": {
"default": "运行一个函数"
}
}
],
"icons": [
{
"width": 48,
"height": 48,
"path": "icons/plugin-icon.png",
"scale": [
1,
2
],
"theme": [
"darkest",
"dark",
"medium",
"lightest",
"light",
"all"
],
"species": [
"pluginList"
]
}
]
}