跳转到内容

After Effects 脚本开发

欢迎来到使用 ExtendScript 开发 After Effects 脚本的综合指南。学习如何通过强大的脚本自动化工作流程、创建自定义工具并扩展 After Effects 的功能。

After Effects 脚本是 ExtendScript 程序,可用于自动化任务、操作项目元素并扩展应用程序的功能。它们的范围可以从简单的自动化工具到复杂的工作流程解决方案。

ExtendScript 是 Adobe 实现的 JavaScript,为 Creative Suite 应用程序提供了附加功能:

  • 基于 JavaScript ES3: 熟悉的 JavaScript 语法和概念
  • Adobe 扩展: 用于 After Effects 的特殊对象和方法
  • 文件系统访问: 在本地系统上读写文件
  • UI 创建: 构建自定义用户界面
  • 跨平台: 可在 Windows 和 macOS 上运行

在 After Effects 启动时自动运行的脚本,用于初始化和设置。

可通过 文件 > 脚本 菜单访问的脚本,用于按需功能。

具有自定义用户界面的脚本,可以停靠在 After Effects 工作区中。

在渲染过程中执行的脚本,用于自定义输出处理。

  1. ExtendScript 工具包 - Adobe 官方 IDE (旧版)
  2. Visual Studio Code - 带有 ExtendScript 扩展的现代编辑器
  3. After Effects - 用于测试的目标应用程序
  4. 文档 - Adobe ExtendScript 和 After Effects 脚本参考

脚本文件夹:

  • Windows: C:\Program Files\Adobe\Adobe After Effects [version]\Support Files\Scripts\
  • macOS: /Applications/Adobe After Effects [version]/Scripts/

ScriptUI 面板:

  • Windows: C:\Program Files\Adobe\Adobe After Effects [version]\Support Files\Scripts\ScriptUI Panels\
  • macOS: /Applications/Adobe After Effects [version]/Scripts/ScriptUI Panels/
// 基本的 After Effects 脚本模板
(function() {
'use strict';
// 检查 After Effects 是否可用
if (typeof app === 'undefined') {
alert('此脚本需要 After Effects');
return;
}
// 主要脚本逻辑
function main() {
try {
// 您的脚本代码在此处
var comp = app.project.activeItem;
if (!comp || !(comp instanceof CompItem)) {
alert('请选择一个合成');
return;
}
// 示例:创建一个固态层
var solidLayer = comp.layers.addSolid(
[1, 0, 0], // 红色
'脚本生成的固态层',
comp.width,
comp.height,
comp.duration
);
alert('固态层已创建: ' + solidLayer.name);
} catch (error) {
alert('错误: ' + error.toString());
}
}
// 执行主函数
main();
})();

app 对象是 After Effects 对象模型的根:

