Advertisement
Seedmanc

im@s2 subtitle generator +q-boxes, names & frames

Aug 26th, 2013
355
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ffmpegSource2("C:\Users\Seedmanc\Desktop\guiminer\avisynth\imas_question_pause.mkv")
  2. global samples = ImageReader("C:\Users\Seedmanc\Desktop\guiminer\avisynth\subhelp\names.png", end=framecount-1, fps=framerate, pixel_type="y8").converttoyv12.mt_edge
  3. #^ Path to the pic with names http://puu.sh/4bqOU.png
  4.  
  5. #Settings:
  6. global workdir      ="C:\Users\Seedmanc\Desktop\guiminer\avisynth\"
  7. # ^ Folder where frames will be written to
  8. global filename     = "c:\Users\Seedmanc\Desktop\guiminer\avisynth\subhelp\subtitle.ass"
  9. global stringtemplate   = "Dialogue: 0,0:00:00.00,0:00:01.00,Style,Actor,0000,0000,0000,,"
  10. global shift        = 0 # Shift of subtitle line placement in milliseconds, relative to time of detection. Both starting and ending times are affected
  11. global mult     = 1.0   # Multiplier of subtitle line duration relative to detected on-screen duration. You'll likely want to increase it.
  12. global debug        = true  # Controls visual indication and writebuffer flushing. Without them script runs at ~450 fps.
  13. global overwrite    = false # Overwrites output file instead of appending to it. Useful while testing.
  14. global TBlowthr     = 185   # Detection lower threshold, separates textbox from darker background.
  15. # Raising will delay detection until textbox fully appears, but might fail to catch textboxes with lots of text.
  16. # Lower values might result in false positives on brighter backgrounds
  17. global TBhighthr    = 225   # Detection higher threshold, separates textbox from brighter flash-screens
  18. # Lower values ensure no false positives, but might delay detecting past the appearance of first few words on brighter backgrounds
  19. 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).
  20. # 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.
  21. global minlength    = 1000  # Minimum duration of legit detection in milliseconds, used to filter out accidental false positives.
  22. #/Settings.
  23.  
  24. function analyze(int cur_frame)
  25.     {  
  26.         mode    = "add"
  27.         method = "xor"
  28.         namebox = "
  29.     \      global n =  (n>=nmax)?0:n+1  
  30.     \      sample = samples.crop(0, n*nh, 0, nh)
  31.     \      dif =  rt_averageluma(mt_logic(narea, sample, method ).mt_deflate,n=cur_frame)
  32.     \      global nfound = (dif<10)
  33.     \   "
  34.         textbox = "
  35.     \   value = tarea.rt_averageluma(n=cur_frame )
  36.     \   global analyzed = (tblowthr<value && value<tbhighthr)
  37.     \   (analyzed && !nfound)?
  38.     \       eval(namebox)
  39.     \       :(nop)
  40.     \   (analyzed && debug)?
  41.     \       c.overlay(c.blankclip(width=tbw, height=tbh, color=$00FF00), x=tbx, y=tby, opacity=0.25, mode=mode).
  42.     \       overlay((nfound)?c.blankclip(width=nw*2, height=nh, color=$00FF00):c.crop(nx,ny,4,2), x=nx-6, y=ny, opacity=(nfound)?0.25:0, mode=mode)
  43.     \       :c
  44.     \   "  
  45.          
  46.         qbox = "
  47.         \   value = qarea.rt_averageluma(n=cur_frame)
  48.         \   global analyzed = (value>qbthr)
  49.         \   global yellow = (analyzed)?
  50.         \       (yarea.RT_AverageLuma(n=cur_frame)>qbthr)
  51.         \       :(yellow)
  52.         \   mark = c.blankclip(width=qw, height=qh, color=$00FF00)
  53.         \   (analyzed && debug)?
  54.         \       c.overlay(mark, x=qxb, y=qyb, opacity=0.33, mode=mode).
  55.         \       overlay(mark, x=qxr, y=qyr, opacity=0.33, mode=mode).
  56.         \       overlay((yellow)?mark:c.crop(qxy, qyy, 4, 2), x=qxy, y=qyy, opacity=(yellow)?0.33:0, mode=mode)
  57.         \       :c
  58.         \   "  
  59.            
  60.         return eval(rt_txtgetline("eval(textbox)"+chr(10)+"eval(qbox)",m ))
  61.     }  
  62.    
  63. function detect(int cur_frame)
  64.     {
  65.         (analyzed)?          
  66.         \   (detected)?    
  67.         \       nop
  68.         \      :eval("
  69.     \   global detected = true   
  70.     \       global startframe = cur_frame
  71.     \       global qbthr = qbthr-15
  72.     \       ")          
  73.     \  :(detected)?                      
  74.     \       eval("
  75.     \   global detected = false      
  76.     \   global endframe = cur_frame-1    
  77.     \   global startshow = startframe            
  78.     \   global qbthr = qbthr+15
  79.     \   validate()
  80.     \   ")    
  81.     \   :eval("global m = (m>=mmax)?0:m+1")  
  82.     }
  83.    
  84. function validate()
  85.     {  
  86.         global delta = endframe-startframe
  87.         global accepted = (delta>minlength)
  88.         (accepted)? eval("""     
  89.     \    c.writefile(filename, "prepareline(stringtemplate, startframe+shift, startframe+round(delta*mult)+shift)", append=true, flush=debug)
  90.     \    fname=rt_strreplace(frame2time(startframe+shift),":","-")
  91.     \    converttorgb24
  92.     \    imagewriter(file=workdir+fname+"%0.0f.jpg",type="jpg", info=debug)
  93.     \    converttoyv12""")           
  94.     \   :nop
  95.  
  96.     }
  97.  
  98. function prepareline(string s, int b, int e)
  99.     {
  100.         result = RT_StrReplace(s, "0:00:00.00", frame2time(b))
  101.         result = RT_StrReplace(result, "0:00:01.00", frame2time(e))
  102.         result = (m==1)?
  103.         \   (RT_StrReplace(result, "Style", "QB_Blue")+chr(10)
  104.         \    +(yellow?
  105.         \        RT_StrReplace(result, "Style", "QB_Yellow")+chr(10)
  106.         \       :"")
  107.         \    +RT_StrReplace(result, "Style", "QB_Red")
  108.         \   ).RT_StrReplace("Actor", "Q-Box")
  109.         \  :(m==0)?
  110.         \      (nfound)?
  111.         \          rt_strreplace(result,"Actor",rt_txtgetline(names,n))
  112.         \          :result
  113.         \     :result
  114.         global nfound=false          
  115.         global n = 0  
  116.         #these 2 lines must be inside of detect() after validate() call
  117.         #but Avisynth is retarded so I have to put them here for script to work
  118.         return result
  119.     }
  120.          
  121. function frame2time(int f)
  122.     {
  123.         rawtime = f/framerate  
  124.         hours = rawtime/3600.0
  125.         minutes = frac(hours)*60.0
  126.         seconds = frac(minutes)*60.0  
  127.         time = string(floor(hours), "%1.0f")+":"+string(floor(minutes), "%02.0f")+":"+string(seconds, "%05.2f")
  128.        
  129.         return time
  130.     }
  131.  
  132. # Textbox description
  133. global tbX = 238    global tbY = 584
  134. global tbW = 840    global tbH = 90
  135. global tarea = crop(tbx, tby, tbw, tbh).coloryuv(autogain=true)
  136. # Namebox description
  137. global names = \
  138. "Chihaya
  139. Hibiki
  140. Producer"
  141. global nfound = false
  142. global n = 0
  143. global nmax = RT_TxtQueryLines(names)-1
  144. global nx = 244     global ny = 552
  145. global nw = 62      global nh = 32
  146. global narea = crop(nx, ny, nw, nh).mt_edge
  147. # Questionboxes description
  148. global qw  = 308    global qh  = 120                    
  149. global qxb = 200    global qyb = 322                
  150. global qxr = 772    global qyr = qyb
  151. global qxy = 486    global qyy = 180
  152. bluebox = crop(qxb, qyb, qw, qh)      
  153. bluemask = bluebox.maskhs(starthue=360-60, endhue=360-20, maxsat=76, minsat=5).converttoyv12.mt_inflate.mt_expand
  154. redbox = crop(qxr, qyr, qw, qh)                        
  155. redmask = redbox. maskhs(starthue=80, endhue=120, maxsat=76, minsat=5).converttoyv12.mt_inflate.mt_expand
  156. global qarea = mt_logic(bluemask, redmask, mode="min")
  157. yellowbox = crop(qxy, qyy, qw, qh)    
  158. yellowmask = yellowbox.maskhs(starthue=130, endhue=160, maxsat=75, minsat=5).converttoyv12.mt_inflate.mt_expand
  159. global yarea = yellowmask
  160. global yellow = false
  161.  
  162. # Common variables
  163. global m = 0        global mmax = 1
  164. global framerate  = last.framerate
  165. global shift      = round(shift/1000.0*framerate)
  166. global minlength  = round(minlength/1000.0*framerate)
  167. global startframe = 0
  168. global startshow  = 0
  169. global endframe   = 0
  170. global analyzed   = false
  171. global detected   = false
  172. global accepted   = true
  173. writefilestart(filename, "chr(13)", append=!(overwrite))  
  174. global c      = last
  175.  
  176. # main()
  177. scriptclip("""  
  178.    analyze(current_frame)
  179.    detect(current_frame)
  180.    (debug)?
  181.    \   rt_subtitle(((nfound)?rt_txtgetline(names,n):"")+chr(13)+
  182.    \       frame2time(startshow)+" > "+frame2time(endframe)+chr(13)+
  183.    \       (accepted?"Accepted":"REJECTED"))
  184.    \  :last  
  185. """)
  186.  
  187.  #assumefps(450)    # Set Debug to false to get ~450 fps without visual indications (when you finished tuning the script and ready to process your videos).
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement