Commit graph

84 commits

Author SHA1 Message Date
ffd105a8c0 Щелчок в месте наезда перебирает клипы
Наезд двух клипов на одной дорожке — заказ на переход, то есть обычное
дело. Нажатие же всегда попадало в верхний по списку, и нижний клип
нельзя было ни выделить, ни потащить: чтобы до него добраться,
приходилось сперва убирать верхний.

Правило такое. Нажатие берёт тот из накрытых клипов, который уже выделен,
иначе верхний. Щелчок без движения по уже выделенному переводит выделение
на следующий, после последнего снова на верхний. Переключение сделано на
отпускании намеренно: пока кнопку не отпустили, неизвестно, щелчок это
или начало протяжки, а менять клип под рукой посреди протяжки нельзя.
Благодаря этому протяжка тащит именно то, что перед ней выбрали
щелчками.

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

Отбор вынесен в TTrack.ClipsAt, числовая проверка — в lfmcheck.
tests/pickcycle.sh щёлкает дважды и тащит: на прежней сборке уезжает
верхний клип, а нижний едет за ним схлопыванием.
2026-10-16 15:43:01 +03:00
c18b695b89 Своё кадрирование картинки доходит до предпросмотра и ролика
Окно «Кадрирование и поворот» показывало картинку уменьшенной и
сдвинутой, а в кадре она шла во весь экран. В уплощении преобразование
ставилось только обычному видео: у картинки своя ветка, и там его не
было вовсе. Кусок из картинки делался по жёсткой цепочке «вписать целиком
плюс поля», про клип она ничего не знала.

Кусок и так делается заново, поэтому цепочка запекается прямо в него —
тем же TransformFilter, которым считают видео и само окно. Разными путями
считать одно и то же нельзя: окно обещает ровно эту строку и показывает
её текстом.

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

Проверки: flattest сверяет, что заявка несёт цепочку и отдельный путь;
tests/imagecrop.sh проходит всю дорогу — делает картинку, собирает
секунду ролика и смотрит на точки готового кадра. На прежней сборке
картинка выходит во весь кадр, обе падают.
2026-10-16 15:42:49 +03:00
95d92a7582 Крест перехода там, где клипы не накладываются
На монтаже рисовался косой крест через целый клип, строка состояния
обещала переход, а наложения не было: ролик собирался верно. Крест уходил
сам после Ctrl+Z, после любого действия с отменой и после схлопывания.

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

Отмена и схлопывание лечили ровно потому, что пересортировывают списки.
Сборка всё это время была права: она идёт по границам и сортирует
дорожку сама.

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

Проверка tests/dragorder.sh тащит связку за звук с конца монтажа в
середину и читает порядок из сохранённого файла. На прежней сборке
дорожка картинки остаётся в порядке 0, 14, 7.991 — проверка падает.
2026-10-16 14:01:51 +03:00
b078700fc7 Прилипание сильнее кадровой сетки: наезда в семь миллисекунд больше нет
Клип прилипал к концу соседа, а потом округлялся к ближайшему кадру — и
уезжал с той самой границы, к которой только что прилип. Границы клипов
в монтаже лежат не на сетке: они приходят из исходников. Влево это наезд
в семь миллисекунд: ноль пикселей на экране, а в модели заказ на переход.
Человек ищет, откуда взялся кроссфейд там, где ничего не накладывается.

Замерено: дыра, раздвинутая ровно под клип, давала после перетаскивания
наезд 0.007383 с слева и дыру такого же размера справа.

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

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

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

Проверка tests/dropgap.sh, на прежней сборке падает.
2026-10-16 00:24:18 +03:00
6cc9f5e8a8 Прокрутка у кромки помнит зажатые клавиши
Тик повторяет движение мыши за человека. Shift при растягивании края
отменяет прилипание, и повторение с пустым набором клавиш заставляло край
прыгать между тиками: тик с прилипанием, рука без него.
2026-10-15 23:36:44 +03:00
d55fb1b808 Доки: вставка на курсор, прокрутка у кромки, тишина перед сборкой
Описание пополнено тремя абзацами о новом поведении и разделом о том,
как гонять проверки с окном: где взять файл доступа невидимого экрана и
почему якорю увеличения нужен экран шире 1280.

Лог сессии и утверждённый план положены в проект: файлы планов в
~/.claude/plans ротируются, а решения должны переживать сессию.
2026-10-15 23:34:05 +03:00
0fa9bb6130 Клип встаёт на курсор, монтаж едет следом, сборка ждёт конца правки
Три жалобы из настоящей работы над фильмом, и все про одно: положить
кусок туда, куда нужно, было нельзя.

Файл из списка падал в конец дорожки, стоило месту под ним оказаться
занятым, — а занято оно почти всегда: клип длиной в целый файл упирается
хвостом в то, что правее, даже когда начало легло в пустоту. Теперь
монтаж раздвигается: MakeRoomAt режет все дорожки в точке вставки и
сдвигает всё, что начинается с неё и правее, на длину нового клипа. Звук
и надписи едут вместе с картинкой, иначе синхрон рассыплется.

