Есть обрубок от серии 2ххх, GTX 1660SUPER. Приобрел, тестирую, щупаю, проверяю.

Быстрая память 6 Гиг, хорошо разгоняется ядро. Может кодировать B-кадры до 4. Результат на потоке 6 мегабит/с на 1080p 60 Hz весьма хорош, как для стрима. К сожалению, не смог управлять параметром deadzone, который есть в x264, но не работает в NVENC.

Если кодировать и писать видео с постоянным качеством CQP, то можно ограничиться QC=18-20.

С молчаливого согласия авторов выложу некоторые наблюдения.
Имеем AVS+ 0.1.0 r2772 (Avisytnh с нативной поддержкой Gscript и расширением стандартных функций)
masktools2-v2.2.18

Берем источник с записью покатушек в ЕТС2 на разрешении 720р.

src=DirectShowSource("чего-то там.avi", audio=false) #60 ФПС с дропами из-за низкого ФПС в игре.

Пишем строчки

D_f= mt_makediff(src.Loop(times=2, start=0, end=0), src, chroma="process")
D_f

Получаем в тесте 145-152 ФПС

или

D_f= src.mt_makediff(src.trim(1,0), chroma="process")
D_f

Получаем в тесте 145-152 ФПС
или

D_f= mt_makediff(src, src.trim(1,0), src, chroma="process")
D_f

Получаем в тесте 145-152 ФПС
или

D_f= mt_makediff(src.trim(1,0), src, chroma="process")
D_f

Получаем в тесте 58-62 ФПС. А ведь в сравнении с предыдущим вариантом результат одинаков...
или

D_f= src.trim(1,0).mt_makediff(src, chroma="process")
D_f

Получаем в тесте 58-62 ФПС

В общем, я обалдел от такой ситуации. Разница в скорости в 2-2,5 раза!!!

Теория теорией, но реализация просто ужас. Нельзя просто так на ровном месте терять производительность.

Пока шло время, я раскапывал материал и тестировал отдельные модули, попутно проверяя их на скорость исполнения.
И вот что мне стало понятно. Надеюсь, это будет полезным для любителей поковырять AviSynth и реализовать свои решения.

Многопоточность, указанная директивами и завершающим Prefetch([число потоков]) СНИЖАЕТ скорость работы бинарных библиотек, которые реализованы для многопоточности. И снижает катастрофически, до уровня скорости работы стандартных функций AviSynth.

Также проблема касается run-time конструкций, обрамлённых ScriptClip и ему подобных, внутри которых происходит считывание переменной (номер кадра) и присвоение параметрам глобальных переменных. Особо затруднена отладка цепочек, заключённых внутри  ScriptClip. Кроме того, ScriptClip и вся группа не работает в многопоточности. Просто не работает.

Некоторые функции поиска разности можно ускорить с помощью библиотек MaskTool2. И при этом не страдать из-за сложности отладки внутри ScriptClip и ограничений в многопоточности - MaskTool2 многопоточен и этого вполне достаточно для быстрой обработки кадров. Полностью отказаться от ScriptClip не удастся - другого быстрого способа передать в единственную переменную значений искомых параметров (максимум-минимум значений, средние значения в кадре) я пока не обнаружил.

В остальном, приходится действовать по принципу однопоточной обработки последовательности кадров.

PS. Речь идёт о версии AVS+.

Хм, оказывается, документация на AviSynth страдает проблемами. Например, скромно умалчивается в описании функции SelectEvery то, что она продуцирует пониженный ФПС. И то, что Interleave мультиплицирует ФПС. Впрочем по чередованию это есть в общей таблице функций. Но я считаю, что индивидуальное описание функций должно быть полным.

Пока не сделал несколько лабораторных работ, не мог разобраться в работе скрипта. Пока сижу, ковыряюсь. Но вопрос по поводу радиуса поиска векторов в блоке SVP остался - он только пространственный, внутри кадра? Несёт ли клип вектора метаданные, в частности ФПС, как реагирует на метаданные SVSmoothFps? Для чего у SVSmoothFps дополнительный "вход" для оригинального клипа-источника, как это работает?

