diff --git a/README.md b/README.md index 31073c2..9fd055c 100644 --- a/README.md +++ b/README.md @@ -1062,7 +1062,7 @@ Wine с новой библиотекой не грузилось ничего. уход выглядит как накапливающийся рассинхрон, которого нет. На это уже попались один раз. -Ещё десять проверок гоняют саму программу на невидимом экране +Ещё одиннадцать проверок гоняют саму программу на невидимом экране (`Xvfb :99`). Рабочий экран они не занимают: ``` @@ -1076,6 +1076,7 @@ Wine с новой библиотекой не грузилось ничего. ./tests/dropgap.sh [<путь к nlve>] клип садится в дыру без наезда ./tests/dragorder.sh [<путь к nlve>] связка переехала — порядок цел ./tests/pickcycle.sh [<путь к nlve>] щелчок перебирает наехавшие клипы +./tests/cropdialog.sh [<путь к nlve>] окно кадрирования показывает кадр ``` Отдельно от них `tests/imagecrop.sh` — сквозная, без окна: делает @@ -1085,7 +1086,11 @@ Wine с новой библиотекой не грузилось ничего. а не поля. Ей нужны `tests/nlvetool` (`./build.sh test`), ffmpeg и python с PIL. -Последним восьми нужен монтаж в `test/поток/`: `длинный-фейд.nlve` — один +`cropdialog.sh` строит свой монтаж сам, но ему нужна настоящая съёмка: +кадр для окна берётся из файла. Путь задаётся переменной +`NLVE_CROP_SOURCE`. + +Остальным нужен монтаж в `test/поток/`: `длинный-фейд.nlve` — один клип с затуханием секунд на семьдесят (такой кусок сводится около полутора минут, и всё это время человек продолжает работать), `пара.nlve` — два клипа без затуханий. Путь к первому задаётся @@ -1102,7 +1107,7 @@ xdotool не видит ни одного окна и проверка «про экран шире: `Xvfb :98 -screen 0 1600x1000x24` и `ЭКРАН=:98`. Каждую из них стоит прогонять и на прежней сборке: проверка, которая -проходит везде, не проверяет ничего. Все десять на сборке до своей правки +проходит везде, не проверяет ничего. Все одиннадцать на сборке до своей правки падают. Замерено: клип у кромки уезжает на 0.7 с против 4.2 с, файл из списка падает в конец дорожки вместо курсора, сборка начинается через 0.2 с вместо 1.6 с, клип в дыру садится с наездом 0.007383 с, дорожка diff --git a/src/uPanCropForm.pas b/src/uPanCropForm.pas index b251ca3..c834eb0 100644 --- a/src/uPanCropForm.pas +++ b/src/uPanCropForm.pas @@ -247,6 +247,15 @@ begin FTransform := ATransform; FPreviewFile := APreviewFile; + { Кадр пишется в кэш проекта, а его может ещё не быть: кэш заводится + при первой сборке вставок, а кадрирование открывают и раньше. Тогда + ffmpeg падал с «No such file or directory», и окно показывало «Не + удалось получить кадр» с цепочкой фильтров — выглядело так, будто + дело в самой цепочке. } + if (FPreviewFile <> '') and + (not ForceDirectories(ExtractFilePath(FPreviewFile))) then + FPreviewFile := GetTempFileName; + lblSource.Caption := Format('%s: %dx%d → кадр проекта %dx%d', [ExtractFileName(APath), AInfo.Width, AInfo.Height, ADstWidth, ADstHeight]); diff --git a/tests/cropdialog.sh b/tests/cropdialog.sh new file mode 100755 index 0000000..fef28e6 --- /dev/null +++ b/tests/cropdialog.sh @@ -0,0 +1,123 @@ +#!/bin/sh +# Окно кадрирования показывает кадр и в проекте, где кэша ещё нет. +# +# Кадр для окна пишется в кэш проекта, а кэш заводится при первой сборке +# вставок. Кадрирование открывают и раньше — тогда ffmpeg падал с «No +# such file or directory», а окно писало «Не удалось получить кадр» и +# показывало цепочку фильтров. Выглядело так, будто дело в цепочке, +# хотя дело было в отсутствующей папке. +# +# Проверяется так: проект без папки кэша, щелчок по кнопке кадрирования +# на клипе, затем смотрим, появился ли файл кадра. Появился — окну было +# что показать. +# +# Нужен настоящий файл съёмки: кадр берётся из него. Путь задаётся +# переменной NLVE_CROP_SOURCE. +# +# Запуск (экран :99 поднят): +# tests/cropdialog.sh [<путь к nlve>] +set -e +cd "$(dirname "$0")/.." +BIN=${1:-$PWD/nlve} +DISP=${NLVE_DISPLAY:-:99} +SRC=${NLVE_CROP_SOURCE:-/mnt/02F6E7F6F6E7E7BD/writable2/kamenolomni2/DJI_20261010143437_0044_D.MP4} +WORK=$PWD/test/кадр +PROJ=$WORK/проверка.nlve + +[ -f "$SRC" ] || { echo "нет съёмки $SRC — задай NLVE_CROP_SOURCE"; exit 2; } + +export DISPLAY=$DISP +reachable() { timeout 5 xdotool getdisplaygeometry >/dev/null 2>&1; } +if ! reachable; then + for p in $(pgrep -x Xvfb); do + A=$(tr '\0' '\n' < /proc/$p/cmdline | grep -A1 -x -- -auth | tail -1) + [ -f "$A" ] || continue + XAUTHORITY=$A; export XAUTHORITY + reachable && break + done +fi +reachable || + { echo "нет доступа к экрану $DISP: подними его (xvfb-run) и повтори"; exit 2; } + +rm -rf "$WORK" +mkdir -p "$WORK" +python3 - "$SRC" "$PROJ" <<'PY' +import json, sys +исходник, куда = sys.argv[1], sys.argv[2] +инфо = {'valid': True, 'kind': 'video', 'has_video': True, + 'video_codec': 'hevc', 'width': 2688, 'height': 1512, + 'fps_num': 60000, 'fps_den': 1001, 'pix_fmt': 'yuv420p', + 'duration': 2466.0, 'has_audio': True, 'audio_codec': 'aac', + 'sample_rate': 48000, 'channels': 2} +json.dump({ + 'version': 1, 'next_id': 20, + 'master': dict(инфо, video_bitrate=55000000), + 'pool': [{'id': 'm1', 'path': исходник, 'normalized_path': '', + 'info': инфо}], + 'tracks': [ + {'id': 't1', 'name': 'V1', 'kind': 'video', 'clips': [ + {'id': 'c1', 'media': 'm1', 'kind': 'video', 'src_in': 447.0, + 'tl_start': 0.0, 'duration': 20.0, 'edge_in': 'snap', + 'edge_out': 'snap', 'group': '', 'volume': 1.0, + 'opacity': 1.0, 'fade_in': 0.0, 'fade_out': 0.0, + # Увеличение со смещением: цепочка выходит с crop, как в + # разобранном случае. + 'transform': {'fit': 'fit', 'rotation': 0, 'flip_h': False, + 'flip_v': False, 'zoom': 1.98, + 'offset_x': 0.49, 'offset_y': -0.49}, + 'text': ''}]}, + {'id': 't2', 'name': 'A1', 'kind': 'audio', 'clips': []}], + 'settings': {} +}, open(куда, 'w'), ensure_ascii=False) +print(' проект на 20 секунд, увеличение 198%, папки кэша нет') +PY + +for p in $(pgrep -x nlve); do + { tr "\0" "\n" < /proc/$p/environ; } 2>/dev/null | grep -qx "DISPLAY=$DISP" && kill $p +done +sleep 1 +SP=$WORK/профиль +mkdir -p "$SP" +XDG_CONFIG_HOME=$SP XDG_CACHE_HOME=$SP XDG_DATA_HOME=$SP \ + setsid "$BIN" "$PROJ" >/dev/null 2>&1 < /dev/null & +sleep 18 + +X="timeout 8 xdotool" +WID= +for w in $($X search --name "проверка.nlve" 2>/dev/null); do + xwininfo -id "$w" 2>/dev/null | grep -q IsViewable && { WID=$w; break; } +done +[ -n "$WID" ] || { echo "живое окно редактора не найдено"; exit 2; } +$X windowmove "$WID" 0 0 windowsize "$WID" 1270 990 +sleep 3 + +# Папку кэша убираем прямо перед открытием окна. Иначе её успевает +# создать заготовка чёрной вставки, которая делается при открытии +# проекта, и проверка меряет не то: нужен именно случай, когда к моменту +# открытия кадрирования папки нет. +rm -rf "$WORK/проверка.nlve-cache" + +# Кнопка кадрирования — квадратик в правом нижнем углу клипа. Клип занят +# всю ширину окна, поэтому кнопка у правого края дорожки. +$X mousemove 1257 531 click 1 +sleep 7 + +DLG= +for w in $($X search --name "Кадрирование" 2>/dev/null); do + xwininfo -id "$w" 2>/dev/null | grep -q IsViewable && { DLG=$w; break; } +done + +SHOT=$WORK/проверка.nlve-cache/pancrop.png +if [ -f "$SHOT" ]; then + echo " ok: кадр получен ($(stat -c %s "$SHOT") байт), папка кэша создана" + RC=0 +else + echo " ПЛОХО: кадра нет — окну нечего показать" + [ -n "$DLG" ] || echo " (окно кадрирования вообще не открылось)" + RC=1 +fi + +for p in $(pgrep -x nlve); do + { tr "\0" "\n" < /proc/$p/environ; } 2>/dev/null | grep -qx "DISPLAY=$DISP" && kill $p +done +exit $RC