Точка вставки при этом округляется к кадровой сетке. Без этого вставка
давала наезд в пять миллисекунд: рез внутри раздвижки округляет время
сам, а клип клался на неокруглённый курсор. Отсюда и был «кроссфейд без
видимого перекрытия».

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

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

Проверки числами: раздвижка монтажа и прилипание хвостом. С окном:
insertat.sh, dragscroll.sh, genquiet.sh. Все три прогнаны и на прежней
сборке, где падают: клип в конце дорожки вместо курсора, 0.667 с вместо
4.238 с, сборка через 0.20 с вместо 1.62 с.
2026-10-15 23:33:58 +03:00
6c81fd0907 Проверки с окном не трогают чужой редактор и не врут о поломке
genrestart.sh закрывал все окна редактора разом, включая работу
пользователя на рабочем экране. Закрывает теперь только свои — те, что
живут на экране проверки.

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

zoomanchor.py не передавал XAUTHORITY своим командам: экран, поднятый
через xvfb-run, пускает только по своему файлу доступа.
2026-10-15 23:33:46 +03:00
3bfd8bc688 README: проверки на невидимом экране и полная таблица модулей
Четыре проверки, которые гоняют саму программу, собраны в одном месте с
припиской: каждую стоит прогонять и на прежней сборке, иначе она не
проверяет ничего. Названы монтажи, которые им нужны, и почему их нет в
репозитории.

В таблицу модулей дописаны десять, которых там не было: текст и его
замер, разметка для libass, окна ключа, перекодирования, сборки и «о
программе», страница текста со ссылками, запуск ffmpeg с ходом работы и
вшитые значки.
2026-10-01 16:35:59 +03:00
d75596bca3 Доля растёт ровно: строка «progress=continue» больше не обнуляет место
Показатель висел на пяти процентах, потом прыгал к семидесяти девяти,
потом сразу готово. Виноват не ffmpeg: замерено, что он отдаёт ход
безупречно ровно — блок каждые полсекунды, 7%, 14%, 20%, 27% и дальше
без единого скачка.

Блок заканчивается строкой «progress=continue», в которой места нет:
она сообщает только, что работа продолжается, и разбор честно оставляет
переданное число как было. Я передавал туда ноль, поэтому каждый блок
заканчивался обнулением доли. Показатель стоял и дёргался вверх лишь
тогда, когда опрос попадал между строкой со временем и этой.

Теперь отсчёт начинается с уже известного места — как это давно делает
сборка ролика. Проверено глазами на невидимом экране: шесть снимков
подряд через полторы секунды дают 54, 65, 74, 82, 91, 99 процентов,
полоса растёт вместе с числом.

Ловушку закрепляет проверка в tests/lfmcheck: «progress=continue» и
«progress=end» узнаются, но времени не трогают.
2026-10-01 16:24:59 +03:00
e8cb3cc392 Ручку затухания можно взять и во второй раз
Зона захвата совпадала с нарисованным квадратиком — девять точек на
девять. Пока затухание нулевое, ручка стоит в углу клипа и целиться есть
куда; стоит её сдвинуть, она висит посреди клипа сама по себе, и попасть
в неё почти нельзя.

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

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

Проверено протяжкой мыши на невидимом экране (tests/fadegrab.sh): первый
захват за угол даёт затухание 1.387 с, второй — с прицелом на пять точек
ниже и четыре в стороне от середины ручки — доводит до 2.261 с. На сборке
из прошлого коммита второй захват не делает ничего.
2026-10-01 16:13:37 +03:00
44c0a5de24 Показатель работы: число и полоса показывают одно и то же
Полоса ползла по догадке, а подпись показывала замер — и человек видел
полосу, заполненную на девять десятых, рядом с нулём процентов. Что в
этот момент происходит, по такой паре понять нельзя.

Теперь доля одна на обоих. Берётся она у самого ffmpeg: сборка участка с
затуханием идёт минуту и дольше, а «кусок 1 из 1» всё это время не
меняется, поэтому ffmpeg спрашивают ключом -progress, докуда он дошёл.
Пока он не ответил ни разу, полоса трогается с места на пару процентов и
там стоит — пустая полоса и есть правда о только что начатой работе.

Догадка заодно перестала закрывать промежуток до вехи целиком: предел —
девять десятых, остаток виден глазом. Проверка на это добавлена в
tests/progress.

Полоса в окне сборки была системной, и под gtk2 заполнялась ступенями по
восемь кусков на ширину. Теперь там та же своя полоса, что и внизу
главного окна, — заполняется сплошь. Чтобы она читалась из файла формы,
у неё опубликованы Anchors, Align и Visible: читатель формы берёт только
опубликованные свойства, и без этого окно падало при открытии.

Проверено глазами на невидимом экране: «Собираю наложение 1 из 1 — 2%»
при полосе в 2%, через четыре секунды 69% при полосе в 69%.
2026-10-01 15:50:10 +03:00
8d1cb9af5c Сведение слоёв распаковывает исходник видеокартой
Затухание в полторы-две минуты собиралось минутами, и всё это время
предпросмотр ждёт. Виноваты оказались не фильтры: на десяти секундах
2688x1512 цепочка со сведением стоит 13.5 с, а вовсе без фильтров —
12.7 с. Время уходит на разбор HEVC процессором.

