
Чтение текста из файла, бегущая строка и титры, подсчёт символов формулами, свои шрифты и ручной кернинг — то, что обычно остаётся за кадром туториалов по Text+.
Text+ (в списке узлов он же Text1) — самый недооценённый узел в Fusion-странице DaVinci Resolve. Обычно его используют для набора заголовка и выбора шрифта, а дальше даже не открывают остальные вкладки. Здесь — то, что обычно проходит мимо: чтение текста из файла, бегущая строка и титры, подсчёт символов формулами, свои шрифты и ручная расстановка букв.
Коротко о термине, если ты впервые открываешь expression: это формула, которую вписываешь в поле параметра вместо ручного значения — правый клик по полю → Expression. С этого момента значение в поле каждый кадр вычисляется по формуле. Ниже formulas в основном живут в поле StyledText узла Text+ — том самом большом текстовом поле, куда обычно просто печатают текст.
Текст из файла
Text+ умеет не только принимать напечатанный текст, но и подтягивать его из обычного текстового файла — удобно, когда текст присылает заказчик или он часто меняется: правишь файл на диске, а не лезешь каждый раз в проект.
Пока это работает только с файлами из папки документов DaVinci Resolve — на Windows это
C:\\Documents\\Blackmagic Design\\DaVinci Resolve\\FusionТуда нужно положить свой текстовый файл — например, text.txt, отформатированный заранее в любом текстовом редакторе.
Дальше — правый клик внутри поля StyledText → Expression, и в поле expression:
Text(assert(io.open(comp:MapPath("comp:/text.txt"), "r")):read("*all"):gsub("\\\\n", '\\n'):gsub("\\\\t", " "))
Подтягивает содержимое файла целиком, с переносами строк и табуляцией как в оригинале. Удобно, если нужно вставить присланный текст «как есть»: отрендерил один раз, поменял файл на диске, отрендерил снова с другим текстом — без правок в самом проекте.
Ничто не мешает завести несколько таких Text+ с разными файлами — просто меняй имя файла в формуле у каждого.
Построчный вывод по таймингу
Похожий трюк, но для списка: одна строка текстового файла показывается за раз, и через заданный интервал сменяется на следующую — как титры со сменой реплик. Тут formulas живут не в StyledText, а на странице настроек композиции, в двух отдельных полях: Start Render Script (выполняется один раз, в начале рендера) и Frame Render Script (выполняется на каждом кадре).
Сначала Start Render Script — читает файл целиком в таблицу построчно:
f = [[C:\\list.txt]] -- путь к файлу
interval = 2 -- через сколько кадров меняется строка
t = {}
for l in io.lines(f) do
table.insert(t, l)
end
num_lines = table.getn(t)А затем Frame Render Script — на каждом кадре берёт из этой таблицы нужную по времени строку и кладёт её в StyledText:
index = math.floor(time / interval)
if index > num_lines then
index = num_lines
end
StyledText = tПодставь свой путь к файлу в f и нужный интервал смены строк в interval — остальное произойдёт само.
Считаем и препарируем текст формулами
Дальше — набор формул, которые читают содержимое StyledText одного узла и что-то с ним делают: считают, режут, переставляют. Чтобы формула могла сослаться на текст ИЗ ДРУГОГО узла, у него должно быть имя — например, Text1 — и тогда в формуле другого Text+ пишешь Text1.StyledText.Value, и туда прилетает именно то, что напечатано в Text1.
string.len(Text1.StyledText.Value)
Сколько всего символов в тексте Text1 — включая пробелы и знаки препинания.
:_, mylines = string.gsub(Text1.StyledText.Value, "\\n", ""); return mylines
Сколько в тексте строк.
:_, myspaces = string.gsub(Text1.StyledText.Value, "%s", ""); return myspaces
Сколько пробелов.
:_, myletters = string.gsub(Text1.StyledText.Value, "%a", ""); return myletters
Сколько букв, без пробелов и цифр.
:_, mylower = string.gsub(Text1.StyledText.Value, "%l", ""); return mylower
Сколько символов в нижнем регистре (включая цифры).
:_, myupper = string.gsub(Text1.StyledText.Value, "%u", ""); return myupper
Сколько символов в ВЕРХНЕМ регистре.
:_, alphanumeric = string.gsub(Text1.StyledText.Value, "%w", ""); return alphanumeric
Сколько букв и цифр вместе.
:_, myvow = string.gsub(Text1.StyledText.Value, "[AEIOUaeiou]", ""); return myvow
Сколько гласных букв (латиница).
:_, novow = string.gsub(Text1.StyledText.Value, "[^AEIOUaeiou]", ""); return novow
Всё, кроме гласных: согласные, цифры, пробелы, знаки.
:_, mydigits = string.gsub(Text1.StyledText.Value, "%d", ""); return mydigits
Сколько цифр.
:_, punctuation = string.gsub(Text1.StyledText.Value, "%p", ""); return punctuation
Сколько знаков препинания.
:_, controlchar = string.gsub(Text1.StyledText.Value, "%c", ""); return controlchar
Сколько управляющих символов — на экране не видны (перенос строки, табуляция), но формально тоже часть текста.
:_, myhex = string.gsub(Text1.StyledText.Value, "%x", ""); return myhex
Сколько символов годится для шестнадцатеричной записи — цифры и буквы A–F.
:_, myletters = string.gsub(Text1.StyledText.Value, "%A", ""); return myletters
Всё, что НЕ буквы. Общее правило для всех формул выше: заглавная буква класса после % (было %a, стало %A) всегда переключает результат на противоположный, так же как ^ перед классом в квадратных скобках.
Дальше — не подсчёт, а обработка текста: результат тоже формула, но выводит не число, а переделанный текст.
string.rep(Text1.StyledText.Value, 3)
Повторяет текст Text1 три раза подряд.
string.reverse(Text1.StyledText.Value)
Переворачивает текст задом наперёд.
string.lower(Text1.StyledText.Value)
Весь текст в нижний регистр.
string.upper(Text1.StyledText.Value)
Весь текст в ВЕРХНИЙ регистр.
string.sub(Text1.StyledText.Value, 1, 2)
Первые 2 буквы текста. Отсчёт слева, поэтому 1, 3 — это 1-я, 2-я и 3-я буквы. Отрицательные числа считают с конца.
string.byte(Text1.StyledText.Value, 1)
ASCII-код первой буквы текста числом. Отсчёт тоже слева, отрицательные числа — с конца.
string.char(Text1.StyledText.Value, 1)
Обратное действие: символ по его ASCII-коду.
И склейка текста из нескольких источников:
Text1.StyledText.Value .. " " .. "Eggs"
Текст Text1, пробел и слово «Eggs» следом. Два дефиса .. склеивают строки в Lua — между ними и добавляют пробел, если он нужен: просто напиши .. " " ...
Text1.StyledText.Value .. Text2.StyledText.Value
Текст из двух Text+ подряд, без пробела между ними.
Ещё один источник текста — поле Comments на странице настроек любого узла: обычная текстовая заметка, но её тоже можно склеить формулой, и в неё точно так же можно вставить модификатор — например, таймкод (правый клик в поле Comments → Timecode).
Text1.StyledText.Value .. Comments.Value
Текст Text1 и содержимое поля Comments того же узла — например, вписанный туда таймкод — подряд, без пробела.
Text1.StyledText.Value .. " " .. Comments.Value
То же самое, но с пробелом между ними.
Бегущая строка и титры
Прокручивающиеся титры в конце ролика и бегущая строка внизу экрана — тоже штатная функция Text+, просто спрятана не на первой вкладке.
- На вкладке Layout поменяй Type с Point на Frame — и там же выставь Width и Height в 1.
- Перейди на вкладку Text и найди под настройками привязки (anchor) комбобокс Scroll. Roll — это прокрутка титров, Crawl — бегущая строка.
- Выбери Roll — появится ещё один параметр, Scroll Position. Правый клик по нему → Expression.
1-(time/comp.RenderEnd)
В Scroll Position запускает прокрутку титров снизу вверх на протяжении всей композиции. Не забудь напечатать сам текст в StyledText.
Для бегущей строки внизу экрана то же самое, только Scroll ставится на Crawl — а нужную скорость и положение подбираешь через Width, Height и Position на вкладке Layout.
Не только текст
Text+ умеет выводить не только напечатанное, но и почти что угодно другое — значения других узлов, дату, случайные числа.
Transform1.Angle
Общий принцип: ИмяУзла.Параметр выводит значение любого параметра любого узла композиции — не обязательно текстового. Angle здесь просто пример, работает с любым свойством.
Center.X .. " " .. Center.Y
Координаты самого узла Text+ — X и Y через пробел.
string.format("%.4f" ,Center.X)
То же значение, но округлённое до 4 знаков после запятой — сырые координаты обычно слишком длинные для читаемого вывода.
string.format("%.2f" ,Center.X) .. "x" .. " ".. string.format("%.2f" ,Center.Y) .. "y"
Координаты X и Y вместе, округлённые до 2 знаков, с подписями «x» и «y» — готовая строка для вывода на экран.
math.random()
Случайное число от 0 до 1 — новое на каждом кадре. При воспроизведении будет мельтешить: если нужно значение, привязанное к конкретному кадру, а не дёргающееся на каждом, для этого в статье про expressions есть randomseed.
math.random(0, 100)
То же самое, но случайное целое число от 0 до 100.
os.date("%a")
Сокращённое название текущего дня недели. Со вставленным кэшем кадров могут быть нюансы — движок иногда придерживает старое значение, но в самом рендере дата всегда актуальная.
Код после % в os.date() меняет, что именно выводится:
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
| [object Object] | [object Object] |
Свои шрифты под рукой
Если список шрифтов в Text+ огромный, а пользуешься на деле десятком — можно собрать отдельную папку с избранными и подключить её отдельным пунктом в выпадающем списке шрифтов.
- В папке документов DaVinci Resolve создай папку
Fontsи скопируй туда нужные шрифты. Путь на Windows:C:\\Documents\\Blackmagic Design\\DaVinci Resolve. - На странице Fusion открой Fusion → Fusion Settings → Path Map.
- В списке выбери Fonts — внизу панели появятся детали пути. Нажми на папку и укажи ту, что создал.
- Сохрани и перезапусти Resolve — шрифты подгружаются только при старте программы.
После перезапуска в выпадающем списке шрифтов Text+ появится отдельная группа с твоими избранными.
Ручной кернинг
Текст не обязан лежать ровной строкой — расстояние между конкретными буквами можно двигать руками, а не только общим трекингом.
На странице Fusion, когда в кадре есть текст и выбран сам узел Text+, в левом верхнем углу вьюера есть набор мелких значков. Наведи на них и найди «allow manual kerning» — включи его, затем увеличь масштаб на тексте в кадре: у каждой буквы появится маленький красный квадрат. Перетаскивая его, двигаешь именно эту букву, не трогая остальные.
На постоянку это не нужно почти никогда, но для леттеринга в заголовке или подгонки логотипа под текст — единственный способ подвинуть одну букву, не разваливая всю строку.