Log in

View Full Version : Scrolling, looping text at the bottom of a video


NDog
24th June 2008, 08:53
Hi there, I am trying to acheieve something with avisynth but have'nt had much luck searching, so I am asking here as a kind of last resort. I am not very familiar with avisynth but I believe it should be able to achieve what I want to do.

Ideally I would like to play a video file (avi) that is similar to TV shows where they have some kind of a border at the bottom of the video with scrolling text, for example advertising where the text scrolls from right to left with white text inside a semi-transparent red box

I would like to use a single line text file to load the text, nothing too fancy, and I would like the scrolling text to keep repeating until the video ends i guess.

I think this can be done pretty simply maybe using the animate.subtitle command, but loading the text file and having some kind of a text box semi transparent behind the scrolling text and making the text loop is beyond my scope of knowledge. I have tryed searching this feature, but if anyone can point me at an existing forum or help me solve that request, I am truely grateful :)

mikeytown2
24th June 2008, 11:28
here is a proof of concept example

a=ColorBars().Trim(0,99)
#Create Active Background
a=a.Animate(0,a.framecount-1,"Levels", 0,0.1,255,0,255, 0,3.0,255,0,255)+a.Animate(0,a.framecount-1,"Levels", 0,3.0,255,0,255, 0,0.1,255,0,255)

#loop Active Background, lots of frames
a=a.Loop().ConvertToYV12()

text = Import("x.txt")
text = "Hi There"

ScrollingMarquee(a,text)

function ScrollingMarquee(clip c, string Text, int "Fontsize", float "Speed", int "BackgroundColor", float "BackgroundOpacity", int "repeat", string "Font")
{
#Set Defaults
Fontsize = Default(Fontsize, 36)
BackgroundColor = Default(BackgroundColor, $FF0000)
BackgroundOpacity = Default(BackgroundOpacity, 0.7)
Speed = Default(Speed, 10.0)
Font = Default(Font, "Arial")
x = c.width()

TextLenghtPx = Int(StrLen(Text)*Fontsize/2.5)
Frames = Int(TextLenghtPx/(Speed/10.0))
blacksize=int(fontsize*1.5)
bottom = int(c.height()-blacksize)
y=fontsize

TextBackgroundClip = BlankClip(c, length=Frames, width=x, height=blacksize, color=BackgroundColor, pixel_type="RGB32")
TextBackgroundClipAlpha = BlankClip(TextBackgroundClip, color=$00FF00)
TextBackgroundClipWhite = BlankClip(TextBackgroundClip, color=$FFFFFF)
CreateMask = Overlay(BlankClip(TextBackgroundClipWhite), TextBackgroundClipWhite, opacity=BackgroundOpacity)

c=overlay(c,TextBackgroundClip,y=bottom, mask=CreateMask)
TextBackgroundClipAlpha.SubtitleEx(Text,x,y,0,Frames,font, "m(0,0," + string(y) + "," + string(Frames) + ",-" + string(TextLenghtPx) + "," + string(y) + ")",Fontsize).Loop()
overlay(c,last, mask=ColorKeyMask($00FF00, 1).Blur(0.5), y=bottom)
}


Other Options, and link to SubtitleEx()
http://avisynth.org/mediawiki/External_filters#Subtitling