Ключ -hwaccel cuda перед входом убирает почти всё: настоящее затухание
на семьдесят секунд собирается 18.3 с вместо 75.9 с, картинка бит в бит
та же (одинаковый md5 потока, 4196 кадров там и там).

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

Сборка ролика пока по-старому: там кусок с наложением идёт в общий
поток, и повторить его после отказа посреди работы нельзя — данные уже
ушли в трубу. Это отдельная задача.
2026-10-01 15:11:43 +03:00
d2a49343c3 Сборка вставки не начинается заново от каждой правки
Затухание в семьдесят секунд не собиралось никогда: сборка сведённого
куска шла полторы минуты, и любая правка в это время сбрасывала её на
ноль. В журнале это видно как «Расстановка изменилась» и тот же самый
запуск ffmpeg по кругу.

Причина — в вопросе, который задавался. «Нужна ли ещё эта работа»
проверялось по списку недостающего, а недостающее у нас — это то, чего
нет на диске. У куска, который делается прямо сейчас, файл уже есть:
ffmpeg создаёт его в первую же секунду. Кусок в список не попадал, ответ
был «не нужна», работа отменялась.

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

Проверено обеими сторонами (tests/genrestart.sh, на настоящем материале,
затухание 70 с): пять резов в стороне от затухания — один запуск и ни
одной отмены, было шесть запусков и десять отмен. Удалили всё — работа
прекращается за две секунды, как и прежде.
2026-10-01 00:47:28 +03:00
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
2160c33790 BACKLOG: кадрирование в окне и два видео рядом — по замеру
Про кадрирование обычного клипа было написано, что цепочка фильтров для
2688x1512 слишком дорога. Это память о другом замере: на деле 330 к/с
без фильтра против 214 с веткой, включаемой по времени, при нужных 60 —
запас трёхкратный. Заодно записан путь дешевле: mpv умеет обрезать и
увеличивать на выводе, силами видеокарты.

Про два видео рядом заведён свой раздел: граф сборки проверен на
настоящих файлах, и названы три вещи, которых не хватает. Главная —
клипу негде записать, какое место в кадре он занимает: масштаб сейчас
всегда равномерный, и полосу в половину кадра им не выразить.
2026-09-30 22:00:49 +03:00
d0ec869743 Масштаб таймлайна берётся от точки под мышкой
Ctrl с колесом должен оставлять на месте то, на что смотрит мышь, а
оставлял точку левее — ровно на левый край таймлайна. При мыши у левого
края опора и вовсе уходила за пределы окна.

Причина: MousePos у DoMouseWheel по описанию экранный, но под gtk2 в нём
уже клиентские координаты, и ScreenToClient переводил их второй раз.
Берём Mouse.CursorPos — он экранный в любой системе.

Замерено на невидимом экране: до правки мышь в 700, 1000 и 1300 давала
опору в 260, 560 и 860; после — ровно 700, 1000 и 1300. Проверка
оформлена в tests/zoomanchor.py и прогнана на обеих сборках: на прежней
она падает, на новой проходит.
2026-09-30 20:45:32 +03:00
4526f65fcc Записано, чего сборка потоком не даёт
Четыре оговорки с ценой каждой: продолжение стоит места вдвое, отступ
назад идёт до целого куска, MP4 продолжать нельзя вовсе, и потоком идёт
не всё. Все четыре известны заранее, а не вскроются через месяц.
2026-09-30 16:50:18 +03:00
f841ed79ec Честное предупреждение о контейнере и отметка недописанной сборки
У MP4 два неудобства, о которых человек узнавал поздно: прерванную
сборку в нём продолжить нельзя вовсе, а перекодированный стык точного
реза воспроизводится правильно не везде. Теперь об обоих говорится до
начала работы, одним окном с кнопками «Собрать в MKV», «Всё равно mp4»,
«Не собирать».

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

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

Ещё: на каждом стыке кусков приёмник писал «Packet corrupt», по паре
строк на кусок. Данные целы, но журнал забивался, и настоящую ошибку в
нём было не найти. Лечится ключом -mpegts_flags +initial_discontinuity
у отправителя: сверено по кадрам и по md5, результат тот же.
2026-09-30 16:48:31 +03:00
4522f0000a Продолжение прерванной сборки потоком — с недописанного файла
Потоком кэша кусков нет, и продолжать было не с чего. Но недописанный
файл сам по себе — уже собранная часть фильма: в нём видно, сколько
целых кадров успело записаться. Программа отступает до границы
последнего целого куска, переносит эту часть и досылает остаток.

Дописать в конец существующего MKV нельзя, поэтому продолжение пишется
в новый файл. MP4 продолжать нельзя вовсе: оглавление в конце, и
оборванный файл не открывается — об этом говорится прямо.

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

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