// 访问当前项目
var project = app.project;
// 获取活动的合成
var activeComp = app.project.activeItem;
// 应用程序设置
var version = app.version;
var language = app.isoLanguage;
// 创建新项目
app.newProject();
// 保存项目
app.project.save(new File('/path/to/project.aep'));
// 导入素材
var importFile = new File('/path/to/footage.mov');
var footageItem = app.project.importFile(new ImportOptions(importFile));
// 创建新合成
var newComp = app.project.items.addComp(
'我的合成', // 名称
1920, // 宽度
1080, // 高度
1.0, // 像素长宽比
10, // 持续时间 (秒)
30 // 帧率
);
// 向合成中添加图层
var textLayer = newComp.layers.addText('Hello World');
// 访问图层
var comp = app.project.activeItem;
var firstLayer = comp.layer(1);
var layerByName = comp.layer('图层名称');
// 修改图层属性
firstLayer.transform.position.setValue([960, 540]);
firstLayer.transform.scale.setValue([150, 150]);
firstLayer.transform.rotation.setValue(45);
// 添加关键帧
var position = firstLayer.transform.position;
position.setValueAtTime(0, [100, 100]);
position.setValueAtTime(2, [500, 300]);
function safeOperation() {
try {
// 风险操作
var comp = app.project.activeItem;
if (!comp) {
throw new Error('没有活动的合成');
}
// 继续操作
return comp.layers.addSolid([1, 1, 1], '白色固态层', 100, 100, 1);
} catch (error) {
// 优雅地处理错误
$.writeln('safeOperation 中的错误: ' + error.toString());
return null;
}
}
// 将操作分组以便单次撤销
app.beginUndoGroup('我的脚本操作');
try {
// 此处有多个操作
var comp = app.project.activeItem;
var layer1 = comp.layers.addSolid([1, 0, 0], '红色', 100, 100, 1);
var layer2 = comp.layers.addSolid([0, 1, 0], '绿色', 100, 100, 1);
layer2.transform.position.setValue([200, 200]);
} finally {
app.endUndoGroup();
}
function processLayers() {
var comp = app.project.activeItem;
if (!comp) return;
var totalLayers = comp.numLayers;
// 创建进度条
var progressPanel = new Window('dialog', '处理图层');
var progressBar = progressPanel.add('progressbar', undefined, 0, totalLayers);
var progressText = progressPanel.add('statictext', undefined, '开始中...');
progressPanel.show();
try {
for (var i = 1; i <= totalLayers; i++) {
// 更新进度
progressBar.value = i;
progressText.text = '正在处理 ' + totalLayers + ' 个图层中的第 ' + i + '';
progressPanel.update();
// 处理图层
var layer = comp.layer(i);
// 您的处理逻辑在此处
// 短暂延迟以显示进度
$.sleep(100);
}
} finally {
progressPanel.close();
}
}
// 创建 ScriptUI 面板
function createPanel(thisObj) {
var panel = (thisObj instanceof Panel) ? thisObj : new Window('dialog', '我的脚本面板');
// 添加 UI 元素
var group1 = panel.add('group');
group1.orientation = 'row';
group1.add('statictext', undefined, '图层名称:');
var nameInput = group1.add('edittext', undefined, '新图层');
nameInput.characters = 20;
var group2 = panel.add('group');
group2.orientation = 'row';
var createButton = group2.add('button', undefined, '创建图层');
var cancelButton = group2.add('button', undefined, '取消');
// 按钮事件处理
createButton.onClick = function() {
createLayerWithName(nameInput.text);
};
cancelButton.onClick = function() {
panel.close();
};
// 显示面板
if (panel instanceof Window) {
panel.show();
}
return panel;
}
function createLayerWithName(name) {
var comp = app.project.activeItem;
if (comp && comp instanceof CompItem) {
var layer = comp.layers.addSolid([Math.random(), Math.random(), Math.random()], name, 100, 100, 1);
alert('已创建图层: ' + layer.name);
}
}
// 执行
createPanel(this);
function readTextFile(filePath) {
var file = new File(filePath);
if (file.exists) {
file.open('r');
var content = file.read();
file.close();
return content;
}
return null;
}
function writeTextFile(filePath, content) {
var file = new File(filePath);
file.open('w');
file.write(content);
file.close();
}
function saveProjectData(data) {
var jsonString = JSON.stringify(data, null, 2);
var file = File.saveDialog('保存项目数据', '*.json');
if (file) {
writeTextFile(file.fsName, jsonString);
}
}
function loadProjectData() {
var file = File.openDialog('加载项目数据', '*.json');
if (file) {
var jsonString = readTextFile(file.fsName);
return JSON.parse(jsonString);
}
return null;
}
// 避免重复访问图层
// 差:
for (var i = 1; i <= comp.numLayers; i++) {
comp.layer(i).transform.position.setValue([100, 100]);
comp.layer(i).transform.scale.setValue([50, 50]);
}
// 好:
for (var i = 1; i <= comp.numLayers; i++) {
var layer = comp.layer(i);
layer.transform.position.setValue([100, 100]);
layer.transform.scale.setValue([50, 50]);
}
// 使用撤销组以获得更好的性能
app.beginUndoGroup('批量创建图层');
for (var i = 0; i < 100; i++) {
comp.layers.addSolid([Math.random(), Math.random(), Math.random()], '图层 ' + i, 100, 100, 1);
}
app.endUndoGroup();
// 输出到 ExtendScript 工具包控制台
$.writeln('调试信息: ' + variable);
// 提醒用户反馈
alert('操作完成');
// 确认对话框
if (confirm('继续操作?')) {
// 用户点击了确定
}
function logError(error, context) {
var logMessage = new Date().toString() + ' - ' + context + ': ' + error.toString();
$.writeln(logMessage);
// 可选地写入文件
var logFile = new File(Folder.desktop + '/ae_script_log.txt');
logFile.open('a'); // 追加模式
logFile.writeln(logMessage);
logFile.close();
}
  1. 错误处理: 始终使用 try-catch 块以确保脚本健壮
  2. 撤销组: 将相关操作分组以获得更好的用户体验
  3. 进度反馈: 为长时间操作提供进度指示器
  4. 代码组织: 使用函数和模块以保持代码可维护
  5. 测试: 使用不同的项目配置测试脚本
  6. 文档: 为您的代码添加注释以便将来维护
  1. 设置您的 开发环境
  2. 从简单的自动化脚本开始
  3. 探索 社区示例 获取灵感
  4. 学习高级 ScriptUI 以创建复杂界面
  5. 加入 After Effects 脚本社区寻求支持