Если нельзя, но очень хочется, то нужно обязательно и ничего в мире не стоит того, чтобы делать из этого проблему!

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

суббота, 29 ноября 2014 г.

Как сделать слайдкаст (часть 2)

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

# грузим в переменную a аудиофайл
a = DirectShowSource("доклад.mp3")

global fps = 30.0 # количество кадров в секунду в результирующем клипе
global tempo = 120.0 # на сколько % ускоряем клип

# глобальные переменные, в них будем хранить счетчик фреймов
global frame_start = 0  
global frame_end = 0 
 
# функция перевода времени мин-сек в фреймы с учетом частоты кадров и ускорения клипа
function toFrame(int min, int sec) {
    return Round((min*60 + sec)*fps*100/tempo)
}

# функция загрузки слайда в ряд фреймов длинной min-sec
function loadSlide(string name, int min, int sec) {
    global frame_start = frame_end 
    global frame_end = toFrame(min, sec)
    slide = ImageSource(name, fps=fps, end=frame_end - frame_start)
    # это хак для отладки - выводит дебаг-строчку прямо на видео в левом верхнем углу
    # slide = slide.Subtitle(String(frame_start) + "-" + String(frame_end), text_color=$000000, size=60, first_frame=0)
    return slide
}  
 
# загрузим первый слайд в переменную i сделав из него видеоряд длинной в 2 минуты 3 секунды
i = loadSlide("Slide (1).jpg", 2, 3)
 
# так же для второго слайда и так далее
i = i + loadSlide("Slide (2).jpg", 2, 26)
i = i + loadSlide("Slide (3).jpg", 5, 41)
i = i + loadSlide("Slide (4).jpg", 7, 38)
i = i + loadSlide("Slide (5).jpg", 11, 30)
i = i + loadSlide("Slide (6).jpg", 20, 43)
i = i + loadSlide("Slide (7).jpg", 29, 13)
i = i + loadSlide("Slide (8).jpg", 29, 23)
i = i + loadSlide("Slide (9).jpg", 33, 40)
i = i + loadSlide("Slide (10).jpg", 36, 15)
i = i + loadSlide("Slide (11).jpg", 36, 25)
i = i + loadSlide("Slide (12).jpg", 39, 12)
i = i + loadSlide("Slide (13).jpg", 40, 38)
i = i + loadSlide("Slide (14).jpg", 42, 21)
i = i + loadSlide("Slide (15).jpg", 43, 5)
i = i + loadSlide("Slide (16).jpg", 43, 19)
i = i + loadSlide("Slide (17).jpg", 48, 53)
i = i + loadSlide("Slide (18).jpg", 55, 54)
i = i + loadSlide("Slide (19).jpg", 58, 32)
i = i + loadSlide("Slide (20).jpg", 60, 13)
 
# ресайзим слайды
i = i.LanczosResize(764, 480)
 
# чтобы секономить время слушателя, включаем скорость 'tempo'%
a = a.TimeStretch(tempo=tempo)
 
# и в конце концов смерджим два потока и возвращаем этот результат
AudioDub(a, i)


Enjoy!

воскресенье, 16 ноября 2014 г.

Как сделать слайдкаст

Есть аудиозапись доклада в mp3 и есть слайды в формате ppt. Из ppt можно проэкспортить слайды в png/jpeg и дальше с ними мы будем работать. Итого у нас есть папка с файлами доклад.mp3 и Slide1.jpg - Slide20.jpg. Как из них сделать слайдкаст? Слайдкаст - это видеозапись выступления, где слышно докладчика, но видно только его слайды. Slideshare имеет такую фичу в платной версии, но мы жеж умнички? - сами все сделаем (а чуть позже доберутся руки и фичу-намучу). 

Итак. Раньше мы уже проходили avisynth и я надеюсь без особого труда будет его установить на комп и создать в той же папке файлик с расширением 1.avs и содержимым
Внимание! Существует более удобная версия скрипта. Смотрим тут

# грузим в переменную a аудиофайл
a = DirectShowSource("доклад.mp3")

# загрузим первый слайд в переменную i сделав из него видеоряд с частотой 23.976 и длинной 2080 кадров
i = ImageSource("Slide1.jpg", fps=23.976, end=2080)