В nlvetool у render появились --cancel-after=<сек> и сочетание слов:
cache resume проверяет, что старый путь через кэш не сломался.
2026-09-30 16:37:28 +03:00
38f4b295b9 Сборка потоком: куски идут сразу в готовый файл, без кэша
Раньше каждый кусок монтажа вырезался в отдельный файл, и только потом
список этих файлов шёл на склейку. Кэш весил столько же, сколько готовый
фильм — замерено 110 ГБ на часе материала, — а диск писал всё дважды.

Теперь каждый кусок режется своим ffmpeg прямо в MPEG-TS на стандартный
вывод, все потоки подряд переливаются в один принимающий ffmpeg, а тот
пишет готовый файл. Место куску задаёт -output_ts_offset, считаемый в
кадрах от начала. На диск ложится только результат и звуковая дорожка.

Через кэш по-прежнему собирается то, что потоком не выходит: кодек, не
переносимый в MPEG-TS, и пересборка всего ролика под площадку.

Сверено на четырёх монтажах, включая настоящий материал с дрона
(HEVC 2688x1512, 55 Мбит/с, файлы с шестью потоками): картинка совпала
попиксельно, PSNR бесконечен на каждом кадре, длина и размер те же.
Сверка шла и с прошлым выпуском, а не только нового пути со старым.
На отрывке в 17.5 с: 14.2 с и 421 КБ на диске против 17.5 с и 152 МБ.

По дороге найдены две ловушки, обе записаны в README:
-avoid_negative_ts make_zero отменяет -output_ts_offset, а -fflags
+igndts у приёмника сминает кадры на стыках.
2026-09-30 16:12:00 +03:00
aba9bd57e4 Кнопки внизу: подсказка не перехватывает щелчок, щелчки не теряются
Две беды у всех кнопок нижней полосы.

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

Второй щелчок подряд виджетсет отдавал как двойной, и кнопка его не
видела: быстрая очередь щелчков срабатывала через раз. У кнопки убран
csDoubleClicks, а на случай, если двойной всё же дойдёт, он считается
за обычный.

Проверено: tests/lfmcheck, раздел «Кнопки нижней панели», и
tests/buttonclicks.sh мышью на невидимом экране — по всем шести
переключателям очереди из 1-5 щелчков отрабатываются полностью.
2026-09-30 15:44:29 +03:00
569d0382f7 Кадрирование показывает кадр из клипа, а не из середины файла
Окно кадрирования брало кадр на десятой части от начала исходного файла,
не глядя, какой клип правят. Клип обычно вырезан из середины долгой
съёмки, и в окне была совсем другая сцена: прицелиться увеличением было
нечем.

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

Проверено на съёмке с дрона: клип из 900-й секунды, окно показало кадр
именно оттуда (совпал с эталонным кадром на 900 с), раньше показывало
кадр на пятой секунде.
2026-09-30 12:05:44 +03:00
0ba3bd40a6 Огрызкам на резах задаётся битрейт проекта
Перекодированный кусочек от точки реза до опорного кадра шёл без ключа
битрейта, и NVENC брал своё умолчание. Замерено в готовом ролике
пользователя: 5.7-6.8 Мбит/с в огрызке против 54-60 в скопированном
материале рядом — мутное пятно на полсекунды.

Раньше это задевало только редкие точные резы, а теперь точны все: в том
ролике 98 кусков, то есть 98 таких пятен.

После правки на том же материале: огрызок 86.8 Мбит/с (потолок в полтора
битрейта проекта, для куска в 0.7 с с опорным кадром это нормально),
соседний скопированный 61.6. Сверка кадров и звука проходит.
2026-09-30 00:55:09 +03:00
6617e29514 Выделение по времени, рез по краям промежутка, курсор идёт за резом
Режимов выделения стало два, переключаются клавишей D и кнопкой внизу,
режим показан её значком.

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

Курсор теперь идёт за резом: после S встаёт на место реза (в режиме по
времени — на начало промежутка), после удаления куска — на место стыка,
после схлопывания дыры — туда же. Раньше в это место приходилось попадать
мышью заново.

Рез кладётся на кадровую сетку: между кадрами времени нет, и рез на доле
кадра оставлял бы в монтаже время, которого не бывает.

Выделение рамкой требует настоящего перекрытия, а не касания краями:
сосед, кончающийся ровно на краю рамки, попадал в выделение из-за разницы
в последнем знаке дробей.

Кнопка журнала и строка состояния сдвинуты вправо: переключатель выделения
встал в один ряд с прилипанием и схлопыванием.

Значки — icons8, набор ios-glyphs, авторство дописано в attribution.txt.
Набора «ios26» на их раздаче нет (404), взят ближайший по виду к нынешним.

Проверки: рез по курсору и по краям промежутка, кадровая сетка, выделение
середины, курсор после удаления и после схлопывания.
2026-09-29 23:58:30 +03:00
37787ce96c Починка проекта: клипы на кадровую сетку, пункт в меню
Меню «Проект» → «Проверить и починить проект...». Показывает найденное и
чинит только по согласию, отменяется через Ctrl+Z.

