SHOW:
|
|
- or go back to the newest paste.
| 1 | - | function frame2time(clip c, int f) |
| 1 | + | ffmpegSource2("C:\Users\Seedmanc\Desktop\guiminer\avisynth\imas_question_pause.mkv")
|
| 2 | - | {
|
| 2 | + | |
| 3 | - | rawtime = f/c.framerate |
| 3 | + | |
| 4 | - | hours = rawtime/3600.0 |
| 4 | + | global filename = "c:\Users\Seedmanc\Desktop\guiminer\avisynth\subhelp\subtitle.ass" |
| 5 | - | minutes = frac(hours)*60.0 |
| 5 | + | global stringtemplate = "Dialogue: 0,0:00:00.00,0:00:01.00,Style,Actor,0000,0000,0000,," |
| 6 | - | seconds = frac(minutes)*60.0 |
| 6 | + | global shift = 0 # Shift of subtitle line placement in milliseconds, relative to time of detection. Both starting and ending times are affected |
| 7 | - | time = string(floor(hours), "%1.0f")+":"+string(floor(minutes), "%02.0f")+":"+string(seconds, "%05.2f") |
| 7 | + | global mult = 1.0 # Multiplier of subtitle line duration relative to detected on-screen duration. You'll likely want to increase it. |
| 8 | global debug = true # Controls visual indication and writebuffer flushing. Without them script runs at ~600 fps. | |
| 9 | - | return time |
| 9 | + | global overwrite = false # Overwrites output file instead of appending to it. Useful while testing. |
| 10 | - | } |
| 10 | + | global TBlowthr = 185 # Detection lower threshold, separates textbox from darker background. |
| 11 | # Raising will delay detection until textbox fully appears, but might fail to catch textboxes with lots of text. | |
| 12 | - | function prepareline(clip c, string s, int b, int e) |
| 12 | + | |
| 13 | - | {
|
| 13 | + | global TBhighthr = 225 # Detection higher threshold, separates textbox from brighter flash-screens |
| 14 | - | result = RT_StrReplace(s, "0:00:00.00", frame2time(c, b)) |
| 14 | + | |
| 15 | - | result = RT_StrReplace(result, "0:00:01.00", frame2time(c, e)) |
| 15 | + | global QBthr = 150 # Detection threshold for questionboxes, lower values - sooner happening and longer lasting detection at the cost of higher false positive chance (it's pretty low though). |
| 16 | # Depends on the background, so having an idol in blue clothes on the left and another one in red on the right => more error chances. | |
| 17 | - | return result |
| 17 | + | global minlength = 1000 # Minimum duration of legit detection in milliseconds, used to filter out accidental false positives. |
| 18 | - | } |
| 18 | + | #/Settings. |
| 19 | ||
| 20 | - | ffmpegSource2("C:\Users\Seedmanc\Desktop\guiminer\avisynth\imas_question_pause.mkv")
|
| 20 | + | function analyze(int cur_frame) |
| 21 | {
| |
| 22 | mode = "add" | |
| 23 | - | filename = "c:\Users\Seedmanc\Desktop\guiminer\avisynth\subhelp\subtitle.ass" |
| 23 | + | textbox = " |
| 24 | - | stringtemplate = "Dialogue: 0,0:00:00.00,0:00:01.00,Style,Actor,0000,0000,0000,," |
| 24 | + | \ value = tarea.rt_averageluma(n=cur_frame ) |
| 25 | - | overwrite = true # Overwrites output file instead of appending to it. Useful while testing. |
| 25 | + | \ global analyzed = (tblowthr<value && value<tbhighthr) |
| 26 | - | debug = true # Controls visual indication and writebuffer flushing. Without them script runs at ~600 fps. |
| 26 | + | \ (analyzed && debug)? |
| 27 | - | shift = 0 # Shift of subtitle line placement in milliseconds, relative to time of detection. Both starting and ending times are affected |
| 27 | + | \ c.overlay(c.blankclip(width=tbw, height=tbh, color=$00FF00), x=tbx, y=tby, opacity=0.25, mode=mode) |
| 28 | - | mult = 1.0 # Multiplier of subtitle line duration relative to detected textbox on-screen duration. You'll likely want to increase it. |
| 28 | + | \ :c |
| 29 | - | lowthr = 185 # Detection lower threshold, separates textbox from darker background. |
| 29 | + | \ " |
| 30 | ||
| 31 | qbox = " | |
| 32 | - | highthr = 225 # Detection higher threshold, separates textbox from brighter flash-screens |
| 32 | + | \ value = qarea.rt_averageluma(n=cur_frame) |
| 33 | \ global analyzed = (value>qbthr) | |
| 34 | - | minlength = 1000 # Minimum duration of legit textbox appearance in milliseconds, used to filter out accidental false positives on flash-screens. |
| 34 | + | \ global yellow = (analyzed)? |
| 35 | - | # Textbox will flash green if the detection was accepted or red if it was discarded. |
| 35 | + | \ (yarea.RT_AverageLuma(n=cur_frame)>qbthr) |
| 36 | \ :(yellow) | |
| 37 | - | tbX = 238 |
| 37 | + | \ mark = c.blankclip(width=qw, height=qh, color=$00FF00) |
| 38 | - | tbY = 584 |
| 38 | + | \ (analyzed && debug)? |
| 39 | - | tbW = 842 |
| 39 | + | \ c.overlay(mark, x=qxb, y=qyb, opacity=0.33, mode=mode). |
| 40 | - | tbH = 92 |
| 40 | + | \ overlay(mark, x=qxr, y=qyr, opacity=0.33, mode=mode). |
| 41 | \ overlay((yellow)?mark:c.crop(qxy, qyy, 4, 2), x=qxy, y=qyy, opacity=(yellow)?0.33:0, mode=mode) | |
| 42 | - | shift = round(shift/1000.0*framerate) |
| 42 | + | \ :c |
| 43 | - | minlength = round(minlength/1000.0*framerate) |
| 43 | + | \ " |
| 44 | - | startframe = 0 |
| 44 | + | |
| 45 | - | startshow = 0 |
| 45 | + | return eval(rt_txtgetline("eval(textbox)"+chr(10)+"eval(qbox)",n ))
|
| 46 | - | endframe = 0 |
| 46 | + | } |
| 47 | - | delta = 0 |
| 47 | + | |
| 48 | - | textbox = crop(tbx, tby, tbw, tbh).coloryuv(autogain=true, autowhite=true) |
| 48 | + | function detect(int cur_frame) |
| 49 | - | detected = false |
| 49 | + | {
|
| 50 | - | accepted = true |
| 50 | + | (analyzed)? |
| 51 | - | begin = """ detected = true \ |
| 51 | + | \ (detected)? |
| 52 | - | startframe = current_frame """ |
| 52 | + | \ nop |
| 53 | - | end = """ detected = false \ |
| 53 | + | \ :eval("
|
| 54 | - | endframe = current_frame \ |
| 54 | + | \ global detected = true |
| 55 | - | startshow = startframe """ |
| 55 | + | \ global startframe = cur_frame |
| 56 | - | reject = """ accepted = false \ |
| 56 | + | \ global qbthr = qbthr-15 |
| 57 | - | overlay(blankclip(width=tbw, height=tbh, color=$FF0000), x=tbx, y=tby) """ |
| 57 | + | \ ") |
| 58 | - | checkdif = """ eval("delta=endframe-startframe
|
| 58 | + | \ :(detected)? |
| 59 | - | (delta>minlength)? \ |
| 59 | + | \ eval("
|
| 60 | - | eval(write): \ |
| 60 | + | \ global detected = false |
| 61 | - | eval(reject) |
| 61 | + | \ global endframe = cur_frame |
| 62 | - | ") """ |
| 62 | + | \ global startshow = startframe |
| 63 | - | write = """ writefile(filename, "prepareline(last, stringtemplate, startframe+shift, startframe+round(delta*mult)+shift)", append=true, flush=debug) \ |
| 63 | + | \ global qbthr = qbthr+15 |
| 64 | - | overlay(blankclip(width=tbw, height=tbh, color=$00FF00), x=tbx, y=tby) \ |
| 64 | + | \ validate() |
| 65 | - | accepted = true """ |
| 65 | + | \ ") |
| 66 | - | ind = (debug)?""" overlay(blankclip(width=tbw, height=tbh, color=$00FF00), x=tbx, y=tby, opacity=0.25, mode="add") """ :"" |
| 66 | + | \ :eval("global n = (n>=nmax)?0:n+1")
|
| 67 | - | scriptclip("""
|
| 67 | + | } |
| 68 | - | status=accepted?"Accepted":"REJECTED" |
| 68 | + | |
| 69 | - | last=(debug)?rt_subtitle(frame2time(startshow)+" > "+frame2time(endframe)+chr(13)+status):last |
| 69 | + | function validate() |
| 70 | - | tal=textbox.rt_averageluma |
| 70 | + | {
|
| 71 | - | (tal>lowthr && tal<highthr)? \ |
| 71 | + | global delta = endframe-startframe |
| 72 | - | eval(ind+"(detected==false)? \ |
| 72 | + | global accepted = (delta>minlength) |
| 73 | - | eval(begin):last \ |
| 73 | + | (accepted)? |
| 74 | - | ") \ |
| 74 | + | \ c.writefile(filename, "prepareline(stringtemplate, startframe+shift, startframe+round(delta*mult)+shift)", append=true, flush=debug) |
| 75 | - | :(detected==true)? \ |
| 75 | + | \ :nop |
| 76 | - | eval(end+checkdif):nop |
| 76 | + | } |
| 77 | - | last |
| 77 | + | |
| 78 | function prepareline(string s, int b, int e) | |
| 79 | {
| |
| 80 | - | # assumefps(600) # Set Debug to false to get ~600 fps without visual indications (when you finished tuning the script and ready to process your videos). |
| 80 | + | result = RT_StrReplace(s, "0:00:00.00", frame2time(b)) |
| 81 | result = RT_StrReplace(result, "0:00:01.00", frame2time(e)) | |
| 82 | result = (n==1)? | |
| 83 | \ (RT_StrReplace(result, "Style", "QB_Blue")+chr(10) | |
| 84 | \ +(yellow? | |
| 85 | \ RT_StrReplace(result, "Style", "QB_Yellow")+chr(10) | |
| 86 | \ :"") | |
| 87 | \ +RT_StrReplace(result, "Style", "QB_Red") | |
| 88 | \ ).RT_StrReplace("Actor", "Q-Box")
| |
| 89 | \ :result | |
| 90 | ||
| 91 | return result | |
| 92 | } | |
| 93 | ||
| 94 | function frame2time(int f) | |
| 95 | {
| |
| 96 | rawtime = f/framerate | |
| 97 | hours = rawtime/3600.0 | |
| 98 | minutes = frac(hours)*60.0 | |
| 99 | seconds = frac(minutes)*60.0 | |
| 100 | time = string(floor(hours), "%1.0f")+":"+string(floor(minutes), "%02.0f")+":"+string(seconds, "%05.2f") | |
| 101 | ||
| 102 | return time | |
| 103 | } | |
| 104 | ||
| 105 | # Textbox description | |
| 106 | global tbX = 238 global tbY = 584 | |
| 107 | global tbW = 840 global tbH = 90 | |
| 108 | global tarea = crop(tbx, tby, tbw, tbh).coloryuv(autogain=true) | |
| 109 | # Questionboxes description | |
| 110 | global qw = 308 global qh = 120 | |
| 111 | global qxb = 200 global qyb = 322 | |
| 112 | global qxr = 772 global qyr = qyb | |
| 113 | global qxy = 486 global qyy = 180 | |
| 114 | bluebox = crop(qxb, qyb, qw, qh) | |
| 115 | bluemask = bluebox.maskhs(starthue=360-60, endhue=360-20, maxsat=76, minsat=5).converttoyv12.mt_inflate.mt_expand | |
| 116 | redbox = crop(qxr, qyr, qw, qh) | |
| 117 | redmask = redbox. maskhs(starthue=80, endhue=120, maxsat=76, minsat=5).converttoyv12.mt_inflate.mt_expand | |
| 118 | global qarea = mt_logic(bluemask, redmask, mode="min") | |
| 119 | yellowbox = crop(qxy, qyy, qw, qh) | |
| 120 | yellowmask = yellowbox.maskhs(starthue=130, endhue=160, maxsat=75, minsat=5).converttoyv12.mt_inflate.mt_expand | |
| 121 | global yarea = yellowmask | |
| 122 | global yellow = false | |
| 123 | ||
| 124 | # Common variables | |
| 125 | global n = 0 global nmax = 1 | |
| 126 | global framerate = last.framerate | |
| 127 | global shift = round(shift/1000.0*framerate) | |
| 128 | global minlength = round(minlength/1000.0*framerate) | |
| 129 | global startframe = 0 | |
| 130 | global startshow = 0 | |
| 131 | global endframe = 0 | |
| 132 | global analyzed = false | |
| 133 | global detected = false | |
| 134 | global accepted = true | |
| 135 | writefilestart(filename, "chr(13)", append=!(overwrite)) | |
| 136 | global c = last | |
| 137 | ||
| 138 | # main() | |
| 139 | scriptclip("""
| |
| 140 | analyze(current_frame) | |
| 141 | detect(current_frame) | |
| 142 | (debug)? | |
| 143 | \ rt_subtitle(frame2time(startshow)+" > "+frame2time(endframe)+chr(13)+(accepted?"Accepted":"REJECTED")) | |
| 144 | \ :last | |
| 145 | """) | |
| 146 | ||
| 147 | #assumefps(500) # Set Debug to false to get ~500 fps without visual indications (when you finished tuning the script and ready to process your videos). |