Log in

View Full Version : Scrolling credits


Floatingshed
29th May 2014, 05:54
I am trying to make smooth-looking credits to scroll upwards over some video. This is the script I'm using:

AVISource(myvideo.avi)
V=last

function credits (clip video, int sf, int ef, string words)
{
Animate(video, sf, ef, "subtitle", words, -1, 780, sf, ef, "Tahoma", 30, $FFFFFF, words, -1, -450, sf, ef, "Tahoma", 30, $FFFFFF)
}

V1=credits(V, 40, 200, "kjhjfdskhdkhfkdfhkdjfhkdsjc")
V2=credits(V1, 60, 220, "kkklscslkcjlskjcksjchksjhcksjchkshc")
V3=credits(V2, 80, 240, "jkcxjsudhd")
V4=credits(V3, 100, 260, "jusjxdskaxdkaxhj")
V5=credits(V4, 120, 280, "ojkdiwudgqwkhjsbi9q7uyhu")
V6=credits(V5, 140, 300, "salijdhuaiuhxoajx")
V7=credits(V6, 160, 320, "wouhdiuwydyughdj")
V8=credits(V7, 180, 340, "jsauduajdahoklsjqdiuoajxsalkjdoisuagdchs")
V9=credits(V8, 200, 360, "kusahiouxdhasoudy8owuihdopwu8d")
V10=credits(V9, 220, 380, "djduyuedbgdj")
V10

The result is scrolling text as expected but when saved as video each line seems to have a life of its own, slightly shifting its vertical position relative to its neighbours, causing a ripple effect.
Am I approaching this from the wrong direction?
Any suggestions most welcome. Thanks.

Gavino
29th May 2014, 08:32
Each line has a life of its own because they are being animated separately and independently.

What you need to do is animate a single multi-line subtitle (using \n and the lsp argument), or (better) put static titles on a (taller) transparent background and animate the overlaying of this onto your source clip, varying its vertical position.

Floatingshed
29th May 2014, 09:31
Each line has a life of its own because they are being animated separately and independently.

What you need to do is animate a single multi-line subtitle (using \n and the lsp argument), or (better) put static titles on a (taller) transparent background and animate the overlaying of this onto your source clip, varying its vertical position.

That makes sense, thanks.
I prefer the multi-line subtitle idea as it would be easier to modify than a static image but I'm not sure how to use \n in this regard. Would you be able to post a short example that I can play with please?

Thanks.

Gavino
29th May 2014, 10:20
function MySub(clip c, int sf, int ef, string text, float "y") {
y = (y == -1 ? -1.0001 : y) # avoid special value -1 (taken as centre)
Subtitle(c, text, first_frame=sf, last_frame=ef, y=y, align=8, lsp=50)
}

function Credits(clip c, int sf, int ef, string text) {
Animate(c, sf, ef, "MySub",
\ sf, ef, text, float(c.height), /* starting args */
\ sf, ef, text, -float(c.height) /* end args */
\ )
}

AVISource(myvideo.avi)
Credits(40, 380, "First line\nSecond line\nThird line")The line spacing can be varied by changing the lsp value and/or inserting extra \n's.

Note the use of a separate function (MySub) to allow named arguments and defaults of Subtitle to be used and avoid repeating fixed arguments (eg align, lsp) in the Animate call.

Floatingshed
29th May 2014, 12:07
Thanks for the help, but I don't understand what the start and end args are. I thought they would be co-ordinates, but everything I try gives me "Invalid arguments to function Credits"...

Gavino
29th May 2014, 12:38
The start and end args are the argument lists for "MySub" at the start of the animation and at the end of the animation respectively. They must match those required by MySub (except for the clip, which is implicit).

In the example, the arguments sf, ef, and text are the same at both start and end - only the argument y is varied. This represents the vertical position of the subtitle, and so is designed to vary from the bottom of the clip at the credits start (frame sf), scrolling up to be beyond the top of the clip at the final credits frame (ef).

If you are still getting problems, post your script and we will take it from there.

Floatingshed
29th May 2014, 14:24
Sorry, I'm not getting this.
My script is the same as your script above. I was trying to get it to work stand-alone before incorporating it into anything else. So I've simply replaced the "AVISource(myvideo.avi)" with a blank clip, thus:

function MySub(clip c, int sf, int ef, string text, float "y") {
y = (y == -1 ? -1.0001 : y) # avoid special value -1 (taken as centre)
Subtitle(c, text, first_frame=sf, last_frame=ef, y=y, align=8, lsp=50)
}

function Credits(clip c, int sf, int ef, string text) {
Animate(c, sf, ef, "MySub",
\ sf, ef, text, float(c.height), /* starting args */
\ sf, ef, text, -float(c.height) /* end args */
\ )
}

BlankClip(length=1000, width=720, height=576, pixel_type="yv12", fps=25)
Credits(40, 380, "First line\nSecond line\nThird line")

Sorry to be so dim!

Gavino
29th May 2014, 15:23
Strange - that script works fine for me (using v2.60, but it should also work with 2.58).

Are you sure there's nothing else in your script, and that you are picking up the text exactly as you posted?