Ищутся клипы мимо кадровой сетки, клипы на дорожках чужого вида и
повторяющиеся имена дорожек. Первое — наследство: в старых проектах
времена записаны как попало (2.457599 с при 59.94 к/с — это 147.31 кадра),
и пока монтаж просит доли кадра, предпросмотр и сборка округляют их
каждый по-своему. Сдвиг при починке не больше полкадра.

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

Проверено на копии настоящего проекта: 82 клипа, после починки мимо сетки
ни одного, клипы остались встык, общая длина изменилась на 0.028 с за два
часа; Ctrl+Z возвращает как было. Плюс проверка в lfmcheck, включая клип
короче кадра — он не должен схлопнуться в ничто.
2026-09-16 20:39:33 +03:00
019d016db9 Звук больше не отстаёт от картинки
Рез всегда точный. Раньше начало куска притягивалось к ближайшему
опорному кадру, а звук брался из непритянутой точки: по журналам сборки
средняя притяжка 0.24 с, худшая 0.99 с, и на длинном куске этот сдвиг
держится все его минуты. Плата за точность — доли секунды перекодирования
на рез. Второй вид реза (Shift+S) стал тем же самым и убран.

Разбор заголовка MP4 не учитывал список правок (elst): метки опорных
кадров уезжали на задержку показа, на пробе два кадра. Сверка быстрого
пути с ffprobe теперь совпадает точно, в том числе на записи с B-кадрами.

Куску заказывается точное число кадров, а не только время: при
копировании ffmpeg отмеряет конец по времени декодирования, и у записи с
B-кадрами кусок выходил длиннее.

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

Звука в кусках картинки больше нет: он не используется, а в MPEG-TS ещё и
сбивает выравнивание склейки на 36 мс.

Границы кусков ложатся на кадровую сетку: картинка выходит целым числом
кадров, звук набирается до отсчёта, и доли кадра разводили их в стороны.

Разогрев кодировщика звука компенсируется: сжатый AAC начинается со
служебных отсчётов, MP4 помечает их пропускаемыми, Matroska — нет, и звук
ехал на 21.3 мс позже. Величина меряется пробным сжатием.

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

В журнал сборки добавлена проверка синхронности: сколько кадров вышло и
сколько просил монтаж, с вердиктом и худшей частью.

Замер (tests/syncprobe.sh, исходник со вспышкой и щелчком на каждой
секунде): было до 0.6 с и росло по ходу ролика, стало 0.02-0.04 с без
накопления при точности измерения 0.017 с.
2026-09-16 18:28:29 +03:00
18e55d466e Работа не теряется: автосохранение, видимое сохранение, запасной файл
Сохранение теперь отвечает в строке состояния: «Проект сохранён: имя,
время». Раньше об этом знал только журнал, а он по умолчанию закрыт —
нажал Ctrl+S и не знаешь, дошло ли до файла.

Проект пишется во временный файл рядом и подставляется целиком; прежний
остаётся как .bak. Оборванная запись больше не может оставить огрызок
вместо проекта.

Автосохранение: пока есть несохранённое, раз в полминуты рядом с
проектом пишется копия .autosave. При открытии программа сравнивает её
время с временем проекта и, если копия новее, показывает оба времени и
предлагает её открыть. После сохранения проекта копия убирается.

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

Клавиша \ подтягивает окно к курсору и ставит его посередине: её жмут
после реза или выделения. Переключатель «курсор посередине» остался
кнопкой с целью.
2026-09-14 16:06:40 +03:00
86c28a3308 Выделение областью, рез всех дорожек, курсор не улетает
Рамка выделения: протяжка по пустому месту дорожек обтягивает клипы,
Delete убирает всё, что она задела. Щелчок без движения по-прежнему
ставит курсор.

Рез по курсору (S) режет все дорожки, а не ту, что под указателем мыши:
стоило указателю оказаться над пустой дорожкой, и клавиша молча не
делала ничего. Теперь рез отвечает числом разрезанных клипов.

Курсор после правки монтажа улетал в конец: при перезагрузке списка
кусков mpv сбрасывает отсчёт времени, программа ждала перемотки, не
дожидалась и подтягивала курсор к плееру. На паузе курсор теперь
остаётся там, куда его поставил человек. Это и делало Ctrl+Shift+R
неудобным: после каждого схлопывания приходилось целиться заново.

Схлопывание дыры ищет её с допуском и по всем дорожкам, а не только под
мышью, и называет дорожку в строке состояния.

Ответ на команду держится в строке состояния несколько секунд: раньше
его через долю секунды затирало сообщение о пересборке предпросмотра.

Проверки: рамка, рез всех дорожек, допуск при схлопывании (lfmcheck).
2026-09-14 15:27:43 +03:00
00af5e1eec Отмена генерации не ошибка, длинная тишина набирается повторами
Отмену вставок просили мы сами, когда правка сделала работу ненужной, а
журнал сообщал «Не удалось подготовить вставки: Отменено» — неправда там,
где всё шло по плану. Теперь отмена докладывается как отмена и сразу
планирует пересборку предпросмотра, а не ждёт таймера.

