nlve/IMPLEMENTATION_PLAN.md
4aiman 73911410e9 Цветовой ключ и живое наложение в предпросмотре
Клипу задаётся цвет, который при сборке становится прозрачным. Окно
ключа показывает кадр: цвет берётся щелчком по нему, выбитое показано
клеткой, допуск и смягчение края — ползунками. Открывается из окна
кадрирования и из меню «Правка», на монтаже клип помечен квадратиком
выбиваемого цвета.

Предпросмотр перестал сводить такие участки в файлы. Плеер играет две
дорожки одна поверх другой: оверлей во весь ролик больше не заставляет
пересобирать весь фильм после каждой правки. Замерено: наложение стоит
0.4 с на 10 с материала 2688x1512, вчетверо быстрее реального времени.

Починено в сборке: уменьшенный клип обкладывался чёрными полями, и они
закрывали собой нижнее видео — оставалась видна только дырка, выбитая
ключом. Теперь верхний слой кладётся по координатам, тем же, по которым
его показывает предпросмотр.

Смещение по горизонтали и вертикали работает и там, где картинка меньше
кадра проекта: раньше уменьшенный клип нельзя было сдвинуть в угол.

Проверки форм теперь создают каждое окно из файла формы: элемент,
забытый в классе, вскрывается на сборке, а не при открытии окна.
2026-08-31 00:10:28 +03:00

8.7 KiB
Raw Blame History

План: наложение в предпросмотре без сборки

Что не так сейчас

Клип с ключом или полупрозрачностью перестаёт быть сплошным, и участок под ним приходится сводить в отдельный файл. Для пятисекундного наплыва это копейки. Для оверлея во весь ролик — а это обычный случай, компас или карта поверх всего материала, — сводится весь фильм: «Собираю наложение 1 из 10» после каждой правки, и всё это через видеокарту, в кэш, который потом никто не убирает.

Хуже того: пока сведение не готово, в окне показывается верхний клип как есть — пурпурная плашка во весь кадр. То есть человек ждёт минуты ради картинки, которая мешает работать.

Решение

Предпросмотр не сводит ничего. Плеер играет две дорожки одна поверх другой: верхний клип — как он есть, на своём месте в кадре, нижний — везде, где верхний его не накрывает. Кодировать при этом нечего.

Это не композитинг: наложение живёт только в плеере. В готовом ролике всё по-прежнему сводится по-настоящему, с ключом и прозрачностью.

Замерено до начала работ (mpv 0.37, тяжёлое видео 2688x1512, HEVC 87 Мбит/с, 600 кадров):

Что Время
только основа 2.13 с
основа плюс оверлей поверх (масштаб и overlay) 2.53 с

Вчетверо быстрее реального времени; наложение стоит 0.4 с на 10 с материала. Список кусков (EDL) как внешняя видеодорожка тоже принимается, проверено.

Этап 1. Место клипа в кадре

Цель. Знать не только цепочку фильтров для клипа, но и куда именно его класть в кадре.

Критерий готовности. Функция отдаёт цепочку без обкладывания полями и отдельно — точку, куда встанет получившаяся картинка. Числа те же, что уже даёт сборка: где сборка обкладывает полями, плеер кладёт по тем же координатам.

Проверка. Для одного и того же клипа pad=W:H:X:Y из сборки и точка X:Y из новой функции совпадают.

Состояние. Готов.

Обе стороны считает один и тот же код. Сверено на пяти случаях: середина, угол, упор в край, заполнение с обрезкой, поворот на 90 — координаты совпали везде.

Этап 2. Уплощение с отдельным оверлеем

Цель. Разделить монтаж на основу и то, что кладётся поверх.

Критерий готовности. Уплощение для предпросмотра не считает клип с ключом или прозрачностью победителем: под ним видно то, что лежит ниже. Такие клипы собираются отдельным списком с их временем и местом в кадре. Уплощение для сборки не меняется вовсе.

Проверка. Модульная: монтаж из нижнего клипа и оверлея во весь ролик даёт основу из одного куска и один оверлей на всю длину.

Состояние. Готов.

Проверка 8 в nlvetool flattest: при сборке побеждает верхний клип, при уплощении для предпросмотра в основе виден нижний, а верхний ушёл в оверлей со своим временем, размером и местом.

Одна дорожка не может показывать два куска разом, поэтому оверлеи, наложившиеся друг на друга по времени, берутся не все: первый уходит в наложение, остальные остаются в основе и сводятся по-старому. Потерять их было бы хуже.

Этап 3. Наложение в плеере

Цель. Плеер показывает обе дорожки.

Критерий готовности. Оверлей подключается вторым видеовходом (video-add), цепочка lavfi-complex кладёт его на основу по координатам и только на своём отрезке времени. Звук в той же цепочке остаётся как был.

Проверка. Снимок кадра предпросмотра: оверлей на своём месте, под ним видно нижнее видео, ничего не собиралось.

Состояние. Готов.

Проверено снимками на невидимом экране, в том числе при воспроизведении: основа играет, оверлей стоит в своём углу, в кэше проекта ни одного сведённого файла.

Важное про цепочку: она отбирает дорожки, и всё, что в ней не упомянуто, mpv снимает с выбора. Поэтому при наложении звук приходится вести через неё же, даже когда дорожка одна, — иначе он просто пропадает. Проверено отдельно: та же самая цепочка, прогнанная через mpv в файл, даёт и картинку, и звук.

Этап 4. Убрать лишнюю сборку

Цель. Предпросмотр перестаёт заказывать сведение.

Критерий готовности. Сведение остаётся только для наплывов и переходов, где оно и правда нужно. Правка оверлея не запускает ни одного ffmpeg.

Проверка. Правка клипа с ключом на длинном монтаже: в журнале ни одной строки о сборке наложения, картинка меняется сразу.

Состояние. Готов.

По дороге вскрылась ошибка самой сборки, и она была в готовом ролике, а не только в окне. Уменьшенный клип обкладывался полями до кадра проекта, поля чёрные и непрозрачные, и они закрывали собой всё нижнее видео — оставалась видна только та дырка, которую выбил ключ. Теперь верхний слой не обкладывается полями, а кладётся на своё место теми же координатами, что и в предпросмотре. Сверено по точкам кадра: вне оверлея готовый ролик совпал с нижним видео.

Чего это не даёт

Предпросмотр не равен готовому ролику. Ключ в окне не применяется: верхний клип виден со своим фоном. Так решено сознательно — видно, что и куда положено, а как оно вырежется, показывает сборка. Применить ключ на лету стоит недорого, и это может стать переключателем.

Наплывы и переходы по-прежнему собираются. Они короткие, и живого пути для них не пишем.