Учебное пособие. |
|
Линейное редактирование
В первой части сего пособия, мы сконцентрируемся на линейном редактировании
того же сорта, что вы можете выполнить в VirtualDub.
Скриптовый язык AVISynth писался с расчётом на простоту
решения задач линейного редактирования: вам нет нужды волноваться о переменных
и сложных выражениях если вы этого не хотите.
|
|
Как только вы установили AVISynth, воспользуйтесь текстовым
редактором для создания файла с именем version.avs (или любым
другим, лишь бы расширение было AVS) и вставьте
туда следующую
единственную строку текста:
|
Version
|
|
Теперь запустите Windows Media Player и используйте его для
открытия вашего файла. Если всё в порядке, вы должны увидеть десяти-секундный
видео-клип показывающий информацию относящуюся к версии AVISynth.
(Если же вы получите ошибку говорящую "формат не поддерживается",
удостоверьтесь, что вы выполнили все инструкции по установке.)
|
|
Version - то, что можно назвать методом-источником,
подразумевая, сто он формирует новый клип вместо модификации существующего.
Первой командой в скрипте AVISynth должен быть метод источник
(или команда загрузки внешнего фильтра).
|
|
Теперь добавьте вторую строчку в файл скрипта,
так что он должен читаться так:
|
Version
ReduceBy2
|
|
Снова откройте этот файл в Windows Media Player. Вы снова
должны увидеть информацию о версии, но в половину
прежнего размера.
ReduceBy2 - трансформирующий фильтр, это значит, что он берёт
существующий фильтр и каким-то образом модифицирует его. Вы можете собрать
последовательно множество трансформирующих фильтров, как в
VirtualDub. Например добавим ещё один, чтобы сделать наше
видео затухающим в темноту в конце. Добавим ещё строчку в файл скрипта:
|
Version
ReduceBy2
FadeOut(15)
|
|
Опять откроем файл. Клип должен быть таким же
первые 9 секунд и
затем, на последней секунде должен плавно перейти в чёрный. Фильтр
FadeOut берёт целочисленный аргумент, который показывает
число затухающих кадров. Видео сформированное Version
имеет частоту кадров 15 FPS, так что аргумент равный 15 для
FadeOut начинает заглушать за одну секунду до конца.
|
|
Проходит много времени до начала заглушения,
так что давайте отрежем начало
клипа для уменьшения ожидания. Клип формируемый Version - 150 кадров
длинной (15 FPS в течении 10 секунд), и AVISynth начинает отсчёт
кадров с 0, так что имеем кадры с 0 до 149. FadeOut добавляет
лишний кадр, так что конец этого скрипта несколько дальше, кадры меняются
с 0 до 150. Давайте отбросим первые 120 из них:
|
Version
ReduceBy2
FadeOut(15)
Trim(120,150) # отрезать первые 8 секунд
|
|
В этом примере впервые использован комментарий. Комментарий начинается с
символа #, продолжается до конца строки и полностью игнорируется
AVISynth.
|
|
Trim требует два аргумента разделённых запятой: первый и
последний кадр части клипа, которую следует сохранить. Если передать 0 как
номер последнего кадра, то это будет аналогично концу клипа,
так что команда
вырезания в скрипте может быть просто записана как Trim(120,0) .
|
|
Помнить число кадров таким образом муторно. Гораздо легче открыть
частично-готовый клип в приложении типа VirtualDub,
которое покажет вам число кадров. Вы также можете использовать фильтр
ShowFrameNumber , который впечатает номер кадра в него самого.
|
|
Имеется много других фильтров для обобщённого масштабирования,
для размытия/подчёркивания границ, и для других целей. Прочитайте
описание списка команд для всех чудовищных подробностей. На практике
гораздо более используемым фильтром нежели Version
будет AVISource , считывающий AVI файл (или
один из нескольких других типов файлов) с диска. Если у вас есть
поблизости AVI файл, вы можете попробовать использовать
те же фильтры на нём:
|
AVISource("d:\capture.avi") # или как вы там его назовёте
ReduceBy2
FadeOut(15)
Trim(120,0)
|
|
Даже однострочный скрипт содержащий только команду AVISource
может быть весьма полезен для добавления поддержки AVI файлов >2GB
к приложениям поддерживающим только файлы <2GB.
|
|
|
Нелинейное редактирование
Теперь перейдём к более весёлой части. Сделаем AVS файл
со следующим скриптом внутри:
|
StackVertical(Version, Version)
|
|
Теперь откроем его. Результат: Выходное видео имеет две идентичных линии
информации о версии, одно над другой.
|
|
Вместо передачи чисел или строк как аргументов, StackVertical
берёт видео-клипы. В этом скрипте, Version вызывается
дважды.
Каждый раз, метод возвращает копию клипа о версии. Эти два клипа затем
передаются в StackVertical , который объединяет их вместе
(не интересуясь их происхождением).
|
|
Один из наиболее используемых фильтров такого типа это UnalignedSplice ,
который соединяет видео-клипы друг-за-другом. Вот скрипт, который грузит три
AVI файла (которые могут быть созданы AVI_IO) и
объединяет их вместе.
|
UnalignedSplice(AVISource("d:\capture.00.avi"), AVISource("d:\capture.01.avi"), AVISource("d:\capture.02.avi"))
|
|
(Метод SegmentedAVISource обеспечивает лучшую реализацию.
смотрите описание команд).
|
|
Обе команды, StackVertical и UnalignedSplice
могут принимать как минимум два и как максимум шестьдесят аргументов.
|
|
Вы можете использовать оператор "+" как псевдоним для
UnalignedSplice . К примеру, такой скрипт делает
тоже, что и предыдущий.
|
AVISource("d:\capture.00.avi") + AVISource("d:\capture.01.avi") + AVISource("d:\capture.02.avi")
|
|
Давайте теперь предположим вы захватываете видео используя
VIDCAP32. Это приложение также сохраняет видео
в различных AVI сегментах, но оно помещает
аудио в отдельном WAV файле. Можем ли мы воссоединить всё?
Ваши ставки:
|
AudioDub(AVISource("d:\capture.00.avi")+AVISource("d:\capture.01.avi")+AVISource("d:\capture.02.avi"), WAVSource("d:\audio.wav"))
|
|
Все обычные трансформирующие фильтры использованные в части линейного
редактирования принимают видео-клип своим последним аргументом. Так что
вы можете написать к примеру:
|
FadeOut(15, ReduceBy2(Version))
|
Вместо: |
Version
ReduceBy2
FadeOut(15)
|
|
|
Переменные
Вы должно-быть заметили то, что пример с AudioDub
был немного
неуклюж, и если мы объединяем более трёх файлов будет ещё хуже. Вы
можете упростить ваши выражения использованием переменных. Вот другая версия
последнего примера, который более управляем и лёгок для понимания:
|
a = AVISource("d:\capture.00.avi")
b = AVISource("d:\capture.01.avi")
c = AVISource("d:\capture.02.avi")
sound_track = WAVSource("d:\audio.wav")
AudioDub(a+b+c, sound_track)
|
|
Имена переменных может содержать до пятидесяти символов длинной и
содержать буквы, числа и подчёркивание (_). Вы можете присвоить результат
выражения переменной поместив имя переменной в начале строки, следующим =
и затем выражение. После этого видео-клип будет присвоен переменной. Вы
можете использовать переменную позже в любом месте, где ожидается клип.
|
|
Переменные никогда не изменяются пока вы не переприсвоите их. Для примера,
вы можете написать ReduceBy2(myvideo) , но это не изменит переменной
"myvideo" пока вы не присвоите результат снова используя
myvideo=ReduceBy2(myvideo)
|
|
|
Подразумевание last
Что если вы не присваиваете результат выражения переменной?
Ответ - результат будет присвоен специальной переменной именуемой
"last", как если бы строка начиналась "last= ".
last обычно подразумевается в двух других ситуациях:
первое, если мы используем фильтр, и фильтр имеет один параметр
clip первым в своём списке аргументов, который вы не
указываете; и второе, когда скрипт заканчивается, видео-клип в
last берётся как "значение возврата" скрипта это видео клип,
который видит приложение открывая скрипт.
|
|
Эти три правила, взятые вместе, причина по которой примеры линейного
редактирования в первой части были работоспособны без явных переменных.
Вот один из ранних примеров, переписанный полностью явно:
|
last = Version
last = ReduceBy2(last)
last = FadeOut(last, 15)
return last
|
|
Команда return использованная здесь должна сама себя
объяснять, но если хотите можете посмотреть в описании.
|
|
Неявное использование last может быть полезно даже в нелинейном
редактировании. К примеру если мы хотим загрузить AVI файл, извлечь
две сцены из него и объединить их вместе с видимым перекрытием между ними,
то можно записать что-нибудь вроде:
|
AVISource("capture.avi")
Dissolve(10, Trim(123,456), Trim(789,1000))
|
|
Здесь два фильтра Trim и каждый использует клип, который
последним был присвоен last - который в этом случае результат
выполнения AVISource .
|
|
|
Объёктно-ориентированная запись
Уже упоминалось, что трехстрочный пример с
Version /ReduceBy2 /FadeOut может быть переписан в виде:
|
FadeOut(15, ReduceBy2(Version))
|
|
Пример рабочий, но несколько сбивающий с толку. Из-за одной вещи -
порядок написания функций обратен порядку, в котором они
выполняться (проблема донимавшая математиков веками). И ещё одна вещь, по мере
добавления функций вы получаете всё больше и больше окружающих
скобок, и трудно сказать как много их надо в конце.
|
|
AVISynth поддерживают другой стиль записи
вызовов функций, называемый стилем "ООП записи", который представляется
лучше функционального стиля" во многих ситуациях. Применяя стиль
"ООП записи" можно записать вышеупомянутый скрипт так:
|
Version.ReduceBy2.FadeOut(15)
|
|
Это напоминает синтаксис вызова метода используемый во многих
объектно-ориентированных языках программирования, таких как C++
и JAVA. Вот ещё пример:
|
myvideo = AVISource("capture.avi")
return Dissolve(10, myvideo.Trim(123,456), myvideo.Trim(789,1000))
|
|
Недостаток стиля ООП записи в том, что он может использоваться только с
фильтрами типа Trim которым требуется один параметр видео-клип,
но не с фильтрами типа Dissolve которым требуется несколько.
|
|
Остаётся верным то, что переменная не изменяется, пока ей ничего не присвоили,
так что если вы напишите myvideo.ConvertToRGB() , то
конвертированная версия клипа будет помещена в last и myvideo останется неизменным.
|
|
|
|