View Full Version : ShowSMPTE() for 50, 59.94 fps?
Adub
19th August 2008, 16:29
Hi, I am running some tests and it would be great if there was a way for ShowSMPTE() to support framerates over 30.
I am trying to generate some 1920x1080 png's, about 400 of them, using the ShowSMPTE() and ImageWriter() functions.
I need these to be in both the HD PAL format as well as HD NTSC, thus the reason for 50 and 59.94.
Anyone know how this can be done?
mikeytown2
19th August 2008, 20:24
Here's a quick start for you
Function SMPTE(clip c)
{
c.ScriptClip("""subtitle(string(Int(current_frame/framerate)) + ":" + String(current_frame%Round(framerate)))""")
}
Adub
19th August 2008, 20:29
Ah, so that's how you go about doing it. I have never used ScriptClip before, but it seems simple enough. Thanks!
mikeytown2
19th August 2008, 20:57
Here's better version
Function SMPTE(clip c)
{
c.ScriptClip("""subtitle(string(Int(current_frame/framerate)) + ":" + String(int(current_frame%Round(framerate)/10.0)) + String(current_frame%10))""")
}
Post the final one u use if it's different, I'm sure your not the first one who has had this issue.
Adub
19th August 2008, 21:46
Hmm... It seems that Mug Funky came up with one years ago. It's not bad.
#
# 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
int(hours+mins+secs+frames)
}
function itc (int "framecount", float "rate", bool "ms")
{
rate=default(rate,25)
ms = default(ms, false)
drop = (rate==29.97)? true : false
rate2 = (drop==true)? 30 : rate
hours=floor((framecount/rate)/3600)%60
mins=floor((framecount/rate)/60.0)%60
secs=floor(framecount/rate)%60
milli=floor(1000*framecount/rate)%6000%1000
fmilli=framecount/rate - floor(framecount/rate)
#frames=floor(fmilli*rate2)
frames=framecount%int(rate)
dframes = (drop==false)? frames : (secs==0)&&(mins%10!=0)? floor(fmilli*rate2) + 2 : frames
return (ms==false)? (string(hours,"%02.0f")+":"+string(mins,"%02.0f")+":"+string(secs,"%02.0f")+":"+string(frames,"%02.0f")) :
\ (string(hours,"%02.0f")+":"+string(mins,"%02.0f")+":"+string(secs,"%02.0f")+":"+string(milli,"%03.0f"))
}
function super (clip c, string "offset", bool "ms")
{
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
ms = default(ms, false)
offset = default(offset,"00:00:00:00")
global offset = tc(offset)
global ms = ms
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, ms=ms)),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)
}
mikeytown2
19th August 2008, 21:54
ColorBars()
Bob()
super()
It's off by one frame per second or so.
Adub
19th August 2008, 22:33
Uh, it shouldn't be. Remember it's zero-based.
Edit: Also I changed the script back to it's defaults, as I was actually blowing up the output for my purposes.
mikeytown2
19th August 2008, 22:34
ColorBars()
ShowSMPTE()
super()
Simple Compare
Adub
19th August 2008, 22:42
Hmm...That is interesting. It seems that MugFunky's script resets to 00 on the 29th frame and then counts to one second.
Edit: I think it has something to do with the drop-frame theory. It works fine for 23.976.
Gavino
20th August 2008, 08:49
It works fine for 23.976.
I'm afraid it doesn't.
I get inconsistencies in the output of this script
ColorBars().AssumeFPS(23.976)
ShowSMPTE()
super()
The code as written only really works for integral framerates.
Even then, I can see that offset is wrongly interpreted for rates other than 25 - it should be setting offset=tc(offset, rate).
It's also a classic example of the 'variable scoping' problems you can get using ScriptClip in a function.
The author has had to introduce four global variables to pass values into the run-time script ("Subtitle(...)"). However, because the run-time script is evaluated at a later point in time, this will go wrong (the wrong values will be used) if the function is called more than once with different parameters (eg offset), or even if you happen to have a script-level variable with the same name as any of the globals.
If you use my GRunT plugin, you can forget about these problems.
IanB
20th August 2008, 12:24
Note! ShowSMPTE(23.976) is an Avisynth special. There is no definition (at least that I can find) about how to do the drop count for the NTSC Film rate. I just implemented a progression average approach so that 86313.686 frames in 1 hour counts as 86400, like for 29.97 107892.108 frames in 1 hour counts as 108000. The drop pattern occurs such that the error is never more than 0.5 count i.e. when the error is 0.5 count I jump a 1 count so the error then become -0.5 count. SMTPE(29.97) dictates that you jump 2 counts at the start of each minute but not for the 10's of minutes.
Adub
20th August 2008, 16:08
Well, crap. Here I thought that I found the ultimate solution, posted by the master Mug Funky nonetheless, and yet it is repeatedly shown that I am wrong.
I can't fix this script, as I do not have the time. If someone who understands avisynth scripting, and GRunT, then by all means, go nuts!!!
It also looks like what I was originally going to use it for isn't truly necessary. If anything may just end up using mikeytown2's example script and play with it for my own purposes.
Gavino
20th August 2008, 20:05
I can't fix this script, as I do not have the time. If someone who understands avisynth scripting, and GRunT, then by all means, go nuts!!!
The GRunT part is easy (GRunT does the grunt work ;)).
Delete the word 'global' everywhere and change the ScriptClip line to
box = ScriptClip(box,
\ "Subtitle(String(itc(current_frame+offset, rate, ms=ms)),align=2,y=int(.225*bheight) + bheight/2, size=round(.45*bheight), spc=int(.3*bheight), text_color=$ffffff)",
\ args="offset, rate, ms, bheight")
# voila!
Add the offset fix I mentioned earlier too, and at least you've got a robust version that works for 50fps (and other integral framerates).
I haven't got time to figure out the 59.94 case, particularly since I don't know how the 'drop frame' thing should work for this rate.
mikeytown2
21st August 2008, 22:55
Different code base
http://niiyan.net/?ShowTimeCode
Fairly sure it doesn't use drop-frame timecode.
http://avisynth.org/mediawiki/ShowFrameNumber#ShowSMPTE
Gavino
21st August 2008, 23:49
Different code base
http://niiyan.net/?ShowTimeCode
Fairly sure it doesn't use drop-frame timecode.
To quote from that page -
Note: timecode generated by this function may be slightly different from actual timecode because of rounding floating point numbers.
- ie it doesn't do the difficult part. :(
It's also afflicted with the ScriptClip global variable disease.
But OK, it's probably fine for casual use.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.