У меня есть вопрос по определению поиска векторов вперед и назад применительно к функциям самого SVP.

Имеем кадры 0,1,2 длительностью каждый 1/FPS_src. SVP работает в режиме удвоения частоты кадра. В новой последовательности точка генерации находится (по глобальному времени) между 1 и 2 исходной последовательности (1.5/FPS_src). Что является поиском назад, учёт положений пикселей в кадре 0 относительно кадра 1 исходного клипа?


Каков радиус (расстояние) исследования исходных кадров и регулируется ли это заданием строки JSON для поиска вектора?

ЗЫ. Протестировал GameDropFix 5.01-й версии на скорость. Даже в однопоточном варианте выдаёт порядка 200 к/с. Т.е по скорости это просто зверская штука. Но увы, скрипт не может восстановить исходный ФПС, ориентируясь на число дублированных кадров, полученных при захвате последовательности с переменной ФПС на повышенной фиксированной частоте. Из-за этого происходят рывки при восстановлении промежуточных кадров и остаются дубли. Я так думаю, но могу и ошибаться. Я попробую вручную удалить дубли и посмотрю на общуюю плавность безотносительно звука. Просто интересно.

Дополнение.
Нет 200 к/с. Видимо, из-за глюка часть операций скриптом не выполнялась. Потому и скорость была сумасшедшая.

Каков будет вывод по тому видео, что я предоставил?

MAG79 wrote:

YPlaneMinMaxDifference
Это вообще не то. Это посчитать максимум и минимум яркости внутри одного кадра. И вернуть разницу между ними. По сути - длину диапазона яркости для кадра.

Полезная вещь. Например, с помощью оверлея делаешь кадр сравнения между C и C.trim(1,0) в режиме Difference. Получаем серый кадр, в котором отличия выделены пикселями с отклоняющимися абсолютными значениями. Именно они независимы от площади, что значительно упрощает указание пороговых значений для выяснения смены сцены или движения. Но именно с оверлеем многопоточность глючит. Это очень печально - исполнять скрипт на одном потоке, без Prefetch.

PS. Буду ковыряться в MT-фильтрах. Если эта группа значительно быстрее, чем основные фильтры Ависинта, то лучше MT. Скорость - наше всё.

PPS. О, разработчик использует обратную польскую запись для вычислений. Это интересно. Я со школы был с ней знаком - применялась в "научных" советских калькуляторах. Да и в языке для PS полиграфии та же ситуация.

Похоже, что я повторяю путь, пройденный намного раньше другими.

Выяснил, что функция yDifferenceFromPrevious зависит от площади. Т.е. если я возьму полный кадр и часть, где происходит движение, то получу в качестве разницы отличающиеся цифры.

Не знаю, что там думали разработчики, но это явно не то, что хотелось получить. Есть функции типа YPlaneMinMaxDifference, которые дают превосходные результаты и не зависят от площади. Но! Они полностью не работоспособны под Prefetch. Я понимаю, что AviSynth крайне специфичен и забит фильтрами под устаревшие технологии, но многопоточность! Как же без неё?

ЗЫ. Может я многого хочу? smile

Ух, начерно завершил эксперимент с многопоточностью...

Тестировал и подбирал режимы на таком примере. Меня интересовали значения дельты не только по яркости, но и по цвету. Случаи бывают разные... Сварганил тестовый скрипт. Голова пухнет - скриптовый язык знаю посредственно. smile

На нём и отлаживал. Были странности, когда при малой дельте она показывалась дважды там, где её не должно быть. И зависело это от числа потоков. Приходилось перегружать программу AvspMod для каждой новой попытки. Но это не долго. Зато надёжно сбрасывает память. Цвет пятна регулируется в строке определения клипа Blink. Я специально задал цвет с нейтральным серым, чтобы увидеть разницу в цветовых плоскостях.

SetMemoryMax(6000)