# так же для второго слайда и так далее
i = i + ImageSource("Slide2.jpg", fps=23.976, end=888)
i = i + ImageSource("Slide3.jpg", fps=23.976, end=1614)
i = i + ImageSource("Slide4.jpg", fps=23.976, end=1733)
i = i + ImageSource("Slide5.jpg", fps=23.976, end=2533)
i = i + ImageSource("Slide6.jpg", fps=23.976, end=1126)
i = i + ImageSource("Slide7.jpg", fps=23.976, end=3953)
i = i + ImageSource("Slide8.jpg", fps=23.976, end=1566)
i = i + ImageSource("Slide9.jpg", fps=23.976, end=2442+1770)
i = i + ImageSource("Slide10.jpg", fps=23.976, end=2000)
i = i + ImageSource("Slide11.jpg", fps=23.976, end=1800)
i = i + ImageSource("Slide12.jpg", fps=23.976, end=1800)
i = i + ImageSource("Slide13.jpg", fps=23.976, end=2240+172)
i = i + ImageSource("Slide14.jpg", fps=23.976, end=29779-27730)
i = i + ImageSource("Slide15.jpg", fps=23.976, end=31942-29779)
i = i + ImageSource("Slide16.jpg", fps=23.976, end=36023-31942)
i = i + ImageSource("Slide17.jpg", fps=23.976, end=39666-36023)
i = i + ImageSource("Slide18.jpg", fps=23.976, end=42056-39666)
i = i + ImageSource("Slide19.jpg", fps=23.976, end=44356-42056)
i = i + ImageSource("Slide20.jpg", fps=23.976, end=49302-44356)
i = i + ImageSource("Slide21.jpg", fps=23.976, end=52906-49302)

# ресайзим слайды
i = i.LanczosResize(764, 480)

# чтобы секономить время слушателя, включаем скорость 150%
a = a.TimeStretch(tempo=150.0)

# и в конце концов смерджим два потока
AudioDub(a, i)

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

Что может смутить в скрипте, так это magic numbers указанные в аргументе параметра end функции ImageSource. Подбирается он вручную (пока) с помощью VirtualDub прослушивая доклад с целью поиска места, где слайд надо переключить. На будущее я хочу сделать либо кликер с возможностью трекать милисекунды когда был переключен слайд, либо сделать такую же фичу, как в SlideShare, где все на драгэндропе.


Пользоваться сторонними сервисами, типа SlideShare программистам я не рекомендую и вот почему. Когда-то я воспользовался этой фичей у SlideShare и даже очень обрадовался что есть такая фича. Запостил в блоге embed и радовался каждому 1000-му просмотру. Но потом slideshare захотел денег и просто изъял видяшку из эфира оставив только ppt. Всю работу похерили - обидно. С тех пор я решил, что весь контент буду хранить у себя на блоге+дропбокс. С ним тоже были проблемы, но после проплаты готового аккаунта все наладилось :) Отвлекся я. Что хотел сказать - если ты программист, то будет любопытно написать свой аналог, который потом сможешь кастомизировать как хочешь. А если выбрал использовать чужой сервис - будь готов к будущим неожиданностям.

Как-то так


четверг, 4 сентября 2014 г.

Два скрипта для стабилизации изображения с помощью avisynth и плагинов DePan и MVTools

Примеры и исходники взяты тут и тут

LoadPlugin("mvtools2.dll") 
LoadPlugin("DePan.dll")       

DirectShowSource("input.mov")
LanczosResize(1280, 768)
converttoYV12()

AssumeTFF().SeparateFields() 
vectors = MSuper().MAnalyse(isb = false)
globalmotion = MDepan(vectors, pixaspect=1.094, thSCD1=400)
DepanStabilize(data=globalmotion, cutoff=2.0, mirror=15, pixaspect=1.094)
Weave() # делает interlace - надо разобраться почему

Вот второй пример

LoadPlugin("DePanEstimate.dll")        
LoadPlugin("DePan.dll")

DirectShowSource("input.mov")
LanczosResize(1280, 768)
converttoYV12()

mdata=DePanEstimate()
DePanStabilize(data=mdata)
#Crop(50, 50, -52, -52)

DLL-ки можно разместить в папке со скриптом.

воскресенье, 31 августа 2014 г.

Avisynth скрипт для реализвации slow motion

Есть камера gopro - в ней есть режим со съемкой на скорости 120 кадров в секунду. Его и использовал.  Звук писал отдельно диктофоном, потому как камера в звуконепроницаемом боксе (камеру обливал водой :)) - естественно между аудио и видео случился рассинхрон. Снято было все со штатива, камера размещалась необычно вертикально (видео надобно потом перевернуть).

Что вышло


Вот сам скрипт, может кому и пригодится

video_audio_sync = 610 # на это количество кадров видео опережает аудио

# грузим видео, обрезаем первые N кадров для синхронизации с аудио и убиваем аудио (там все равно буль буль)
v = DirectShowSource("video.MP4").Trim(video_audio_sync, 0).KillAudio() 

# грузим аудио
a = DirectShowSource("audio.MP3")

clip_start = 4858 # если вырезать все левое, то где-то тут начинается самое интересное
clip_len = 4378 # длинной в столько кадров

# мерджим видео с новым аудио, обрезаем то что должно пойти в эфир и вставляем 
v = AudioDub(v,a).Trim(clip_start, 0).Trim(0, clip_len).FadeOut(200).FadeIn(100)

slow_start = 2469 + 100 # место в котором надо включить slo-mo
slow_end = 2900 - 50 # тут заканчиваем slo-mo

# делим видео+аудио на три части
v1 = v.Trim(0, slow_start)
v2 = v.Trim(slow_start, slow_end)
v3 = v.Trim(slow_end, 0)

