nlve/BACKLOG.md
4aiman 235cd00e9a Предпросмотр показывает кадрирование клипа
Клип со своим кадрированием играл в окне во весь кадр: цепочка фильтров
у mpv одна на весь список кусков, а включить её на одном куске и
выключить на следующем нечем — из фильтров ffmpeg по времени
переключается только наложение.

Обошлось без цепочки вовсе. У вывода mpv своя обрезка, и делает её
видеокарта: курсор зашёл в клип с кадрированием — выставили, вышел —
сняли. Ни перестройки цепочки, ни копирования кадров из памяти
видеокарты в обычную.

Рамку источника считает теперь один код на две стороны: по ней окно
«Кадрирование и поворот» рисует рамку, и её же плеер отдаёт как обрезку.
Проверка в tests/lfmcheck сверяет рамку с фильтром сборки: увеличение
2.77 даёт 970x546 посередине, и это ровно то, что вырезает
crop=2688:1512:2379:1338 после scale=7446:4188.

Проверено глазами на невидимом экране, на настоящем материале с дрона:
картинка в окне совпала с готовым роликом, на границе с обычным клипом
обрезка снимается и возвращается. Сверено со сборкой из прошлого
коммита — там на том же месте кадр без кадрирования.

Не покрыто и записано в BACKLOG: отражение (свойства для него нет),
растяжение и участки с наложением — там кадр уже сведён цепочкой.
2026-10-01 00:04:57 +03:00