function Show_delta(clip So) {
Global C=So
So=So.Gscriptclip(""" Subtitle("dY=" + string(yDifferenceFromPrevious(C)) + " dU=" + string(uDifferenceFromPrevious(C)) + " dV=" + string(vDifferenceFromPrevious(C))) """)
return So
}

Threads=3

SetFilterMTMode("Show_delta", 3, force=true)

Src=BlankClip( Length=1, width=1280, height=720, FPS=30, pixel_type="YV12", color_YUV=$808080 )
Blink=BlankClip( Length=1, width=50, height=50, FPS=30, pixel_type="YV12", color_YUV=$80808f )

Res=Overlay(Src, Blink,  x=500, y=200, opacity=1.0, mode="blend", greymask=false, ignore_conditional=false, pc_range=true)
loop(Src, 3)+ loop(Res,3)

Show_delta(last)

Prefetch(Threads)

Число потоков от 1 до 3. Между 2 и 3 разница незначительна при тестировании на скорость.

Пока суть на дело, я немного покопался в изменениях. И вот что нашёл интересное.
Появился Grunt и произошли весьма заметные изменения в Ависинте. Начну с последнего, AVS+.
Появилась естественная для программирования интерпретация IF, FOR безо всяких ScriptClip, появилась команда (часть функции по сути) выхода из модулей условия или цикла при достижении некоторых условий return.
Пример (http://avisynth.nl/index.php/GScript#Avisynth.2B).

BlankClip(width=240, height=160)
Subtitle("GScript AVS+ test", align=8)

for (i=0, 5) {
  Subtitle(String(i), y=18*i)
  if (i>=3) {
    Subtitle("i>=3", align=5)
    return Last
  }
}

return Subtitle("(exit)", align=3)

/*
Loop IS terminated by 'return Last' statement;
"(exit)" line NOT executed
*/

Что примечательно, это работает с Prefetch. Сами попробуйте, у кого есть AviSynth+.

Печалит то, что мой старый пример точно так же показывает зависимость от многопоточности, когда слетает юстировка. И это независимо от того GScriptClip или ScriptClip.


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

Дополнено.

Для полной работоспособности функций типа
    YDifferenceToNext(clip [, int offset = 1])   
    UDifferenceToNext(clip [, int offset = 1])   
    VDifferenceToNext(clip [, int offset = 1])   
    RGBDifferenceToNext(clip [, int offset = 1])
необходимо использовать gruntx64.dll (в оригинале называется grunt-x64.dll, что недопустимо для модулей в 7-ке) и можно использовать хоть GScriptClip, что ScriptClip - всё едино.  Почему ссылки на него нет у самого автора на форуме Doom9 - не знаю. Есть только х32 - версия. 64-бит версия есть только на справочном сайте AviSynth, в разделах AVS+, с неправильным названием. Но название легко исправить. smile

Достаточно его кинуть в папаку C:\Program Files (x86)\AviSynth+\plugins64+

Одна неприятность - при работе в редакторе AvsPmod (х64) иногда происходит его фатальное зависание при попытке перемотать кадры в начало ролика. Пока буду продолжать тестирование.

Но уже радует, что с Prefetch работает пример ниже, хоть и со слетающей юстировкой. Но юстировка мне побоку, мне циферки давай. smile

scriptclip(""" Subtitle("dY=" + string(yDifferenceFromPrevious(last)) +
\ " dU=" + string(uDifferenceFromPrevious(last)) + 
\ " dV=" + string(vDifferenceFromPrevious(last))
\,align=5) """)
Prefetch(2)

Важно!

Чтобы не мучиться и не заниматься ручным подбором свойств многопоточности, сообщество создало импорт-клип, в котором известные модули уже расписаны как нужно. Я тут выложу файлик, ибо он погребён в недрах англоязычного Doom9, в теме обсуждения MT-режимов. Для начала достаточно, но кто захочет - найдёт на оригинальном форуме.

Есть еще файлик на 450 мегабайт, там ещё сложнее. Там капли на стёклах и фатальное снижение ФПС в тоннеле. Да ещё смена масштаба просмотра и резкие повороты головы.
Добавил ссылку. Там 5 минут видео с характерными сложностями для поиска векторов движения. Будет лежать 90 дней.
https://m.mega.dp.ua/HGE9

>Теперь бы исходник, любой короткий. Чтоб потренироваться со скриптом

Чуть позже.

Должен заметить, что те ролики были записаны с отсчётами на 30 ФПС, поэтому дублей там меньше 3. А вот на 60 ФПС уже начинается ахтунг. Хотя, казалось бы, в чём проблема? Ну изменил частоту отсчётов... smile

При этом в некоторых местах даже на 30 ФПС алгоритм выявления дубликатов не срабатывает и они остаются. А SVP этот момент не отлавливает, к сожалению...

Дополнено.

Вот ссылка. Будет лежать 90 дней. AVI 43 мегабайта.
https://m.mega.dp.ua/5SC6

Вот здесь есть примеры.
https://youtu.be/ZJ-qsHfOCQs - на 49-й секунде отсутствует синтез кадра. Дубликат.
https://youtu.be/huSXbXDfyjA

В таком неспешном симуляторе езды важна плавность картинки.

На какой ресурс выложить?

Специально найду кусок с 5-6 дропами.

ЗЫ. Вообще-то кто-то смотрел образец на моём канале. Именно в ту субботу. Там отчётливо видны дропы. Я там свёл две половинки с обработкой и без.

MAG79 wrote:

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

У меня была мысль нарезать по 20-60 кадров, дропы подсчитывать и вырезать, но отрезку присваивать новый ФПС с учётом удалённых дропов и скармливать алгоритму, который должен восстановить исходную частоту. Потом отрезки суммировать, причём в новом начальный кадр следует отсечь, чтобы он не дублировал восстановленный кадр предыдущего отрезка. Вначале думал применить твой плагин для пересъёмки видео, но проблема состоит в том, что отрезок может содержать часть цепочки дропов, продолжающейся в новом отрезке. И поэтому придётся искать начало цепочки конечных дропов, переносить в новый отрезок. А это замедление работы и использование функций типа YDifference в дополнение к тому, что исполняет плагин пересъёмки видео.

Но вряд ли логика AviSynth позволит мне делать произвольное количество отрезков для фильма произвольной длины без переполнения памяти. Рекурсию можно попробовать, но именно она сожрёт память. Да ещё и с глобальными параметрами нужно разбираться. GameDropFix по этой причине не может быть запущен дважды в одном скрипте. smile

В общем, глубина обработки в 3 дропа маловата оказалось.

Кстати, можно в настройках поиска векторов движения использовать поиск только вперёд или только назад? Можно регулировать радиус поиска по количеству кадров?

Почитав с мучениями (английский воспринимаю как чтение сквозь заляпанные очки) форум Doom9, нашёл решение для мультипоточности. Костыль, скорее всего. Это ConditionalFilterMT

Есть ссылка на проект https://github.com/mysteryx93/ConditionalMT
DLL здесь.
https://github.com/mysteryx93/ConditionalMT/releases

Там внутри этого оператора работают все станартные функции. По крайней мере простой тест не выявил проблем. Буду проверять остальное.

Не думаю, что следует модифицировать имеющийся скрипт. Хотя... У меня встречаются дубли до 6 кадров после оригинального. И происходит это не регулярно. Т.е. при записи, например, EuroTruck Simulator 2 я могу в отдельных местах карты получить до 12 ФПС. От этого не спасает даже использование видеокарт 1080, как показали наблюдения за стримерами на Ютубе. Просто разработчики (платных) карт местности не оптимизировали их, оставив кучу плоскостей и невидимого мусора по принципу "и так сойдёт". А поскольку запись идёт на стандартных 30-60 ФПС, то мы получаем удивительную картину, когда время жизни оригинального кадра накладывается на последующие кадры в видео, снятого с фиксированным ФПС. И ФПС в игре не постоянен. Хоть и можно его залочить на определённом максимуме разными средствами.

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

Для интереса получил значения своего видео FramerateNumerator/FramerateDenominator. Получилось точно 5 000 000/83 333.

Я тут подумал...
Хорошо бы реализовать нарезку на части определённой длины, как было упомянуто раньше в этой теме (или не тут). Если дубликаты протянулись до конца отрезанного фрагмента, то их перекинуть в начало следующего. В общем, соорудить заплатку, соединяющую два клипа.

Вот как это реализовать в логике AviSynth? Алгоритмически это понятно. Gscript почему-то не работает в версии +. Так бы я проверил работу под Prefetch.

В скрипте используется принцип конвейера? Т.е. создаются цепочки-клипы с разным содержанием кадров и затем взаимно анализируются и выбираются нужные?

tracker35 wrote:

http://s019.radikal.ru/i633/1711/18/513997709a88.png

Avisynth+ r2544 / SVPflow 4.2.0.142
В режиме MT выдаёт такую ошибку, вне зависимости от того какой SetFilterMTMode("DEFAULT_MT_MODE", 2)  1, 2 или 3.

Я в субботу списался с MAG79.

Благодарю за ответ. Надеюсь, на форуме можно обращаться на "ты".

Итак, в квоте видна типичная проблема, возникающая при размещении команды Prefetch(Threads) внизу скрипта.

Я выяснил это совершенно случайно. Если эту команду убрать, то скорость остаётся стандартной. Для моего компьютера это примерно 12 к/с при обработке игрового видео 720р. К сожалению, GameDropFix-v5-01 (и любой их них), прекращают свою работу при размещении команды Prefetch и выдают на картинке такой заголовок. И это не проблема скрипта от Mag79.

Примечательно, что с этой командой прекращают работу или глючат ВСЕ примеры из справочника для AviSynth, основанные на ScriptClip и других функций этой группы. Вначале я подумал, что проблема касается только ран-тайм функций сравнения и анализа кадров внутри скриптов. Однако сделал простейший пример типа

#<любой источник>
Threads=2 #1|3|4
ScriptClip(Last, """
    L = 20
    last.Subtitle("L=" + String(L), align=5)
""", show=false)
Prefetch(threads)

и получил следующие изображения.

Prefetch закомментирован. L=20 по центру, как и полагается для параметра align=5.
Prefetch активен. Надпись L=20 слева вверху.

Проблема в том, что даже для такой простейшей функции, как субтитры, слетает принятая в функции выключка размещения (юстировка вправо-влево-верх-вниз). Наличие или отсутствие описателей SetFilterMTMode никак не влияет на результат. Я так понял, что SetFilterMTMode - это декларация, ничего более. А вот уже Prefetch - это собственно функция распараллеливания. Потому и ставится перед самым выходом и запрашивается самой первой.

В общем, всё очень плохо. С Префетч на 2 потока стандартные функции и обработка клипов идёт очень шустро (на 60-80% быстрее, чем без Префетч), практически 30 к/с и выше. Это отлично чувствуется, если попытаться сделать Dissolve на дистанции 100 кадров.

Сейчас у меня последняя версия AviSynth+ 0.1.0 r2772 с редистрибутивом C. Скрипт просматриваю под AVSPMod 2.6.0.6 64 бит, в нём же имеется модуль проверки скорости выполнения скрипта.

Система вин7 64 бита. DLL от SVP брал для 64 бит, естественно.

PS. Если что - я тоже почитатель физики Ньютона, дифференциального исчисления, матриц и теории гравитации. Но не такой скиловый. smile
PPS. Что-то мне подсказывает, что нужно срочно учиться писать бинарники-аналоги для ран-тайм функций AviSynth. Потому что как новичок я не знаю, какими стандартными функциями получить средние или экстремумы светлот из кадра, выданного, например, в Overlay. Или вообще как получить YUV/RGB отдельного пиксела кадра...