Вчерашнее дробление дыр не дошло до звуковых дорожек: они уплощаются
отдельной функцией. Кусок тишины в три минуты ссылался на минутный файл, и
плеер жаловался «uses 192.5 seconds, but file has only 60». Теперь длинная
тишина набирается повторами, а одинаковые файлы не заказываются дважды.

Проверено живьём на материале 2688x1512: отмена ловится, обе строки в
журнале верные, предупреждений о коротких файлах ноль. Проверка 15 в
flattest следит за дроблением тишины.
2026-09-12 00:51:19 +03:00
8258de7145 Логи сессии и бэклог: прокрутка, копирование клипов, непроверенная отмена 2026-09-11 21:19:43 +03:00
ab719dfd1e Копирование клипов: Ctrl+C и Ctrl+V
Отбивку или текстовый блок проще размножить копией, чем заводить заново
через меню и настраивать оформление с нуля.

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

Дорожка выбирается сама: сначала та, откуда копировали, если это время на
ней свободно; потом любая подходящая по виду; в крайнем случае заводится
новая. Наложить копию на соседа по дорожке нельзя — это означало бы
переход, которого никто не заказывал.

В модели появился TClip.CopyAllFrom: полная копия, кроме места на
монтаже. Проверка в lfmcheck перебирает перенесённые свойства и отдельно
убеждается, что место и связка не переносятся.
2026-09-11 21:14:52 +03:00
407eb02f2d Прокрутка во время воспроизведения больше не отскакивает
При выключенном «курсоре посередине» окно всё равно подтягивалось к
курсору, стоило тому выйти за край видимой части. Со стороны это выглядело
так: Shift с колесом, первый поворот прокручивает, второй возвращает
обратно. Человек отматывает осознанно, и возвращать его силой нельзя.

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

Проверено на невидимом экране при идущем воспроизведении: оба поворота
колеса двигают линейку (1651 и 1581 изменившихся точек), и к исходному
виду она не возвращается.
2026-09-11 20:44:32 +03:00
939184fce7 Чёрные вставки стоят копейки, текст режет кусок
Дыра в сорок минут требовала двухчасового чёрного файла: лестница готовых
длин доходила до восьми часов, и NVENC кодировал такое минутами. Отсюда
«Делаю чёрную вставку 1 из 3», которое не кончается. Теперь длины две, 15
и 60 секунд, длинная дыра набирается повторами минутного файла, а само
чёрное кодируется мегабитом вместо полусотни.

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

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

Ctrl+Shift+R работает без мыши: дыра ищется на активной дорожке, если
указатель не над дорожками, и команда отвечает в строке состояния, а не
молчит.

Вжигание текста режет кусок на части и пересобирает только середину.
Надпись в тридцать секунд внутри сорокаминутного куска стоила сорока
минут пересборки. Часть после надписи помечается точным резом, иначе
копия пошла бы от опорного кадра и картинка сдвинулась бы.

Проверки: flattest 13 и 14, схлопывание без мыши в lfmcheck, сборка с
надписью внутри длинного куска — 1.000000 с пересборки вместо 6.
2026-09-11 19:35:26 +03:00
82929a8d5b В репозитории только исходники
Из истории убраны собранный ролик, скачанные зависимости под Windows,
отладочные символы macOS, пробники замеров, изначальная постановка и
рабочие бумаги — планы с логами сессий. Всё это осталось на диске, но
больше не отслеживается и закрыто .gitignore: они попадали в коммиты
через git add -A по корню.
2026-09-02 02:08:33 +03:00
1ed479739d Значок цели: исходник и запись в генераторе значков 2026-09-02 02:06:05 +03:00
45777bbdbb Ролик больше не хранится на диске дважды
Картинка собиралась в промежуточный файл, а потом сшивалась со звуком в
конечный. На часовом ролике это 91 ГБ в кэше плюс 91 ГБ рядом и лишний
полный проход копирования — ради того, чтобы приписать звуковую дорожку.

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

Куски после удачной сборки удаляются, и в журнале сказано, сколько места
освободилось: на часовой съёмке их набирается больше сотни гигабайт, а
нужны они только чтобы продолжить прерванную сборку. После неудачной
сборки они остаются — с них и продолжают. Настройка keep_parts оставляет
их всегда.
2026-08-31 17:39:40 +03:00
a28955fa2e Свойства клипа, порядок дорожек, оценка времени и продолжение сборки
Копирование оформления: Ctrl+Shift+C берёт с выделенного клипа
кадрирование, поворот, увеличение, смещение, прозрачность, ключ,
затухания и громкость, Ctrl+Shift+V применяет их ко всем выделенным. Вид
клипа и текст не переносятся: свойства копируют между разными клипами.

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

Окно сборки показывает, сколько прошло и сколько примерно осталось.
Оценка по пройденной доле; скорость на деле меняется, поэтому «примерно»
и пересчёт на каждом шаге.