220 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Что отложено
Список того, что известно и сознательно не сделано. Не «когда-нибудь
починим», а «знаем, чего это стоит, и решили пока не платить».
## macOS: собирается, но работает наполовину
Сборка проверена. В тулчейне fpcupdeluxe уже стоит всё нужное:
кросс-компиляторы, Apple SDK (10.13, 11.0, 12.3) и виджетсет cocoa для
обеих архитектур. Обе цели собираются с первого раза:
./build.sh macos → nlve_intel (Mach-O x86_64)
nlve_arm (Mach-O arm64)
Чего не будет, пока не сделано:
**Предпросмотра нет.** Встраивание mpv написано под два случая: X11 (под
gtk2 создаётся своё дочернее окно и его номер отдаётся mpv в `wid`) и
Windows (там у панели есть настоящий HWND). Под cocoa нужен третий путь —
отдать mpv указатель на NSView. Это не правка на десять строк: нужно
разобраться, как LCL под cocoa отдаёт NSView панели, и проверить, что mpv
рисует именно в неё.
**Окно зависимостей врёт.** Списки в `uDeps.pas` разделены на два случая:
Windows и всё остальное. Мак попадает во второй и получает совет
`sudo apt install ffmpeg`. Нужен свой список: `brew install ffmpeg mpv`
или готовые сборки.
**Проверить нечем.** У нас нет мака. Собранный, но ни разу не запущенный
файл — это предположение, а не сборка. Всё, что можно утверждать сейчас:
компилятор и компоновщик отработали без ошибок.
**Двух файлов может оказаться мало.** Intel и Apple Silicon сейчас
раздаются отдельно. Склеить их в один универсальный умеет `lipo`, но в
тулчейне он есть только для powerpc — для x86_64 и arm64 его надо
доставить.
**Обёртка .app не настроена.** lazbuild её создаёт, но внутри лежит
ссылка на файл с именем `nlve`, которого после переименования нет.
Сейчас она просто удаляется. Настоящему приложению нужны свой Info.plist,
значок и, для раздачи, подпись и нотаризация у Apple.
## Лицензия не выбрана
libmpv грузится в наш процесс, а её сборки — GPL (в Ubuntu GPL-3+ из-за
libsmbclient, у shinchiro тоже GPL). По толкованию FSF это делает
совместную работу производной, и при раздаче программа должна быть под
GPL-3+ или совместимой.
Пока ничего не раздаётся — вопрос не стоит. Решать его перед первой
раздачей сборок. Возможный обход: отказаться от libmpv в пользу своего
вывода кадров через ffmpeg, но это большая работа и заметно хуже по
плавности.
ffmpeg проблемой не является: он запускается отдельной программой.
## Настоящая прозрачность в исходном файле
Цветовой ключ выбивает цвет, но бывает и прозрачность, записанная в самом
файле: WebM с VP8/VP9, ProRes 4444, QuickTime Animation. ffmpeg их
распаковывает в кадр с альфа-каналом, и ключ таким файлам не нужен —
достаточно не выбрасывать альфу по дороге.
Что для этого потребуется, когда дойдут руки:
- при добавлении файла запоминать, есть ли у него альфа (`pix_fmt` с
буквой «a»: yuva420p, yuva444p10le, argb);
- такой клип считать несплошным так же, как клип с ключом, — то есть
собирать участок слоями;
- в цепочке фильтров следить, чтобы альфа не терялась: `scale` её
сохраняет, а `pad` — только с прозрачным цветом полей;
- аппаратное декодирование к таким файлам не применять: альфа в VP9
лежит отдельным потоком, и видеокарта его не отдаёт.
Чего не будет в любом случае: раздать готовый ролик с прозрачностью в
MP4/H.264 нельзя — контейнер и кодек альфу не хранят. Для этого нужен
отдельный вывод в VP9 или ProRes 4444.
## Предпросмотр: чего он про кадрирование всё ещё не показывает
Кадрирование обычного клипа окно теперь показывает — обрезкой на выводе
плеера, её делает видеокарта даром. Остались три случая, где оно
по-прежнему играется как есть, и для них точную картинку даёт окно
«Кадрирование и поворот»:
**Отражение.** У вывода mpv нет свойства для отражения, только для
поворота. Понадобится — придётся вести такой клип через цепочку.
**Растяжение.** Кадр жмётся неравномерно, рамкой это не описать.
**Участок с наложением.** Там кадр уже сведён цепочкой, и обрезка на
выводе резала бы сведённое целиком, вместе с нижним слоем. Такой клип
нужно вести через ту же цепочку, что и само наложение.
Цена пути через цепочку известна, мерили (DJI 2688x1512, HEVC
55 Мбит/с, 600 кадров, `--vo=null`):
| | время | кадров в секунду |
|---|---|---|
| без фильтра | 1.82 с | 330 |
| ветка «обрезать и растянуть» с `enable` | 2.81 с | 214 |
Нужно 60, то есть запас трёхкратный: по деньгам проходит. Устроена она
так: раздвоить поток, одну ветку обрезать и растянуть, и наложить её на
другую с `enable='between(t,...)'`. Иначе никак — из фильтров ffmpeg по
времени переключается только `overlay`, у `crop` и `scale` поддержки
временной шкалы нет.
## Два видео рядом в одном кадре
Два ролика 16:9, каждый обрезан до половины кадра: один слева до
середины, другой от середины вправо. Никакого смешивания, просто два
куска рядом.
Сборке для этого не нужно ничего нового — только числа. Проверено на
настоящих файлах, кадр получается с первого раза:
[0:v]crop=1344:1512:672:0,pad=2688:1512:0:0,setsar=1[l];
[1:v]crop=1344:1512:672:0,setsar=1[r];
[l][r]overlay=1344:0[out]
То есть каждому источнику своя обрезка, затем оба кладутся на свои места.
Именно такой граф и строит `ArgsRenderLayers`: у слоя уже есть и своя
цепочка фильтров, и координаты, куда его положить.
Не хватает трёх вещей, и первая — главная.
**Клипу негде записать, какое место в кадре он занимает.** Преобразование
сейчас описывает только, как источник ложится в кадр целиком: вписать,
заполнить с обрезкой, увеличение, смещение, поворот. Масштаб при этом
всегда равномерный, поэтому из кадра 2688x1512 никакими настройками не
получить полосу 1344x1512 — для неё нужно сжать вдвое по ширине и не
трогать высоту. Нужен прямоугольник назначения: четыре числа в долях
кадра проекта. Тогда всё остальное — вписывание, увеличение, смещение —
начинает работать внутри него, а `BuildTransform` меняется только в
аргументах: размер прямоугольника вместо размера кадра, а возвращаемые
координаты сдвигаются на его начало.
**Уплощение считает непрозрачный клип закрывающим всё.** Нижний клип
подхватывается, только когда верхний полупрозрачный или с ключом. Значит
половинка на верхней дорожке сегодня закроет собой нижнее видео чёрными
полями. Условие должно смотреть на прямоугольник назначения: не накрывает
кадр — значит под ним видно то, что ниже.
**Предпросмотру нужна вторая дорожка наложения.** Сейчас плеер добавляет
одну: основа — список кусков, поверх неё одна внешняя дорожка. Для двух
половинок обе должны идти через цепочку над чёрной основой, то есть
внешних дорожек нужно две. Механика та же самая — ещё один `video-add` и
ещё один вход `[vidN]` в цепочке.
Переключателей, которые стоят машинного времени, становится больше, а
живут они кто где: прилипание и схлопывание — кнопками внизу, ключ в
предпросмотре — в меню «Вид», выбор кодировщика вообще нигде (берётся
NVENC, если он есть). Это разрозненно и не даёт увидеть общую цену.
Нужно одно окно, где собрано всё, что можно выключить ради скорости:
- ключ и прозрачность в предпросмотре (сейчас в меню «Вид»);
- наложение в предпросмотре вообще — на слабой машине может не хватать и
его, тогда честнее показывать одну основу;
- кодировщик для пересборки: аппаратный или процессорный, и какой
именно;
- где держать кэш и когда его убирать;
- прилипание клипов и курсора (сейчас кнопками, но им место и здесь).
Почему это важно: разработка идёт на машине с быстрой видеокартой, и
всё, что здесь считается «недорогим», на другой может оказаться
неподъёмным. Пока цифры замеряны только на одной машине, у человека
должна быть возможность выключить любую из этих трат.
## Сборка потоком: чего она не даёт
Ролик собирается потоком — куски идут сразу в готовый файл, кэш не
создаётся. За это заплачено тремя вещами, и все три известны заранее.
**Продолжение стоит места.** Дописать в конец существующего MKV нельзя:
Matroska этого не даёт. Продолжение всегда пишется в новый файл, куда
сперва переливается целая часть старого, так что на диске в этот момент
лежат оба — места нужно вдвое больше готового ролика. Обойти это можно
только разбором и правкой самого контейнера, а это уже своя маленькая
библиотека Matroska.
**Отступ назад — до целого куска.** Продолжают не с последнего
записанного кадра, а с границы последнего целого куска: кусок — это
неделимая единица, у него свои метки времени и своё число кадров. На
замерах терялось от нуля до нескольких секунд работы. Мельче отступать
можно было бы, храня рядом с файлом карту стыков, но выигрыш в секундах
не стоит нового файла, который надо держать в согласии с роликом.
**MP4 продолжать нельзя вовсе.** Оглавление пишется в конец, оборванный
файл не открывается — `moov atom not found`. Программа предупреждает об
этом до начала сборки и предлагает MKV. Теоретически недописанный MP4
можно восстановить, собрав оглавление по кускам самому (так делают
untrunc и подобные), но это отдельная задача другого размера.
**Потоком идёт не всё.** MPEG-TS несёт не любой кодек, и пересборка
всего ролика под площадку требует списка кусков. В этих случаях сборка
идёт по-старому, через кэш — со всеми его 110 ГБ на часе материала.
## Мелочи, до которых не дошли руки
**Вид дорожки не виден в её заголовке.** Дорожки картинки, звука и текста
подписаны V1, A1, Т1, и по букве вид угадывается, но не более того.
Клип, попавший на дорожку чужого вида, теперь не принимается и не
теряется, но само различие стоило бы показать явно — значком или цветом
полосы заголовка.
**Значок файла программы под Windows.** Значок окна задаётся из
`uIconData`, а значок самого `.exe` в проводнике берётся из ресурса при
сборке — там он до сих пор стандартный.
**Кэш наложений не убирается.** Каждая правка наплыва создаёт в кэше
проекта новый файл; старые остаются лежать. Клипы с ключом и
прозрачностью сюда больше не попадают — их показывает сам плеер, — так
что расти кэшу теперь почти не с чего.
**Окно кадрирования открывается около четырёх секунд.** Оно синхронно
достаёт два кадра ffmpeg-ом (по 2.2 с каждый на шестигигабайтном файле) и
только потом показывается. Лечится показом окна сразу и дорисовкой кадра
по готовности, либо одним кадром вместо двух.