Три жалобы из настоящей работы над фильмом, и все про одно: положить кусок туда, куда нужно, было нельзя. Файл из списка падал в конец дорожки, стоило месту под ним оказаться занятым, — а занято оно почти всегда: клип длиной в целый файл упирается хвостом в то, что правее, даже когда начало легло в пустоту. Теперь монтаж раздвигается: MakeRoomAt режет все дорожки в точке вставки и сдвигает всё, что начинается с неё и правее, на длину нового клипа. Звук и надписи едут вместе с картинкой, иначе синхрон рассыплется. Точка вставки при этом округляется к кадровой сетке. Без этого вставка давала наезд в пять миллисекунд: рез внутри раздвижки округляет время сам, а клип клался на неокруглённый курсор. Отсюда и был «кроссфейд без видимого перекрытия». При перетаскивании у кромки окна монтаж прокручивается сам: иначе при большом увеличении кусок упирается в край, и переносить его приходится в несколько приёмов. Прилипание заодно считается и по концу клипа — иначе клип встаёт началом в дыру, а хвостом на соседа, и это снова наезд. Тяжёлая сборка больше не начинается с первым движением: список кусков пересобирается сразу, а ffmpeg запускается, когда монтаж постоял тихо полторы секунды и клип никто не держит мышью. Сам наезд перестал быть сюрпризом — строка состояния называет дорожку, величину и клипы. Проверки числами: раздвижка монтажа и прилипание хвостом. С окном: insertat.sh, dragscroll.sh, genquiet.sh. Все три прогнаны и на прежней сборке, где падают: клип в конце дорожки вместо курсора, 0.667 с вместо 4.238 с, сборка через 0.20 с вместо 1.62 с.
143 lines
6.3 KiB
Bash
Executable file
143 lines
6.3 KiB
Bash
Executable file
#!/bin/sh
|
||
# Монтаж едет следом, пока тащишь клип у кромки окна.
|
||
#
|
||
# При большом увеличении видно секунды, а двигать кусок надо на минуты.
|
||
# Если монтаж не прокручивается, клип упирается в край окна и дальше не
|
||
# идёт: приходится отпускать, прокручивать, брать снова — и так десятки
|
||
# раз.
|
||
#
|
||
# Проверяется так: монтаж из одного клипа, сильное увеличение, клип
|
||
# тащится к правому краю и там удерживается на месте. Рука стоит, значит
|
||
# двигать может только прокрутка. Результат читается из сохранённого
|
||
# проекта, а не с картинки.
|
||
#
|
||
# Запуск (экран :99 поднят):
|
||
# tests/dragscroll.sh [<путь к nlve>]
|
||
set -e
|
||
cd "$(dirname "$0")/.."
|
||
BIN=${1:-$PWD/nlve}
|
||
DISP=${NLVE_DISPLAY:-:99}
|
||
SRC=$PWD/test/поток/пара.nlve
|
||
PROJ=$PWD/test/поток/прокрутка.nlve
|
||
|
||
[ -f "$SRC" ] || { echo "нет монтажа $SRC"; exit 2; }
|
||
|
||
# Невидимый экран поднят через xvfb-run, у него свой файл доступа, а в
|
||
# окружении обычно лежит файл рабочего экрана. С чужим файлом xdotool не
|
||
# видит ни одного окна, и проверка «проходит» вслепую, ничего не проверив.
|
||
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; }
|
||
|
||
# Монтаж из одного клипа: второй убран, чтобы перетаскивание ни на кого
|
||
# не наезжало и не заказывало переход.
|
||
python3 - "$SRC" "$PROJ" <<'PY'
|
||
import json, sys
|
||
d = json.load(open(sys.argv[1]))
|
||
keep = None
|
||
for t in d['tracks']:
|
||
for c in t['clips']:
|
||
if c['kind'] == 'video' and c['tl_start'] < 0.001:
|
||
keep = c.get('group')
|
||
for t in d['tracks']:
|
||
t['clips'] = [c for c in t['clips'] if c.get('group') == keep]
|
||
json.dump(d, open(sys.argv[2], 'w'), ensure_ascii=False)
|
||
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
|
||
rm -rf test/поток/профиль-прокрутка
|
||
mkdir -p test/поток/профиль-прокрутка
|
||
rm -f "$PROJ.autosave"
|
||
SP=$PWD/test/поток/профиль-прокрутка
|
||
XDG_CONFIG_HOME=$SP XDG_CACHE_HOME=$SP XDG_DATA_HOME=$SP DISPLAY=$DISP \
|
||
setsid "$BIN" "$PROJ" >/dev/null 2>&1 < /dev/null &
|
||
sleep 14
|
||
|
||
X="timeout 8 xdotool"
|
||
# Окно ищем по имени монтажа и проверяем, что оно на экране. По одному
|
||
# «nlve» находятся и обломки прошлых запусков: они невидимы, нажатия в
|
||
# них уходят в никуда, и проверка молча показывает «ничего не двинулось».
|
||
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 2
|
||
|
||
start() {
|
||
$X key ctrl+s
|
||
sleep 2
|
||
python3 -c "
|
||
import json
|
||
d = json.load(open('$PROJ'))
|
||
for t in d['tracks']:
|
||
for c in t['clips']:
|
||
if c['kind'] == 'video':
|
||
print('%.3f' % c['tl_start']); raise SystemExit
|
||
print('0')
|
||
"
|
||
}
|
||
|
||
echo " начало клипа до правок: $(start) с"
|
||
|
||
ROW=${NLVE_ROW:-505} # высота видеодорожки в окне
|
||
GRAB=${NLVE_GRAB:-650} # точка захвата внутри клипа (клип начинается с 588)
|
||
EDGE=1255 # кромка у правого края окна
|
||
|
||
# Увеличение: шесть щелчков колесом с Ctrl, опора в точке захвата, чтобы
|
||
# клип из-под указателя не уехал.
|
||
I=0
|
||
while [ $I -lt 6 ]; do
|
||
$X mousemove $GRAB $ROW
|
||
$X keydown ctrl click 4 keyup ctrl
|
||
sleep 0.3
|
||
I=$((I + 1))
|
||
done
|
||
sleep 1
|
||
|
||
# Берём клип и тащим к правому краю, где и держим: рука стоит, едет
|
||
# только прокрутка.
|
||
$X mousemove $GRAB $ROW mousedown 1
|
||
sleep 0.3
|
||
$X mousemove 800 $ROW
|
||
sleep 0.3
|
||
$X mousemove $EDGE $ROW
|
||
sleep 6
|
||
$X mouseup 1
|
||
sleep 2
|
||
|
||
MOVED=$(start)
|
||
echo " начало клипа после перетаскивания с удержанием: $MOVED с"
|
||
|
||
for p in $(pgrep -x nlve); do
|
||
tr '\0' '\n' < /proc/$p/environ 2>/dev/null | grep -qx "DISPLAY=$DISP" && kill $p
|
||
done
|
||
rm -f "$PROJ.autosave"
|
||
|
||
python3 -c "
|
||
moved = $MOVED
|
||
# После шести щелчков колесом в окне видно около полутора секунд монтажа.
|
||
# Указатель доезжает до кромки и встаёт, поэтому без прокрутки клип
|
||
# уезжает на эти полторы секунды и больше никуда. С прокруткой за шесть
|
||
# секунд удержания набегает втрое больше. Порог стоит между измеренными
|
||
# величинами: 1.1 с на сборке без прокрутки, 3+ с с прокруткой.
|
||
if moved < 2.5:
|
||
print(' ПЛОХО: клип уехал всего на %.3f с — монтаж не прокручивался' % moved)
|
||
raise SystemExit(1)
|
||
print(' ok: клип уехал на %.3f с, дальше видимой части' % moved)
|
||
"
|