I have a feeling that AVSLib (http://avslib.sourceforge.net/) will be able to do what your asking for, without a lot of the above uglyness.

sidewinder711
24th June 2008, 11:45
Here is an example which I have found in the German doom forum (http://forum.gleitz.info/showthread.php?t=28339):


LoadPlugin("path\autocrop_25_20050103.dll")
video=AVISource("yourmovie.avi")

marquee(video, "here.comes.your.scrolling.text...","Vardana",24,$FAE5F1,$184458,320)

function marquee (clip "vclip", string "vtext", string "vfont", int "vsize", int "vtcolor", int "vhcolor", int "vspeed"){
v1=BlankClip(length=1,width=2048,height=vsize + 16,fps=Framerate(vclip),color=$000000,pixel_type="YV12")
v1=Subtitle(v1,vtext,2,0,0,0,vfont,vsize,$FFFFFF,$FFFFFF,7,0)
v1=AutoCrop(v1,mode=0,threshold=20)
v2=BlankClip(v1,length=1,width=Width(v1)+6,height=Height(v1)+6,color=$000000,pixel_type="RGB32")
v2=Subtitle(v2,vtext,2,0,0,0,vfont,vsize,vtcolor,vhcolor,7,0).ResetMask()
vm=Subtitle(v2,vtext,2,0,0,0,vfont,vsize,$FFFFFF,$FFFFFF,7,0).ResetMask()
v2=Mask(v2,vm)
videoW1=Width(vclip)
videoW2=0-Width(v2)
videoh=Height(vclip)-Height(v2)-16
vx=BlankClip(vclip,color=$000000,pixel_type="RGB32")
vy=Trim(Animate(0,vspeed,"Layer",vx,v2,"add",255,videoW1,videoh,vx,v2,"add",255,videoW2,videoh),0,vspeed).Loop()
vv=Layer(ConvertToRGB32(vclip),vy,op="add",level=255,x=0,y=0)
return vv
}

gzarkadas
24th June 2008, 21:04
I have a feeling that AVSLib will be able to do what your asking for, without a lot of the above uglyness.

Since someone took the time to mention my lib :D, here is my attempt to fulfill NDog's request. I'm not sure though if I have managed to remove the uglyness :p.

LoadLibrary("avslib")

global marquee_duration = 8.0 # marquee duration in seconds
global marquee_distance = 64 # distance between text blocks
global marquee_char_width = 8.8888 # 640 / 72 for std subtitle fonts
global marquee_height = 32 # height of marquee window
global marquee_background = color_red

text = Import("...your text file...")
src = AviSource("...your source...")

marquee_width = RoundBs(Ceil(StrLen(text) * marquee_char_width) + marquee_distance, 4)
marquee_frames = Ceil(marquee_duration * src.Framerate)
base = src.BlankClip(length=marquee_frames, width=marquee_width, height=marquee_height)
title = base.SubTitle(text, x=0, y=marquee_height *2 / 3, align=4, \
text_color=color_white, halo_color=color_gray50)

times_w = Ceil(Float(src.Width) / Float(marquee_width))
times_2w = 2 * times_w
times_f = Ceil(Float(src.Framecount) / Float(marquee_frames))
total_times = times_2w * times_f

mbase = base.BlankClip(length=marquee_frames * times_f, width=marquee_width * total_times)
mtext = ArrayFill(title, total_times).ArraySum(sum_func="StackHorizontal")
mmask = mtext.ScaleToPC()
mwindow = Animate(mbase, 0, marquee_frames * times_f - 1, "Overlay", \
mtext, src.Width, 0, mmask, \
mtext, -marquee_width * total_times + src.Width, 0, mmask \
).Crop(0, 0, src.Width, 0)

mwindow = mwindow.Trim(0, -src.Framecount)

mbackground = src.Crop(0, src.Height - marquee_height, 0, marquee_height)
mbackground = Overlay(mbackground, mbackground.BlankClip(color=marquee_background), opacity=0.5)

marquee = Overlay(mbackground, mwindow, mask=mwindow.ScaleToPC())

StackVertical(src.Crop(0, 0, 0, src.Height - marquee_height), marquee)


The text file must contain a single line string inside quotation marks in order for Import to work as expected.

DarkT
24th June 2008, 21:52
Isn't what you're asking for but, it'd be dead-simple to achieve with the addition of AEGISUB... You'd make a super simple script in it and then load it with VSFILTER, TextSub("trix.ass")

NDog
25th June 2008, 09:46
Thanks everyone for the input.

@mikeytown2
This is a good solution, it is very effective, and I think I will learn a lot from tweaking this script, for example speed settings, opacity and colour settings, and the size of the bar.

@gzarkadas
Thanks for the effort, I tried your method, and it works, however media player classice (winxp) leaped to 456MB memory usage and the CPU was extremely high, so the video did not render properly and basically froze. maybe I am donig something wrong, I will try to investigate further, but any suggestions will be good

gzarkadas
25th June 2008, 21:15
...
@gzarkadas
Thanks for the effort, I tried your method, and it works, however media player classice (winxp) leaped to 456MB memory usage and the CPU was extremely high, so the video did not render properly and basically froze. maybe I am donig something wrong, I will try to investigate further, but any suggestions will be good

The solution I posted was not meant for playback :); you will have to encode the output of the script to a video clip to play nicely. If you want on-the-fly realtime processing, you will have to use a specialised subtitling plugin such the ones proposed by others in this thread.