Floatingshed
29th May 2014, 16:57
OK, I've just upgraded to 2.58 (was on 2.57!)
Error is now: Script error: The named argument "y" to subtitle had the wrong type
Line 3 Line 10 Line 14

StainlessS
29th May 2014, 17:21
From v2.6 docs


Version Specific Information
Position (x,y) can be float (previously int) (with 0.125 pixel granularity).

Nice cheat with the y= -1.0001, G

Suggest v2.6Alpha5, its probably a lot better than v2.7 that you are used to.

EDIT Also suggest this style as easier


Subs = """First line
Second line
Third line
"""
Credits(40, 380, Subs)

Floatingshed
29th May 2014, 17:37
Just updated to 2.6 and the script works fine.
Thanks to both of you...

Is it possible to have the list of subs in a text file that can be read into the subs variable in: Credits(40, 380, subs)?

Gavino
29th May 2014, 17:39
Thanks, StainlessS - I'd forgotten the float change was only in 2.60.
It will work in 2.58 if you change y to int (and remove float from the Animate call), but then you would also have to remove the '-1 cheat' and see a temporary glitch as y passed through -1.

Also suggest this style as easier


Subs = """First line
Second line
Third line
"""
Credits(40, 380, Subs)

No, that won't work - Subtitle doesn't recognise real newlines, you just get a blob. However you could do

Subs = "First line" +\
"\nSecond line" +\
"\nThird line"
Credits(40, 380, Subs)

StainlessS
29th May 2014, 18:13
Yes of course G, thank you.
Or for simplicity add a

Subs=RT_StrReplace(Subs,Chr(10),"\n")


to original line separated snippet.
Could also do something like

Subs=RT_ReadTxtFromFile("MySubs.txt")
Subs=RT_StrReplace(Subs,Chr(10),"\n")

Floatingshed
29th May 2014, 18:35
I'm impressed, this is working really well.
One more question....
How about making the scrolling credits smoother by interlacing them? My source material is interlaced so I'm processing as such anyway.
Simply using Separatefields() & Weave() will mess up the subtitle's vertical size, I think.

wonkey_monkey
29th May 2014, 23:45
When interlacing text I've always recommended applying a 1px vertical blur to avoid (de)interlace flicker.

As to another solution for the original problem, you could try my xyremap (http://forum.doom9.org/showthread.php?t=166087) plugin:


blankclip(width=640,height=1280,length=1500*2).subtitle(\
"It is a period of civil war.\n"+\
"Rebel spaceships, striking\n"+\
"from a hidden base, have won\n"+\
"their first victory against\n"+\
"the evil Galactic Empire. \n\n"+\
"During the battle, Rebel\n"+\
"spies managed to steal secret\n"+\
"plans to the Empire's\n"+\
"ultimate weapon, the DEATH\n"+\
"STAR, an armored space\n"+\
"station with enough power to\n"+\
"destroy an entire planet. \n\n"+\
"Pursued by the Empire's\n"+\
"sinister agents, Princess\n"+\
"Leia races home aboard her\n"+\
"starship, custodian of the\n"+\
"stolen plans that can save\n"+\
"her people and restore\n"+\
"freedom to the galaxy.... "\
,lsp=0,align=8,size=50)

# clip length doubled to 3000 frames to compensate for 0.5x scrolling speed

blur(0,1) # vertical blur to mitigate flicker

converttorgb32 # required for xyremap

xyremap(y="y n 0.5 * + 360 -",w=640,h=360) # w,h specify output width and height

converttoyv12 # or whatever is required


The above RPN expression is equivalent to y+n*0.5-360, where y is the input y coordinate, n is the current frame number, 0.5 is the scrolling speed (0.5 pixels per frame) and the -360 is to shift the input clip so it starts off the bottom of the screen.

Simply using Separatefields() & Weave() will mess up the subtitle's vertical size, I think.

It won't; by this point your subtitles have been rasterised to video pixels so it'd be just like interlacing any other progressive video.

David

foxyshadis
30th May 2014, 02:50
At the point of having enough subtitles to need an external file, especially if you have any special cases, maybe it's time to investigate SSA/ASS subtitle format with (xy-)VSFilter?

Floatingshed
30th May 2014, 08:24
[QUOTE=davidhorman;1682310]

Thanks for helping out.

xyremap does some great things, however I'm not sure that it can do what I want. In the current case the scrolling credits are over black so it works great but another project requires them to scroll over video. The example above will scroll the video too, I believe...

wonkey_monkey
30th May 2014, 20:54
Then you just ensure that the text has an alpha channel and use layer:

As above, then:


...,lsp=0,align=8,size=50)

# clip length doubled to 3000 frames to compensate for 0.5x scrolling speed

blur(0,1) # vertical blur to mitigate flicker

converttorgb32 # required for xyremap

mask(last,last.showgreen) # use the brightest channel (green) to generate an alpha channel for the RGB32 clip

xyremap(y="y n 0.5 * + 360 -",w=640,h=360) # w,h specify output width and height

background=version.bicubicresize(640,360).converttorgb32.loop(12) # test background image

layer(background,last) # apply the alpha-channelled, remapped text to the background image

converttoyv12 # or whatever is required

Though again there are things you might want to do to tidy the output up, like extending the alpha channel slightly so the text has a slight outer-stroke to it, separating it more clearly from the background image.