Mug Funky
8th May 2005, 15:38
hi all.
i've been asked a few times to make an encode with the video's timecodes burnt in - usually for subtitling purposes. i thought it'd be useful to be able to do this in software, so i wrote this.
it's pretty modest as far as functions go, but could be useful for subtitling, as it's fast enough to work in realtime using ffdshow's avisynth processing, so one needn't use virtualdub when subbing. also, it's nice and big.
it's named "super" after the timecode-superimposed outputs on some tape decks.
#
# Mug's Timecode stuff.
#
# tc:
# enter a timecode string in quotes, and out comes an integer frame number.
#
# itc:
# reverse of tc - enter a frame number, and out comes a SMPTE timecode.
#
# - for both of these, you can enter a framerate as well (last.framerate is useful)
#
#
# super:
# outputs a SMPTE timecode in a shaded box. useful for subtitling.
#
# - you can also enter a "start timecode" in quotes (like "10:00:00:00")
# which helps if you're syncing with a tape's timecode.
#
function tc (string "timecode", float "rate")
{
rate=default(rate,25)
frames=value(rightstr(timecode,2))
secs=value(rightstr(timecode,5).leftstr(2))*rate
mins=value(rightstr(timecode,8).leftstr(5))*60*rate
hours=value(rightstr(timecode,11).leftstr(8))*60*60*rate
return int(hours+mins+secs+frames)
}
function itc (int "framecount", float "rate")
{
rate=default(rate,25)
Fhours=((framecount/60.0)/60.0)/rate
hours=floor(Fhours)
Fmins=(Fhours - hours)*60.0
mins=floor(Fmins)
Fsecs=(Fmins - mins)*60.0
secs=floor(Fsecs)
frames=round((Fsecs-secs)*rate)
return(string(hours,"%02.0f")+":"+string(mins,"%02.0f")+":"+string(secs,"%02.0f")+":"+string(frames,"%02.0f"))
}
function super (clip c, string "offset")
{
global rate = c.framerate
global bheight=int(c.height*0.15/4)*4
bwidth=int(c.width*0.4/4)*4
off=int(c.height*0.15/4)*4
offset = default(offset,"00:00:00:00")
global offset = tc(offset)
box=c.crop((c.width-bwidth)/2, c.height-(bheight+off), bwidth, bheight).levels(0,1,255,0,160)
left=c.crop(0, 0, (c.width-bwidth)/2, 0)
right=c.crop((c.width-bwidth)/2 + bwidth, 0, (c.width-bwidth)/2, 0)
top=c.crop((c.width-bwidth)/2, 0, bwidth, c.height-(bheight+off))
bottom=c.crop((c.width-bwidth)/2, c.height-off, bwidth, off)
box = ScriptClip(box, "Subtitle(String(itc(current_frame+offset, rate)),align=2,y=int(.225*bheight) + bheight/2, size=round(.45*bheight), spc=int(.3*bheight), text_color=$ffffff)")
middle=stackvertical(top,box,bottom)
stackhorizontal(left,middle,right)
}
instructions are in the script... hopefully they're not too brief.
hope someone finds this useful :)
[edit]
hmm... seems to behave strangely with non-integer framerates (like 29.97 for instance). hehe... i can't be bothered fixing this just now as it works fine for PAL, and PAL is all i'll be using it for. also i have a headache :)
i've been asked a few times to make an encode with the video's timecodes burnt in - usually for subtitling purposes. i thought it'd be useful to be able to do this in software, so i wrote this.
it's pretty modest as far as functions go, but could be useful for subtitling, as it's fast enough to work in realtime using ffdshow's avisynth processing, so one needn't use virtualdub when subbing. also, it's nice and big.
it's named "super" after the timecode-superimposed outputs on some tape decks.
#
# Mug's Timecode stuff.
#
# tc:
# enter a timecode string in quotes, and out comes an integer frame number.
#
# itc:
# reverse of tc - enter a frame number, and out comes a SMPTE timecode.
#
# - for both of these, you can enter a framerate as well (last.framerate is useful)
#
#
# super:
# outputs a SMPTE timecode in a shaded box. useful for subtitling.
#
# - you can also enter a "start timecode" in quotes (like "10:00:00:00")
# which helps if you're syncing with a tape's timecode.
#
function tc (string "timecode", float "rate")
{
rate=default(rate,25)
frames=value(rightstr(timecode,2))
secs=value(rightstr(timecode,5).leftstr(2))*rate
mins=value(rightstr(timecode,8).leftstr(5))*60*rate
hours=value(rightstr(timecode,11).leftstr(8))*60*60*rate
return int(hours+mins+secs+frames)
}
function itc (int "framecount", float "rate")
{
rate=default(rate,25)
Fhours=((framecount/60.0)/60.0)/rate
hours=floor(Fhours)
Fmins=(Fhours - hours)*60.0
mins=floor(Fmins)
Fsecs=(Fmins - mins)*60.0
secs=floor(Fsecs)
frames=round((Fsecs-secs)*rate)
return(string(hours,"%02.0f")+":"+string(mins,"%02.0f")+":"+string(secs,"%02.0f")+":"+string(frames,"%02.0f"))
}
function super (clip c, string "offset")
{
global rate = c.framerate
global bheight=int(c.height*0.15/4)*4
bwidth=int(c.width*0.4/4)*4
off=int(c.height*0.15/4)*4
offset = default(offset,"00:00:00:00")
global offset = tc(offset)
box=c.crop((c.width-bwidth)/2, c.height-(bheight+off), bwidth, bheight).levels(0,1,255,0,160)
left=c.crop(0, 0, (c.width-bwidth)/2, 0)
right=c.crop((c.width-bwidth)/2 + bwidth, 0, (c.width-bwidth)/2, 0)
top=c.crop((c.width-bwidth)/2, 0, bwidth, c.height-(bheight+off))
bottom=c.crop((c.width-bwidth)/2, c.height-off, bwidth, off)
box = ScriptClip(box, "Subtitle(String(itc(current_frame+offset, rate)),align=2,y=int(.225*bheight) + bheight/2, size=round(.45*bheight), spc=int(.3*bheight), text_color=$ffffff)")
middle=stackvertical(top,box,bottom)
stackhorizontal(left,middle,right)
}
instructions are in the script... hopefully they're not too brief.
hope someone finds this useful :)
[edit]
hmm... seems to behave strangely with non-integer framerates (like 29.97 for instance). hehe... i can't be bothered fixing this just now as it works fine for PAL, and PAL is all i'll be using it for. also i have a headache :)