[JavaScript, API] ExtendScript Работа с композициями
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
<- Предыдущая статья ExtendScript Работа с файламиВ прошлых двух статьях я рассказал, как сделать скрипт запускающийся в After Effects. Наш скрипт создавал окно в интерфейсе программы, в котором мы можем писать и выполнять код ExtenScript. Но это игрушка, полезна она может быть только новичку. Давайте же сделаем нечто более полезное, применимое в реальной жизни.Одной из самых распространенных задач, которые встречались мне в работе была динамичная расстановка титров в видеороликах. Видео сегодня, один из самых популярных форматов контента. Одно из ограничений накладываемых браузером, невозможность запустить в ролике звук без действия пользователя. Естественный выход из данной ситуации, заменить звук титрами. Если это 5 - 10 титров, то можно сделать их и руками. Ну а что, если вам надо выпускать по пять роликов в день и в них не 10, а 50 - 70 титров? Да еще каждый ролик в 2 - 3 форматах. Да плюс ко всему, еще и на нескольких языках? Если вам кажется такая ситуация необычной, то я сталкиваюсь с ней ежедневно.Так давайте же упростим эту задачу на сколько это возможно. Мы сделаем более менее универсальный скрипт, который будет интерпретировать текст в титры на сцене After Effects. Хоть я и решал эту задачу уже много раз, буду писать свой скрипт прямо во время написания статьи, чтобы ничего не упустить и сделать свой рассказ максимально подробным. Приступим.Текст титров мы будем вводить следующим образом
#simple Текст первого титра
Тип данного титра simple
#simple Титры simple могут быть и в одну строку
#double Текст третьего титра
Тип этого титра double
Титры отделены друг от друга двойным переносом. Строки одного титра разделены переносом. Первое слово с символом # является тегом, определяющим тип титра. По этому тегу мы впоследствии будем определять какой макет нам нужен для создания данного титра. Но об этом чуть позже, пока примите такую структуру текста как должное.За основу нашего скрипта можно взять скрипт из первой статьи. Мы оставим в интерфейсе те же элементы только немного подредактируем. Во первых, я убрал весь код в самовызывающуюся функцию init, просто для удобства, чтобы он не мешал в общей массе остального кода.
{
(function init(){
// Тут весь код из скрипта первой статьи
})();
}
Далее мы исправим дефолтный текст в текстовом поле
var editText = win.add(
'edittext',
[0, 0, 300, 300],
'Введите текст титров',
{multiline: true}
);
Ну а в обработчике нажатия кнопки run мы удалим строку выполнения кода, заменив ее на вызов метода createTitres
btnRun.onClick = function () {
try {
createTitres(editText.text.getTitresData());
} catch (err) {
alert(err)
}
};
Соответственно нам надо создать метод createTitres, принимающий аргументом некий массив данных.
function createTitres(data) {
}
И расширить класс String, добавив ему метод getTitresData, который будет парсить текст, создавая из него массив объектов. Это в свою очередь влечет небольшое расширение класса Array, ему мы добавим метод map. Приведу оба расширения вместе.
String.prototype.getTitresData = function() {
return this
.replace(/(^\n|^ |^"|\n+$| +$|"+$)/g, "")
.split("\n\n")
.map(function(d) {
var str = d.replace(/(^\n|^ |\n+$| +$)/g, "")
var tag = str.split(" ")[0];
var text = str.replace(tag + ' ', '');
return {
type: tag.replace('#', ''),
text: text,
}
});
}
Array.prototype.map = function(callback) {
var arr = [];
for (var i = 0; i < this.length; i++) {
arr.push(callback(this[i]));
}
return arr;
}
Давайте посмотрим, что у нас тут происходит. В методе getTitresData мы первым делом удаляем из строки часто встречающиеся артефакты в начале и в конце всего текста. Такими артефактами являются переносы, пробелы и, что случается, если копировать текст из гугл таблицы, кавычки.
this.replace(/(^\n|^ |^"|\n+$| +$|"+$)/g, "")
Далее мы разбиваем текст по разделителю двойной перенос
.split("\n\n")
И формируем из получившегося массива новый, отделяя от каждого титра тег
.map(function(d) {
var str = d.replace(/(^\n|^ |^"|\n+$| +$|"+$)/g, "")
var tag = str.split(" ")[0];
var text = str.replace(tag + ' ', '');
return {
type: tag.replace('#', ''),
text: text,
}
});
Я запустил скрипт. В метод createTitres приходит массив объектов. Пока все верно. Можно двигаться дальше.Теперь нам следует поработать над макетом. Открываем After Effects. Создаем новый проект. В окне Project добавим папку, назовем ее 1x1. В этой папке создадим композицию с именем ModelScene_1x1
По префиксу ModelScene мы будем определять, что это макет сцены, по настройкам этого макета мы будем ориентироваться далее. Суффикс 1x1 означает соотношение сторон, мне так удобнее понимать о какой сцене идет речь. Вы же можете выбрать другой суффикс, главное в дальнейшем следить, чтобы макеты титров имели тот же суффикс в имени. Префикс с суффиксом отделены нижним подчеркиванием.Настраиваем нашу сцену.
Указываем ширину, высоту, частоту кадров, продолжительность сцены. Значение Duration лучше сделать побольше, чтобы влезли все титры. Все эти параметры мы позже скопируем в нашу рабочую сцену.Макет сцены готов. Вернемся к скрипту.В методе createTitres первым действием мы получим данные всех сцен имеющихся в нашем макете.
function createTitres(data) {
var scenesData = getScenesData();
}
function getScenesData() {
var doc = app.project;
var data = [];
for (var i = 1; i <= doc.numItems; i++) {
var item = doc.item(i);
if (item instanceof CompItem &&
/^ModelScene/.test(item.name)) {
data.push({
type: item.name.split('_')[1],
width: item.width,
height: item.height,
frameRate: Math.floor(1 / item.frameDuration),
duration: item.duration
});
}
}
return data;
}
В новом методе getScenesData мы проходимся по всем элементам в нашем проекте. Обратите внимание, что индексация элементов в списке проекта начинается с единицы. Общее число элементов хранится в свойстве проекта numItems.
for (var i = 1; i <= doc.numItems; i++)
Мы смотрим, является ли элемент композицией и есть ли в его имени префикс ModelScene.
if (item instanceof CompItem &&
/^ModelScene/.test(item.name))
Если условие выполнено, добавляем данные о сцене в массив.
data.push({
type: item.name.split('_')[1],
width: item.width,
height: item.height,
frameRate: Math.floor(1 / item.frameDuration),
duration: item.duration
});
Нас интересует тип сцены, отделяем суффикс от ее имени. Ширина, высота, частота кадров и продолжительность сцены. Частоту кадров мы выссчитываем из свойства frameDuration - длительность одного кадра в секундах.Теперь пройдемся по массиву, поищем наши сцены в проекте, и если таковых нет, создадим их.
function createTitres(data) {
var scenesData = getScenesData();
for(var i = 0; i < scenesData.length; i++) {
var scene = getScene(scenesData[i]);
}
}
function getScene(data) {
var sceneName = 'scene-' + data.type;
return getItem(sceneName, CompItem) ||
app.project.items.addComp(
sceneName,
data.width,
data.height,
1,
data.duration,
data.frameRate
);
}
function getItem(name, type) {
var doc = app.project;
for (var i = 1; i <= doc.numItems; i++) {
if (doc.item(i).name === name) {
if (type) {
if (doc.item(i) instanceof type) {
return doc.item(i);
}
} else {
return doc.item(i);
}
}
}
return null;
}
Метод getScene сначала ищет композицию в проекте по имени
getItem(sceneName, CompItem)
И если не находит такой, то создает ее, используя параметры макета
app.project.items.addComp(
sceneName,
data.width,
data.height,
1,
data.duration,
data.frameRate
);
Можете проверить работу скрипта. Если вы все сделали правильно, в проекте должна появиться композиция scene-1x1. Сюда мы будем добавлять наши титры. Но об этом в следующий раз.Полный скрипт к этой статье с комментариями вы можете найти тутВ следующей статье я расскажу, как добавлять титры на сцену.<- Предыдущая статья ExtendScript Работа с файлами
===========
Источник:
habr.com
===========
Похожие новости:
- [Информационная безопасность, Системное администрирование, Программирование, API] Подтверждение номеров телефона без SMS
- [Open source, Виртуализация, Карьера в IT-индустрии, Openshift] Поваренная книга Quarkus Cookbook, бесплатный Developer Sandbox for OpenShift и руководство CentOS Project
- [Мессенджеры, API] Всё, о чём должен знать разработчик Телеграм-ботов
- [Высокая производительность, JavaScript, Программирование, Клиентская оптимизация, TypeScript] JavaScript нанобенчмарки и преждевременные тормоза
- [API, Финансы в IT] Обзор бесплатных источников котировок фондового рынка
- [Анализ и проектирование систем, *nix, API, Разработка под Linux, Разработка под Windows] Спецификация D-Bus. Часть 2, заключительная (перевод)
- [Open source, Java, Scala, Apache, Natural Language Processing] Программируемые NER компоненты
- [Python, API, Программирование микроконтроллеров, Разработка для интернета вещей] Опыт написания IDL для embedded
- [JavaScript, ООП] Создание квадратизированной галереи проектов на JS v 2.0
- [Совершенный код, .NET, API, C#, Микросервисы] Паттерн CQRS: теория и практика в рамках ASP.Net Core 5
Теги для поиска: #_javascript, #_api, #_extendscript, #_after_effects, #_kompozitsija (композиция), #_titry (титры), #_javascript, #_api
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:10
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
<- Предыдущая статья ExtendScript Работа с файламиВ прошлых двух статьях я рассказал, как сделать скрипт запускающийся в After Effects. Наш скрипт создавал окно в интерфейсе программы, в котором мы можем писать и выполнять код ExtenScript. Но это игрушка, полезна она может быть только новичку. Давайте же сделаем нечто более полезное, применимое в реальной жизни.Одной из самых распространенных задач, которые встречались мне в работе была динамичная расстановка титров в видеороликах. Видео сегодня, один из самых популярных форматов контента. Одно из ограничений накладываемых браузером, невозможность запустить в ролике звук без действия пользователя. Естественный выход из данной ситуации, заменить звук титрами. Если это 5 - 10 титров, то можно сделать их и руками. Ну а что, если вам надо выпускать по пять роликов в день и в них не 10, а 50 - 70 титров? Да еще каждый ролик в 2 - 3 форматах. Да плюс ко всему, еще и на нескольких языках? Если вам кажется такая ситуация необычной, то я сталкиваюсь с ней ежедневно.Так давайте же упростим эту задачу на сколько это возможно. Мы сделаем более менее универсальный скрипт, который будет интерпретировать текст в титры на сцене After Effects. Хоть я и решал эту задачу уже много раз, буду писать свой скрипт прямо во время написания статьи, чтобы ничего не упустить и сделать свой рассказ максимально подробным. Приступим.Текст титров мы будем вводить следующим образом #simple Текст первого титра
Тип данного титра simple #simple Титры simple могут быть и в одну строку #double Текст третьего титра Тип этого титра double {
(function init(){ // Тут весь код из скрипта первой статьи })(); } var editText = win.add(
'edittext', [0, 0, 300, 300], 'Введите текст титров', {multiline: true} ); btnRun.onClick = function () {
try { createTitres(editText.text.getTitresData()); } catch (err) { alert(err) } }; function createTitres(data) {
} String.prototype.getTitresData = function() {
return this .replace(/(^\n|^ |^"|\n+$| +$|"+$)/g, "") .split("\n\n") .map(function(d) { var str = d.replace(/(^\n|^ |\n+$| +$)/g, "") var tag = str.split(" ")[0]; var text = str.replace(tag + ' ', ''); return { type: tag.replace('#', ''), text: text, } }); } Array.prototype.map = function(callback) { var arr = []; for (var i = 0; i < this.length; i++) { arr.push(callback(this[i])); } return arr; } this.replace(/(^\n|^ |^"|\n+$| +$|"+$)/g, "")
.split("\n\n")
.map(function(d) {
var str = d.replace(/(^\n|^ |^"|\n+$| +$|"+$)/g, "") var tag = str.split(" ")[0]; var text = str.replace(tag + ' ', ''); return { type: tag.replace('#', ''), text: text, } }); По префиксу ModelScene мы будем определять, что это макет сцены, по настройкам этого макета мы будем ориентироваться далее. Суффикс 1x1 означает соотношение сторон, мне так удобнее понимать о какой сцене идет речь. Вы же можете выбрать другой суффикс, главное в дальнейшем следить, чтобы макеты титров имели тот же суффикс в имени. Префикс с суффиксом отделены нижним подчеркиванием.Настраиваем нашу сцену. Указываем ширину, высоту, частоту кадров, продолжительность сцены. Значение Duration лучше сделать побольше, чтобы влезли все титры. Все эти параметры мы позже скопируем в нашу рабочую сцену.Макет сцены готов. Вернемся к скрипту.В методе createTitres первым действием мы получим данные всех сцен имеющихся в нашем макете. function createTitres(data) {
var scenesData = getScenesData(); } function getScenesData() { var doc = app.project; var data = []; for (var i = 1; i <= doc.numItems; i++) { var item = doc.item(i); if (item instanceof CompItem && /^ModelScene/.test(item.name)) { data.push({ type: item.name.split('_')[1], width: item.width, height: item.height, frameRate: Math.floor(1 / item.frameDuration), duration: item.duration }); } } return data; } for (var i = 1; i <= doc.numItems; i++)
if (item instanceof CompItem &&
/^ModelScene/.test(item.name)) data.push({
type: item.name.split('_')[1], width: item.width, height: item.height, frameRate: Math.floor(1 / item.frameDuration), duration: item.duration }); function createTitres(data) {
var scenesData = getScenesData(); for(var i = 0; i < scenesData.length; i++) { var scene = getScene(scenesData[i]); } } function getScene(data) { var sceneName = 'scene-' + data.type; return getItem(sceneName, CompItem) || app.project.items.addComp( sceneName, data.width, data.height, 1, data.duration, data.frameRate ); } function getItem(name, type) { var doc = app.project; for (var i = 1; i <= doc.numItems; i++) { if (doc.item(i).name === name) { if (type) { if (doc.item(i) instanceof type) { return doc.item(i); } } else { return doc.item(i); } } } return null; } getItem(sceneName, CompItem)
app.project.items.addComp(
sceneName, data.width, data.height, 1, data.duration, data.frameRate ); =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:10
Часовой пояс: UTC + 5