target_fps = 30 # столько кадров/сек хочу на выходе
source_fps = 120 # столько кадров/сек было на входе

# первый и третий ролики приводим к 30 кадрам удаляя лишние
# а второй ролик надо растянуть, показав все кадры но с частотой 30 кадров/сек - от этого он растянется по времени, потому-то надо подтянуть еще и аудио
v1 = v1.ChangeFPS(target_fps)
v2 = v2.AssumeFPS(target_fps).TimeStretch(tempo=(100.0*target_fps)/source_fps)
v3 = v3.ChangeFPS(target_fps)

# снимал видео вертикально и потому надо перевернуть, а так же обрезать слева справа сверху и снизу
r = TurnLeft(v1+v2+v3).Crop(160, 260, -160, -250)

# результат вернуть
r

понедельник, 9 декабря 2013 г.

Как наложить на видео субтитры

Вот только что возникла задача такая. Если она возникла раз - значит возникнет еще раз. Стоит задокументировать.

Пользоваться буду, как положено, AviSynth. Так же понадобится плагин VsFilter. Вот подробное описание того, как он работает. Для удобства возьмем Srt формат субтитров.

Плагин - это VSFilter.dll, что в архиве в папке Release Unicode. Его надо распаковать в папку C:\Program Files\AviSynth 2.5\plugins

Далее берем видеофайл, пусть source.mov и рядом с ним создаем файл subtitle.srt c содержимым
1
00:00:01,000 --> 00:00:05,000
Senator, we're making
our final approach into Coruscant.

2
00:00:05,000 --> 00:00:10,000
Very good, Lieutenant.>
Дальше создаем файл output.avs с содержимым
DirectShowSource("source.mov")
TextSub("subtitle.srt")
Далее открываем файл output.avs В любом видеоредакторе для дальнейшего перекодирования.

Вот и вся магия. Сэмпл можно скачать тут.

вторник, 12 ноября 2013 г.

Как наложить на видео слайды с помощью AviSynth

Сегодня выступал в НАУ с докладом для студентов. Был приятно удивлен встрече с Антоном. Антон так же готовил свой доклад для студентов. Его доклад полезен будет не только для студентов НАУ, а вообще. Потому я его снял на камеру и сегодня же вечерком аккуратненько смонтировал.

Монтировал необычным для себя путем. Способ мне понравился, а потому опишу его туточки. Видео, уверен, Антон выложит на youtube (будет чуть позже). А пока главный ответ на вопрос - как наложить на видяшку, серию слайдов из презентации, причем чтобы те переключались вовремя. Очень просто.

# грузим в переменную v два подряд идущих видеофайла DSC_0877.MOV и DSC_0878.MOV (они склеятся) 
v = DirectShowSource("DSC_0877.MOV")+DirectShowSource("DSC_0878.MOV") 

# ресайзим видео до размера слайдов, сразу после добавляем сверху от 
# видео бордер такой же высоты как и видео. 
# Там пока все черненько будет - мы расположим там слайды
# результат запишем в ту же переменную v 
v = v.LanczosResize(960,540).AddBorders(0, 540, 0, 0, $000000)

# загрузим первый слайд в переменную slide1 сделав из него видеоряд с частотой 23.976 (та же что и у видео) и длинной 1389 кадров
i=ImageSource("Slide1.png", fps=23.976, end=1389)

# так же для второго слайда
i = i + ImageSource("Slide2.png", fps=23.976, end=8181)

i = i + ImageSource("Slide3.png", fps=23.976, end=5863)

i = i + ImageSource("Slide4.png", fps=23.976, end=9130)

i = i + ImageSource("Slide5.png", fps=23.976, end=7726)

i = i + ImageSource("Slide6.png", fps=23.976, end=4545)

i = i + ImageSource("Slide7.png", fps=23.976, end=673)

# и в конце концов смерджим два потока
Overlay(v, i, mode="blend", opacity=1)

Вау?! И что это за заклинание такое? Это скрипт AviSynth. Не так давно я показывал, как с ее помощью открыть любой файл в VirtualDub. На самом деле тула намного более мощная.

Вот как выглядела папочка с исходниками


 А так выглядел avs скрипт загруженный в VirtualDub (и Антон :) )


Дальше дело техники - выставить аудио/видео кодек и сохранить как avi. Положение кадров я определял задра просматривая видеоролик в поисках характерных кликов Антоном своего презентора. Лучше, конечно, снимать как-то так, чтобы был виден хоть краюшек проектора. 


Кстати, можно было с легкостью сделать как-то так (это фича фильтра Overlay)



Еще раз повторюсь AviSynth очень мощная тулза, позволяющая кстати автоматизировать много чё. Этот вопрос более чем реализовал Стас Фомин в своем SeminarAssembler. Кстати там это все делается уже, я в целях изучения просто еще одно колесо изобрел.  

Успехов!

Спасибо Антону, Стасу, НАУ, AviSynth, VirtualDub, Nikon, Google, HP и всем тем ребятам, с помощью которых этот пост случился.