AviSynth. Песня с текстом.
Задумал я один проект. Есть много старых аудиозаписей, которые хотелось бы выложить на YouTube. В качестве видеоряда решено было сделать фон из картинки и движущийся текст песни, на подобии финальных титров кинофильма. Конечно же хочется все это автоматизировать, значит будем использовать AviSynth.
1. Вводные данные: В наличии у нас имеется фоновая картинка уже нужного размера и пропорций, звуковой файл песни, текстовый файл со словами и, еще один текстовый файл с названием. Все это складывем в папку запускаем bat`ник и получаем видео и обложку.
2. Необходbмые плагины:
NicAudio - для загрузки mp3
RT_Stats - для загрузки текста из файла
SubtitleEx - для плавного затухания заголовка композиции.
3. Переходим к основному скрипту для генерации видео main.avs.
# Подгружаем плагины: LoadPlugin("..\RT_Stats_25.dll") LoadPlugin("..\NicAudio.dll") LoadPlugin("..\SubtitleEx_25.dll") # Загружаем аудио #audiotrack=NicMPG123Source("audio.mp3") #для np3 audiotrack=WavSource("audio.wav") #для wav # вычисляем длительность видео в кадрах. Исходим из того, что частота кадров 24 герц. FullFrameCount=audiotrack.AudioLength*24/audiotrack.AudioRate # Загружаем фоновую картинку: videotrack=ImageReader("image.jpg", end=FullFrameCount, pixel_type="RGB32") # соединяем аудио и видеодорожки AudioDub(videotrack, audiotrack)
Далее представим, что наши титры это прямоугольник. Высота прямоугольника = количеству строк умноженное на высоту шрифта. С помощью функции Animate мы будем перемещать этот прямоугольник так, чтобы в начале видео первая строка титров располагалась в центре экрана по вертикале, а в конце видео в центре экранна должна оказаться последняя строка.
Вот как это выглядит визуально:
# вычисляем размер шрифта, размер должен быть пропорционален размеру кадра нашего видео FontSize=int(width/20) # помещаем содержание тестового файла со славами песни в переменную S=RT_ReadTxtFromFile("text.txt") # помещаем содержание тестового файла с заголовком в переменную T=RT_ReadTxtFromFile("title.txt") # вычисляем количество строк в тексте песни LineCount=RT_TxtQueryLines(S) # текст песни будем выравнивать по горизонтали по центру, для этого вычислим координаты центра XPosition=int(width/2) # вычисляем высоту титров а пикселях TextHight=LineCount*FontSize # Стартовая позиция первой строки титров по вертикал - центр экрана BeginTextPositionH=int(Height/2) # Финальная позиция последней строки титров по вертикал - центр экрана EndTextPositionH=-1*(TextHight-(Height/2)) ZerroFrame=(BeginTextPositionH+1)*FullFrameCount/TextHight # Затемняем фоновую картинку Levels(0, 1, 255, 1, 128) # выводим на 12 секунд название песни и ее автора. Потом заголовок плавно исчезает. SubtitleEx(RT_TxtGetLine(T, 0), x=XPosition, y=FontSize, firstframe=0, lastframe=360, size=FontSize, effects="c,f(0,50)") SubtitleEx(RT_TxtGetLine(T, 1), x=XPosition, y=int(FontSize*1.5), firstframe=0, lastframe=360, size=FontSize/2, effects="c,f(0,50)") # Двигаем "прямоугольник" титров. Animate(0,FullFrameCount,"Subtitle", \ S,XPosition,BeginTextPositionH,0,FullFrameCount,"Arial",FontSize,$FFFF00,0,5,0,-1, \ S,XPosition,EndTextPositionH,0,FullFrameCount,"Arial",FontSize,$FFFF00,0,5,0,-1) # выводим водяной знак (понты) WriteLogo(last,0,FontSize) function WriteLogo(clip c, int i, FontSize) { step=4 logo=" xbe.tomsk.ru " i=i+1 clp = Subtitle(trim(c,(i-1)*step, i*step-1), MidStr(logo, 1, i)+"_", font="calibri", size=FontSize*0.7, text_color=$aaaaaa, align=3) return( i==StrLen(logo) ? clp + Subtitle(trim(c,i*step, 0), MidStr(logo, 1, i)+" ", font="calibri", size=FontSize*0.7, text_color=$aaaaaa, align=3) : clp + WriteLogo(c,i,FontSize)) } # начальное и финальное затухание. FadeOut(FadeIn(50),50)
4. На этом можно было бы закончить, да вот вылез один неприятный баг. Наши титры движутся от BeginTextPositionH до EndTextPositionH, при этом EndTextPositionH < 0. В момент когда вертикальная координата равна 0, титры перескакивают в центр экрана на пару кадров, а потом возвращаются на прежние координаты. Не понятно? Вот как это выглядит на примере небольшого скрипта:
BlankClip(length=50, width=72, height=40) Animate(0,50,"Subtitle", \ "Text1\nText2",36,10,0,50,"Arial",24,$FFFF00,0,5,0,-1, \ "Text1\nText2",36,-10,0,50,"Arial",24,$FFFF00,0,5,0,-1)
На этот счет я создал issue. А пока придется делать "костыль".
Вычислим на каком кадре титры переходят через 0. Одной командой будем двигать титры до нулевой координаты, другой командой - от нулевой.
# Вычислим на каком кадре титры переходят через 0. ZerroFrame=(BeginTextPositionH+1)*FullFrameCount/TextHight # двигаем от центра экрана до 0 Animate(0,ZerroFrame,"Subtitle", \ S,XPosition,BeginTextPositionH,0,ZerroFrame,"Arial",FontSize,$FFFF00,0,5,0,-1, \ S,XPosition,0,0,ZerroFrame,"Arial",FontSize,$FFFF00,0,5,0,-1) # двигаем от 0 до конца видео Animate(ZerroFrame+1,FullFrameCount,"Subtitle", \ S,XPosition,-4,ZerroFrame+1,FullFrameCount,"Arial",FontSize,$FFFF00,0,5,0,-1, \ S,XPosition,EndTextPositionH,ZerroFrame+1,FullFrameCount,"Arial",FontSize,$FFFF00,0,5,0,-1)
5. Сисок используемых файлов:
main.avs - основной скрипт для формирования видео;
text.txt - текст песни;
title.txt - файл с заголовком и информацией об авторе;
cover.avs - скрипт для создания обложки;
video.cmd - cmd`шник для создания видеофайла;
cover.cmd - cmd`шник jpeg`а обложки;