Прерванная сборка продолжается с готовых кусков. Каждый доведённый до
конца кусок помечается в списке рядом с ними: одного наличия файла мало —
сборку могли прервать посреди записи. Первая строка списка — отпечаток
плана; не совпал, значит монтаж менялся, и всё собирается заново.
Проверено: четыре куска взяты готовыми, два пересобраны, склейка не
потеряла ни одного кадра; при изменённом монтаже готовые куски отвергнуты.
2026-08-31 14:55:19 +03:00
0bbff345ba Оверлей по порядку дорожек, текст в окне, имена дорожек
Миникарта была видна в окне, но не в ролике. Предпросмотр рисовал оверлей
поверх всего, не глядя на порядок дорожек, а сборка живёт по правилу
«верхний клип побеждает целиком»: фотография лежала выше оверлея и в
ролике его закрывала. Теперь окно считает так же — оверлей показывается
только там, где его не закрывает сплошной клип с дорожки выше, а закрытый
посередине разбивается на несколько окон показа.

Текст не появлялся в окне. Разметка лежит в файле с одним именем на весь
проект, а плеер сравнивал имена: имя прежнее — перечитывать нечего.
Правка доходила до окна только вместе с перезагрузкой списка кусков.
Теперь сравнивается сама разметка, и при изменении файл перечитывается.
Отдельно проверено, что цепочка lavfi-complex субтитрам не мешает.

Две дорожки Т2. Имя новой дорожке давалось по счёту дорожек своего вида
плюс единица, и после удаления средней счёт совпадал с занятым именем.
Имя подбирается свободное, а повторы из старых проектов разводятся при
чтении.

Проверки 11 и 12 в nlvetool flattest.
2026-08-31 12:41:26 +03:00
59c778d2f6 Текст вжигается и в фотографию; дорожки и полоса участка
Вжигание не доходило до сгенерированных вставок. Картинки и чёрное
отбирались первой же веткой сборки — до проверки на пересборку — и
копировались целиком вместе с отметкой о разметке. Галка вжигания стояла,
кусок в журнале был помечен «с текстом», а в ролике надписи не было.
Причину показал журнал сборки рядом с файлом: помечено «пересобирается»,
а команда — копирование.

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

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

Заголовок дорожки: правый щелчок открывает меню — поднять, опустить,
удалить (с клипами — с подтверждением). Заголовок можно и потащить:
порядок дорожек есть порядок перекрытия, и менять его перетаскиванием
привычнее, чем через меню.
2026-08-31 12:01:12 +03:00
07aee86631 Клип не попадает на дорожку чужого вида
В живом проекте фотография оказалась на текстовой дорожке, а надпись — на
дорожке картинки. Уплощение обходит дорожки по видам, и такой клип не
видит ни сборка, ни предпросмотр: на монтаже он нарисован, в готовом
ролике его нет, и ни одной жалобы по дороге. Именно это и было причиной
пропавших фотографии и текста, а не ошибка со стоп-кадром.

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

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

Проверка 10 в nlvetool flattest: картинка на текстовой дорожке в
уплощение не попадает, после переноса попадает и остаётся на своём месте.
2026-08-31 11:12:05 +03:00
96672341d2 Уголки участка, курсор посередине и журнал сборки рядом с роликом
Отметки участка стали видимыми уголками на линейке — жёлтые треугольники
по краям, за них можно тянуть. Клавишами это выходило долго: поставил,
посмотрел, промахнулся, ставь заново. Край прилипает к границам клипов,
как и курсор, и края не пропускаются друг за друга.

Клавиша \ и кнопка с целью переключают, держать ли курсор посередине
монтажа при воспроизведении. Раньше монтаж ехал под курсором всегда, а
это мешает, когда разглядываешь конкретное место.

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

Журнал сборки пишется рядом с готовым файлом и под тем же именем. Общий
журнал программы перезаписывается следующим запуском, а разбираться,
почему в ролике не то, приходится потом. В журнале: время, проект,
участок, кадр и битрейт, что с текстом, и полный список кусков — с
пометками, где слои, где текст и что пересобирается. Строка пишется
сразу, чтобы после падения осталась последняя.
2026-08-31 11:00:30 +03:00
71381bb774 Участок сборки, качество пересборки и пропавшие куски
Отмеченный участок. Клавиши I и O ставят начало и конец по курсору,
полоса под линейкой показывает отмеченное, сборка собирает только его.
Без этого проверить правку на длинном монтаже нельзя: каждая проверка
стоит столько же, сколько идёт весь ролик. Отметки живут в проекте.
Разметка текста при этом берётся с начала участка, иначе надписи легли бы
со сдвигом.

Фотография пропадала из ролика. Кусок с наложением подаёт слои в ffmpeg
как есть, а одиночная картинка даёт ровно один кадр: кусок в три секунды
получался длиной 0.016667 с. Теперь у слоя есть признак «это картинка», и
она повторяется ключом -loop с частотой кадров проекта.

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

Качество пересобранных кусков. Битрейт не задавался вовсе, и кодировщик
брал своё значение по умолчанию: 5.9 Мбит/с там, где исходник 56. Теперь
пересборка целится в наибольший битрейт среди файлов проекта, с потолком
в полтора раза выше и буфером вдвое. Тем же битрейтом делаются вставки из
фотографий.

