After Effects: как запустить внешний процесс и отсоединить его

У меня есть вопрос о сценариях After Effects, но я не уверен, что он будет решен с помощью знаний AE, может быть, больше с помощью автономной разработки.

Я хочу запустить внешний процесс из After Effects, на самом деле я хочу запустить визуализацию открытого файла AEP с помощью файла aerender.exe, поставляемого с After Effects, сохраняя при этом его работоспособность.

var projectFile = app.project.file;
var aeRender = "C:\\Program Files\\Adobe\\Adobe After Effects CC 2018\\Support Files\\aerender.exe";
var myCommand = "-project" + " " + projectFile.fsName;
system.callSystem("cmd /c \""+aeRender+"\"" + " " + myCommand);

Итак, я написал этот простой код JSX, и он работает, он правильно отображает очередь рендеринга сцены. А вот After Effects зависает, ждет окончания процесса. Я хочу, чтобы он оставался пригодным для использования.

Итак, я попытался написать файл .cmd и запустить его с помощью AE system.callSystem, и у меня возникла та же проблема, я попытался пройти через файл .exe (скомпилированный из простого python с помощью pyInstaller), та же проблема:

import sys
import subprocess

arg = sys.argv
pythonadress = arg[0]
aeRender = arg[1]
projectFileFSname = arg[2]

myCommand = "-project" + " " +projectFileFSname
callSystem = "cmd /c \""+aeRender +"\"" + " " + myCommand
subprocess.run(callSystem)

Я даже пробовал с «cmd /c start», и это кажется еще хуже, поскольку After Effects продолжает зависать после завершения процесса.

Есть ли способ заставить AE поверить, что процесс завершен, хотя на самом деле это не так?

Любая помощь будет очень признательна!


person Guillaume Polveche    schedule 26.01.2020    source источник


Ответы (1)


system.callSystem() заморозит выполнение скрипта, поэтому вместо этого вы можете динамически создать файл .bat и запустить его с помощью .execute().

Вот пример .js:

var path = {
  "join": function ()
  {
    if (arguments.length === 0) return null;

    var args = [];

    for (var i = 0, iLen = arguments.length; i < iLen; i++)
    {
      args.push(arguments[i]);
    }

    return args.join(String($.os.toLowerCase().indexOf('win') > -1 ? '\\' : '/'));
  }
};

if (app.project.file !== null && app.project.renderQueue.numItems > 0)
{
  var
  // aeRenderPath = path.join(new File($._ADBE_LIBS_CORE.getHostAppPathViaBridgeTalk()).parent.fsName, 'aerender.exe'), // works only in CC 2018 and earlier
  aeRenderPath = path.join(new File(BridgeTalk.getAppPath(BridgeTalk.appName)).parent.fsName, 'aerender.exe'),
  batFile = new File(path.join(new File($.fileName).parent.fsName, 'render.bat')),
  batFileContent = [
    '"' + aeRenderPath + '"',
    "-project",
    '"' + app.project.file.fsName + '"'
  ];

  batFile.open('w', undefined, undefined);
  batFile.encoding = 'UTF-8';
  batFile.lineFeed = 'Unix';
  batFile.write(batFileContent.join(' '));
  batFile.close();

  // system.callSystem('explorer ' + batFile.fsName);
  batFile.execute();

  $.sleep(1000); // Delay the script so that the .bat file can be executed before it's being deleted
  batFile.remove();
}

Вы можете, конечно, развить его дальше и сделать его совместимым с OSX, добавить больше возможностей и т. д., но это основная идея.

Вот список всех параметров рендеринга (если вы их еще не знаете): https://helpx.adobe.com/after-effects/using/automated-rendering-network-rendering.html

Кстати, $._ADBE_LIBS_CORE.getHostAppPathViaBridgeTalk() даст вам путь к файлу «AfterFX.exe», так что вы можете упростить путь к «aerender.exe».

РЕДАКТИРОВАТЬ: $._ADBE_LIBS_CORE был удален в CC2019, поэтому вы можете использовать BridgeTalk напрямую вместо CC 2019 и выше.

person Alex Munteanu    schedule 26.01.2020
comment
Большое спасибо за такой подробный ответ Алексей! Я просто случайно нашел другой способ, используя system.callSystem("explorer "+batFile.fsName) - person Guillaume Polveche; 26.01.2020
comment
Да, он делает то же самое, что и execute(). - person Alex Munteanu; 26.01.2020
comment
На самом деле кажется, что с system.callSystem("explorer " + batFile.fsName) процесс рендеринга начинается намного медленнее. Я не совсем уверен, почему, но execute() может быть лучшим подходом. Я также отредактировал пример javascript с path.join реализацией модуля path, найденного в Node JS, чтобы вы могли построить путь более элегантно. - person Alex Munteanu; 26.01.2020
comment
Хорошая точность! Я не заметил этой задержки, но рендеры часто бывают очень долгими, поэтому продолжительность запуска процесса становится менее важной. - person Guillaume Polveche; 03.02.2020