Проверки: обрезка списка кусков по участку (nlvetool flattest, 9),
сборка фотографии под наложением и вжигание текста поверх наложения
(nlvetool render ... burn).
2026-08-31 10:37:25 +03:00
d9bbffcaac Записан разрыв: предпросмотр не показывает кадрирование обычного клипа 2026-08-31 01:15:42 +03:00
5bd4e822d9 Рез больше не теряет настройки клипа
После разреза хвост оставался без цветового ключа: перенос настроек был
написан перечислением полей, а ключ появился позже и в перечень не попал.
Хвост переставал быть наложением, становился обычным победителем и
закрывал собой всё, что ниже — вместо компаса в углу окно показывало
пурпурную плашку во весь кадр.

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

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

Проекты, разрезанные прежней сборкой, правка задним числом не чинит:
у хвоста ключ надо включить заново.
2026-08-31 01:08:02 +03:00
d098f1621e Ключ и прозрачность видно прямо в предпросмотре
Оверлей показывался как есть, со своим фоном: чтобы увидеть, что выйдет
после сборки, приходилось собирать. Теперь выбитый цвет и приглушение
считаются в той же цепочке плеера, на лету.

Строки фильтров стали общими со сборкой (ColorKeyFilter, OpacityFilter
в uTransform): окно и готовый ролик больше не могут разойтись по тому,
как записан цвет или порог.

Переключатель в меню «Вид», состояние переживает перезапуск. Замер на
2688x1512, 600 кадров: основа 2.07 с, с наложением 2.43 с, с ключом и
прозрачностью 2.66 с — вчетверо быстрее реального времени, но на слабой
машине это заметнее, поэтому выключить можно.

В бэклог записано окно настроек: переключателей, которые стоят машинного
времени, набралось много, и живут они кто где — кнопками внизу, в меню,
а выбор кодировщика вообще нигде.
2026-08-31 00:46:58 +03:00
4c422ef57d Курсор прилипает к границам клипов
Курсор воспроизведения по щелчку вставал ровно туда, куда попала мышь.
В стык двух кусков так не попасть: на общем плане одна точка экрана —
это секунды материала, а ставят курсор чаще всего именно на стык.

Теперь он притягивается к границам клипов на любой дорожке и к началу
монтажа. Работает и при щелчке по клипу, и по линейке, и по пустому
месту, и при протяжке. Shift меняет решение на противоположное — как у
прилипания клипов.

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

Расчёт открыт наружу и проверяется числами: семь проверок в lfmcheck,
от «стык рядом — притянуло» до «выключено — не притягивает».
2026-08-31 00:32:44 +03:00
fb6b60bc3f Свой тип файла для проектов: *.nlve больше не текст
Внутри проект — обычный JSON, и система считала его просто текстом:
открывала редактором и рисовала значок текстового файла.

Теперь у него свой тип application/x-nlve-project, свой значок (лист с
загнутым углом и знаком программы) и открытие двойным щелчком. Тип
объявлен наследником application/json, но не простого текста — иначе
редактор снова оказался бы программой по умолчанию.

Всё, что нужно для встраивания в рабочий стол, лежит в packaging и
ставится скриптом tools/install-desktop.sh в домашний каталог, без прав
администратора. Раньше пункт меню и значки существовали только на одной
машине и нигде не были записаны.
2026-08-31 00:13:50 +03:00
acb921d5f7 Цветовой ключ и живое наложение в предпросмотре
Клипу задаётся цвет, который при сборке становится прозрачным. Окно
ключа показывает кадр: цвет берётся щелчком по нему, выбитое показано
клеткой, допуск и смягчение края — ползунками. Открывается из окна
кадрирования и из меню «Правка», на монтаже клип помечен квадратиком
выбиваемого цвета.

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

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

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

Проверки форм теперь создают каждое окно из файла формы: элемент,
забытый в классе, вскрывается на сборке, а не при открытии окна.
2026-08-31 00:10:28 +03:00
1e28dd098b Схлопывание при удалении, разбор внутренних ошибок, дорожки по номерам
Схлопывание при удалении. При включённом автосхлопывании удаление куска
сдвигает всё, что правее, влево до первого касания — дыра не остаётся, и
сборке не приходится заполнять её чернотой.

Сдвиг считается по всем дорожкам сразу, а не по каждой отдельно: иначе
развалилось бы выверенное соответствие картинки и звука. Насколько можно
сдвинуть, решает та дорожка, где запас меньше всего. Дыра не обязана быть
пустой везде: клип, который её перекрывает, никуда не едет, и запас на
его дорожке считается от его конца, поэтому сдвиг сам останавливается там,
где упёрся.

Проверено: клип 0..4 с парным звуком разрезан на 2 с, удалён первый
кусок. Хвост уехал в ноль, следующий клип встал вплотную, дыры нет.

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

Звуковые дорожки предпросмотра хранятся номерами, а не указателями.
Указатели были ловушкой: отмена и открытие проекта пересоздают все
дорожки, а список продолжал показывать на освобождённую память —
и обращаются к нему на каждое обновление времени, то есть десятки раз в
секунду.
2026-08-30 21:59:26 +03:00