SetFilterMTMode("DEFAULT_MT_MODE", MT_MULTI_INSTANCE) # The downloadable/HD encoding script # http://tasvideos.org/EncodingGuide/PublicationManual.html AviSource("") # Dolphin (with FFMPEG). Use FFV1 patch for dumping: # https://github.com/vadosnaprimer/dolphin/releases # AviSource("movie.avi", pixel_type="RGB24") # AudioDub(last, wavsource("dspdump.wav")) preview = false # Set true for 1080p downscale = false # Set to downscale high res source for SD encodes (set extra hq w/h) trimFrame = 654321 # manual, discards logo lengh automatically handHeld = false # auto, but set it for preview hd = false # auto, but set it for preview halfFPS = false # for games that "lag" every other frame stackNDS = false # stack one of NDS screens near both of them for HD global vb = false # for Virtual Boy encodes # Resizer (for hd upscaling and multisegment import) resizer = hd ? "Point" : "Lanczos" # force Lanczos for 3D footage with increased internal resolution # resizer = "Lanczos" # Subtitles contents game = "gamename" branch = "'branch'" # lowercase for usual words, capital for in-game capital words. when blank, leave "''" author = "author" time = "00:00.00" rerecords = "0" # Subtitles timing and placement subFF = 600 # first subtitles frame, set manually! subAlign = 8 # subtitles horizontal alignment (7/8/9) subEntry = 2 # sets the number of sub entries (2/3/4) subYpos = 0 # subtitles vertical position subXoffs = 0 # subtitles horizontal offset (can be negative) subLengthMul = 5.00 # entry length in seconds (fractions work) subFF2delay = 0 # extra delay in frames between subtitle entries 1 and 2 subFF2delay2 = 0 # extra delay in frames between subtitle entries 2 and 3 subFF2delay3 = 0 # extra delay in frames between subtitle entries 3 and 4 subFont = "helv" # see "fonts" folder for available types bighaloCutoff = 384 # width and height above this will use bighalo instead of freesub # Subtitle fades fadeIn1 = 0 # number of frames to fade in subtitle entry 1 from black (set to 0 to disable fade) fadeIn2 = 0 # number of frames to fade in subtitle entry 2 from black fadeIn3 = 0 # number of frames to fade in subtitle entry 3 from black fadeIn4 = 0 # number of frames to fade in subtitle entry 4 from black fadeOut1 = 0 # number of frames to fade out subtitle entry 1 to black (set to 0 to disable fade) fadeOut2 = 0 # number of frames to fade out subtitle entry 2 to black fadeOut3 = 0 # number of frames to fade out subtitle entry 3 to black fadeOut4 = 0 # number of frames to fade out subtitle entry 4 to black # Multisegment import (upscales hires segments straight to HD when needed) # requires normally importing a sample whose attributes it will use for all segments ms = true # enable multisegment import ms_base = "" # common string for all segment names ms_start = 0 # number of the first segment ms_end = 15 # number of the last segment ms_format = "%1.0f" # string format: http://avisynth.nl/index.php/Internal_functions#String # Extra HQ (upscaled downloadable encodes) hq = false # auto hq_scale = 2 # manual for now hq_hiResSrc = false # we downscale hires 3D source, and upscale lowres pixelated source hq_baseWidth = 320 # aspect-corrected 1x width (only for hires source) hq_baseHeight = 240 # aspect-corrected 1x height (only for hires source) # Aspect ratio correction wAspect = 4 hAspect = 3 # Subtitles text subString1 = game + "\n" \ + (branch == "''" ? "" : branch + "\n") \ + "Played by " + author subString2 = "Playing time: " + time \ + "\nRerecord count: " + rerecords subString3 = "This is a tool-assisted recording." \ subString4 = "For details, visit http://TASVideos.org/" ################ # LEGACY STUFF # ################ # Famtasia # ConvertAudioTo16bit() # Mupen64 # ResampleAudio(last, 44100) # Crop(0,0,-0,-20) # when old Glide64 is used # PSXjin # audio = WavSource("movie_000.wav") # AudioDub(audio, last) # Old Dolphin (remove /* and */ to uncomment) # get values at http://tasvideos.org/forum/viewtopic.php?p=373299#373299 /* M = 486000000 F = 60 k = 1 N = 525 b = 0 D = (k * N + b) * floor(floor(M / F) / N) # don't edit this formula LoadCPlugin("./programs/timecodefps.dll") video = last.TimecodeFPS("timecodes.txt", fpsnum=M, fpsden=D) audio = \ WavSource("dspdump0.wav") + \ WavSource("dspdump1.wav").ResampleAudio(32000) + \ WavSource("dspdump.wav") */ # Fix progressing (not floating) desync # AssumeFPS(last.FrameCount / last.AudioLengthF * last.AudioRate) ###################### # AUTOMATED SETTINGS # ###################### ConvertToRGB32() # Add 1 scanline if height is uneven (ntsc sms, pal c64) last.height % 2 > 0 ? StackVertical(last, Crop(0, Height-1, 0, 0)) : 0 pass = 0 i444 = false originalWidth = last.width originalHeight = last.height hdvb = hd && vb root = ScriptDir() Import (root + "\programs\functions.avsi") #LoadPlugin (root + "programs\ExactDedup.dll") #LoadPlugin (root + "programs\mvtools2.dll") #LoadPlugin (root + "programs\mt_masktools-26.dll") #LoadPlugin (root + "programs\autolevels_0.6_20110109.dll") #LoadCPlugin(root + "programs\freesub.dll") #LoadCPlugin(root + "programs\assrender.dll" ) # Make too dark scenes brighter # AutoLevels(filterRadius=1000, sceneChgThresh=200, gamma=1.1) # VirtualBoy (bizhawk only!) # http://tasvideos.org/forum/viewtopic.php?p=435440#435440 left = vb ? Crop( 0, 0, 384, 224).Levels(0, 1, 255, 0, 157) : 0 right = vb ? Crop(384, 0, 384, 224).Levels(0, 1, 255, 0, 157) : 0 vb ? hd ? 0 : Anaglyph(left, right, "grey").AudioDub(left) : 0 # Pick logo file file = hd || hq \ ? vb \ ? "logoGrey.png" \ : stackNDS \ ? "logohdnds.png" \ : last.height == 384 \ ? "logonds.png" \ : "hdlogo.gif" \ : last.height == 384 \ ? "logonds.png" \ : "sdlogo.gif" # file = !hd ? "logo34.png" : "hdlogo34.png" # Stack 3 NDS screens upperScreen = last.Crop(0, 0, -0, last.height/2) lowerScreen = last.Crop(0, last.height/2, -0, -0) halfScreen = upperScreen # set which NDS screen to put as main stackNDS && hd ? StackHorizontal(halfScreen.PointResize(last.width*2, last.height), last) : 0 # Aspect ratio correction for SD encodes height = handHeld \ ? last.height \ : last.width > last.height * wAspect / hAspect \ ? last.width * hAspect / wAspect \ : last.height width = handHeld \ ? last.width \ : height * wAspect / hAspect width = width % 4 == 1 ? width + 3 \ : width % 4 == 2 ? width + 2 \ : width % 4 == 3 ? width + 1 : width height = height % 4 == 1 ? height + 3 \ : height % 4 == 2 ? height + 2 \ : height % 4 == 3 ? height + 1 : height # Remember SD frame size for subYpos HD tweaks wARC = width hARC = height # Actually go HD if we need height = hd ? (preview ? 1080 : 2160) : height width = handHeld \ ? height * last.width / last.height \ : height * wAspect / hAspect width = width % 4 == 1 ? width + 3 : \ width % 4 == 2 ? width + 2 : \ width % 4 == 3 ? width + 1 : width # Rescaling # extra HQ: # hires source: downscale straight to aspect-corrected res with lanczos # lowres source: upscalse by our factor with point, then do ARC with lanczos for 512kb # hd: # resize to 4K, then just subsample with lanczos in the end # for hires 3D footage, upscaled with lanczos # handheld and primary (dedupped): do nothing # 512kb: do ARC with lanczos resized = hq && !hd \ ? hq_hiResSrc \ ? Lanczos4Resize(hq_baseWidth * hq_scale, hq_baseHeight * hq_scale) \ : handHeld || pass != 0 \ ? PointResize(last.width * hq_scale, last.height * hq_scale) \ : PointResize(last.width * hq_scale, last.height * hq_scale) \ .Lanczos4Resize(width * hq_scale, height * hq_scale) \ : hd \ ? eval(resizer+"Resize(width, height)") \ : handHeld || pass != 0 \ ? last \ : Lanczos4Resize(width, height) # If ms enabled, we use parameters of "resized" to apply to all segments resized = ms ? resized.AppendSegment(ms_base, ms_start, ms_end, ms_format, resizer).ConvertToRGB32() : resized # Downscale for high res source and SD encodes resized = downscale ? hd ? resized : AreaResize(resized, hq_baseWidth, hq_baseHeight) : resized # Logo logoVideo = ImageSourceAnim(file=file, fps=60.0).ConvertToRGB32().ChangeFPS(resized) logoAudio = BlankClip(logoVideo, audio_rate=resized.AudioRate, channels=resized.AudioChannels) logo = AudioDub(logoVideo, logoAudio).Lanczos4Resize(resized.width, resized.height) last = hdvb ? logo.PointResize(resized.width / 2, resized.height) : logo ++ resized # Virtual Boy left = hdvb ? last ++ left.PointResize(last.width, last.height) : 0 right = hdvb ? last ++ right.PointResize(last.width, last.height) : 0 # Additional subtitle magic # figure out how much our font will be changed after x264 ARC and for HD wFactor = hd || hq ? float(last.width) / wARC : 1 hFactor = hd || hq ? float(last.height) / hARC : 1 wStretch = (handHeld || pass == 0) && !hdvb ? 1 \ : (float(last.width) / last.height) / (float(wAspect) / hAspect) smallerSide = last.height < last.width ? last.height : last.width biggerSide = last.height > last.width ? last.height : last.width # use bighalo if we're relatively hires # or if font stretch on some side is too heavy (ARCed primary) global useBighalo = biggerSide > bighaloCutoff \ || ((wStretch < 0.8 || wStretch > 1.3) \ && !handHeld && pass != 0 \ && smallerSide >= 224) # Subtitles variables subXoffs = int(subXoffs * wStretch) subRatio = float(last.height) / 21 #subRatio = float(smallerSide) / 21 subXpos = subAlign == 7 || subAlign == 4 || subAlign == 1 \ ? (2 + subXoffs) * wFactor \ : subAlign == 8 || subAlign == 5 || subAlign == 2 \ ? last.width / 2 + subXoffs * wFactor \ : last.width - (2 + subXoffs) * wFactor subXpos = hdvb ? subXpos / 2 : subXpos subYpos = int(float(subYpos) / (wStretch > 1 ? wStretch : 1) * hFactor) subYpos = hdvb ? subYpos * hFactor : subYpos global subSize = useBighalo ? subRatio \ : subRatio < 10 ? 8 \ : subRatio < 12 ? 10 \ : subRatio < 14 ? 12 \ : subRatio < 18 ? 14 \ : subRatio < 24 ? 18 : 24 global subWidth = useBighalo && !hd ? float(subSize) / 2.323 * wStretch : 0 subHaloSize = useBighalo ? floor(subSize / 7) : floor(subSize / 4.5) global subHaloSize = subHaloSize < 3 ? 3 : subHaloSize subFontName = subFont + (smallerSide < 224 ? "R" : "B") global subFontFile = "./fonts/" + subFontName + string(subSize) + ".bdf" subLength = int(last.FrameRate * subLengthMul) subFF2 = SubFF + subLength + 1 + subFF2delay subFF3 = SubFF2 + subLength + 1 + subFF2delay2 subFF4 = SubFF3 + subLength + 1 + subFF2delay3 global subColor = vb ? $009D9D9D : $00FFFFFF global subRadius = hd ? subHaloSize : 0 subFadeIn1 = subFF + fadeIn1 subFadeIn2 = subFF2 + fadeIn2 subFadeIn3 = subFF3 + fadeIn3 subFadeIn4 = subFF4 + fadeIn4 subFadeOut1 = subFF + subLength - fadeOut1 subFadeOut2 = subFF2 + subLength - fadeOut2 subFadeOut3 = subFF3 + subLength - fadeOut3 subFadeOut4 = subFF4 + subLength - fadeOut4 # Subtitles functions function subs(clip c, string text, float x, float y, int align, int first_frame, int last_frame, int fade, int fade2) { useBighalo \ ? vb \ ? 0 \ : ng_bighalo(c, text, x=x, y=y, align=align, first_frame=first_frame, \ last_frame=last_frame, size=subSize, font_width=subWidth, text_color=subColor, \ halo_color=$00000000, lsp=2, halo_radius=subRadius, fade=fade, fade2=fade2) \ : FreeSub2(c, text, x=int(x), y=int(y+subHaloSize), align=align, first_frame=first_frame, last_frame=last_frame, \ font=subFontFile, halo_width=subHaloSize, halo_height=subHaloSize, \ text_color=subColor, halo_color=$00000000, lsp=2, fade=fade, fade2=fade2) \ } subEntry == 2 ? subs(subString1 + "\n" + subString2, subXpos, subYpos, subAlign, subFF, subFF+subLength, subFadeIn1, subFadeOut1) : 0 subEntry == 2 ? subs(subString3 + "\n" + subString4, subXpos, subYpos, subAlign, subFF2, subFF2+subLength, subFadeIn2, subFadeOut2) : 0 subEntry == 3 || subEntry == 4 ? subs(subString1, subXpos, subYpos, subAlign, subFF, subFF+subLength, subFadeIn1, subFadeOut1) : 0 subEntry == 3 || subEntry == 4 ? subs(subString2, subXpos, subYpos, subAlign, subFF2, subFF2+subLength, subFadeIn2, subFadeOut2) : 0 subEntry == 3 ? subs(subString3 + "\n" + subString4, subXpos, subYpos, subAlign, subFF3, subFF3+subLength, subFadeIn3, subFadeOut3) : 0 subEntry == 4 ? subs(subString3, subXpos, subYpos, subAlign, subFF3, subFF3+subLength, subFadeIn3, subFadeOut3) : 0 subEntry == 4 ? subs(subString4, subXpos, subYpos, subAlign, subFF4, subFF4+subLength, subFadeIn4, subFadeOut4) : 0 # Virtual Boy hacks left = hdvb ? left \ .ng_bighalo(subString1, x=subXpos, y=subYpos, \ align=subAlign, first_frame=subFF, last_frame=subFF+subLength, \ size=subSize, text_color=subColor, halo_color=$00000000, lsp=2) \ .ng_bighalo(subString2, x=subXpos, y=subYpos, \ align=subAlign, first_frame=subFF2, last_frame=subFF2+subLength, \ size=subSize, text_color=subColor, halo_color=$00000000, lsp=2) \ .ng_bighalo(subString3 + "\n" + subString4, x=subXpos, y=subYpos, \ align=subAlign, first_frame=subFF3, last_frame=(subFF3+SubLength), \ size=subSize, text_color=subColor, halo_color=$00000000, lsp=2) : 0 right = hdvb ? right \ .ng_bighalo(subString1, x=subXpos, y=subYpos, \ align=subAlign, first_frame=subFF, last_frame=subFF+subLength, \ size=subSize, text_color=subColor, halo_color=$00000000, lsp=2) \ .ng_bighalo(subString2, x=subXpos, y=subYpos, \ align=subAlign, first_frame=subFF2, last_frame=subFF2+subLength, \ size=subSize, text_color=subColor, halo_color=$00000000, lsp=2) \ .ng_bighalo(subString3 + "\n" + subString4, x=subXpos, y=subYpos, \ align=subAlign, first_frame=subFF3, last_frame=subFF3+SubLength, \ size=subSize, text_color=subColor, halo_color=$00000000, lsp=2) : 0 hdvb ? yt3d(left, right).AudioDub(left) : 0 Trim(0, trimFrame) # Youtube can't hanble fps above 60 hd && last.FrameRate > 60 ? ChangeFPS(60) : 0 halfFPS ? SelectOdd : 0 # YV24 conversion doesn't reduce chroma, so "point" is fine ConvertToYV24(chromaresample="point", matrix=(hd \ ? "Rec709" \ : (pass == 0 \ ? "Rec601" \ : "PC.601"))) # pass == 1 ? assrender("subtitles.ass") : 0 # Remove duplicate frames for primary pass == 1 ? ExactDedup(firstpass=true, dupinfo="./temp/dup.txt",times="./temp/times.txt") : 0 pass == 2 ? ExactDedup(firstpass=false,dupinfo="./temp/dup.txt" ) : 0 # YV12 reduces chroma, so we use "lanczos" even for HD # http://tasvideos.org/forum/viewtopic.php?t=19426 i444 ? last : ConvertToYV12(chromaresample="lanczos", matrix=(hd \ ? "Rec709" \ : (pass == 0 \ ? "Rec601" \ : "PC.601"))) pass != 1 ? Prefetch(7) : last
# Multisegment AVI import function AppendSegment( \ clip sample, \ string base, \ int first_val, \ int last_val, \ string format, \ string resizer \){ filename = base + string(first_val, format) + ".avi" result = AviSource(filename).Eval(resizer + """Resize(sample.width, sample.height)""") return (first_val < last_val) \ ? result ++ sample.AppendSegment(base, first_val+1, last_val, format, resizer) \ : result } # Multisegment FFMPEG AVI import function FFAppendSegment( \ clip sample, \ string base, \ int first_val, \ int last_val, \ string format, \ string resizer, \ string csp, \ int fps \){ filename = base + string(first_val, format) + ".avi" result = Exist(filename) \ ? FFVideoSource(filename, colorspace=csp, fpsnum=fps, fpsden=1).Eval(resizer + """Resize(sample.width, sample.height)""") \ : BlankClip(length=0, width=sample.width, height=sample.height, fps=fps, pixel_type="RGB24").KillAudio() return Exist(filename) \ ? (first_val < last_val) \ ? result + sample.FFAppendSegment(base, first_val+1, last_val, format, resizer, csp, fps) \ : result \ : (first_val < last_val) \ ? sample.FFAppendSegment(base, first_val+1, last_val, format, resizer, csp, fps) \ : BlankClip(length=0, width=sample.width, height=sample.height, fps=fps, pixel_type="RGB24").KillAudio() } function Remove( \ clip c, \ int start, \ int end \){ c Trim(0, -start) + Trim(end, 0) } function Replace( \ clip dest, \ int start, \ int end, \ clip src \){ Assert(start >= 0, "Replace: parameter 'start' is negative") Assert( end >= 0, "Replace: parameter 'end' is negative") p1 = dest.Trim(0, -start) p2 = src.Trim(start, end) p3 = dest.Trim(end + 1, 0) p1 = (start == 0) ? dest.Trim(0, -1).DeleteFrame(0) : p1 p3 = ( end == 0) ? dest.Trim(0, -1).DeleteFrame(0) : p3 p1 + p2 + p3 return (dest.HasAudio) ? last.AudioDub(dest) : last } # HD encodes need big subtitle fonts, but AviSynth can't enlarge the halo. # Here's the custom subtitle function by nanogyth # It's slow, but we have subtitles for a limited time only function ng_bighalo( \ clip clp, \ string text, \ float "x", \ float "y", \ int "first_frame", \ int "last_frame", \ string "font", \ float "size", \ int "text_color", \ int "halo_color", \ int "align", \ int "spc", \ int "lsp", \ float "font_width", \ float "font_angle", \ int "halo_radius", \ string "mode", \ string "halo", \ string "shadow", \ int "fade", \ int "fade2" \){ #Version 16-17 2012/12/1 # - added circle_12 as default # - reworked math to avoid bitwise functions that are only # availible in experimental builds #Version 15 2012/12/1 # - drop shadow added # - halo_radius still works, but calculating the points of # a hollow circle for halo is much faster # - mode is depricated since memo-ing isn't as needed first_frame = default(first_frame, 0) last_frame = default( last_frame, first_frame + 299) font = default( font, "Arial") size = default( size, 112) x = default( x, -1) y = default( y, -1) text_color = default( text_color, $00DDDDDD) halo_color = default( halo_color, $80000000) align = default( align, 5) spc = default( spc, 0) lsp = default( lsp, 0) font_width = default( font_width, 0) font_angle = default( font_angle, 0) shadow = default( shadow, "") w = clp.width h = clp.height fade = default(fade, first_frame) fade2 = default(fade2, last_frame) ### ### ## # # # # # # # # # # # circle_12="0 0 "+\ "12 0 0 12 -12 0 0 -12 "+\ "1 12 2 12 3 11 4 11 5 11 6 10 7 10 8 9 "+\ "12 1 12 2 11 3 11 4 11 5 10 6 10 7 9 8 "+\ "-1 12 -2 12 -3 11 -4 11 -5 11 -6 10 -7 10 -8 9 "+\ "-12 1 -12 2 -11 3 -11 4 -11 5 -10 6 -10 7 -9 8 "+\ "-1 -12 -2 -12 -3 -11 -4 -11 -5 -11 -6 -10 -7 -10 -8 -9 "+\ "-12 -1 -12 -2 -11 -3 -11 -4 -11 -5 -10 -6 -10 -7 -9 -8 "+\ "1 -12 2 -12 3 -11 4 -11 5 -11 6 -10 7 -10 8 -9 "+\ "12 -1 12 -2 11 -3 11 -4 11 -5 10 -6 10 -7 9 -8 " halo = (defined(halo_radius) && halo_radius != 0) ? mt_circle(halo_radius) : circle_12 invis = BlankClip(1, w, h, pixel_type="YV12") tm = Subtitle(invis, text, x, y, 0, 0, font, size, $00FFFFFF,\ 0, align, spc, lsp, font_width, font_angle) text_mask = tm.mt_expand(mode="0 0 "+shadow, chroma="-128") halo_mask = text_mask.mt_expand(mode=halo, chroma="-128") h0 = halo_color%$01000000 h_color = (h0>=0) ? h0 : $01000000+h0 t0 = text_color%$01000000 t_color = (t0>=0) ? t0 : $01000000+t0 h_alpha = (halo_color>=0) ? 255-(halo_color/$01000000) : (-halo_color-1)/$01000000 t_alpha = (text_color>=0) ? 255-(text_color/$01000000) : (-text_color-1)/$01000000 lut_str = string(h_alpha)+ " x * 255 / " +string(t_alpha)+\ " " +string(h_alpha)+ " - y * 255 / +" alpha_mask = mt_lutxy(halo_mask, text_mask, lut_str) hc = BlankClip(1, w, h, color=h_color) tc = Subtitle(hc, text, x, y, 0, 0, font, size, t_color,\ 0, align, spc, lsp, font_width, font_angle) overlay = tc.Mask(alpha_mask.ConvertToRGB32()) (fade == first_frame && fade2 == last_frame )\ ? clp.ApplyRange(first_frame, last_frame, "Layer", overlay)\ : clp.Animate(first_frame-1, last_frame+1, "LayerFade", \ overlay, first_frame-1, first_frame, last_frame, fade, fade2,\ overlay, last_frame+1, first_frame, last_frame, fade, fade2) } function FreeSub2(clip c, string "text", int "x", int "y", int "align", int "first_frame", int "last_frame", \ string "font", int "halo_width", int "halo_height", \ int "text_color", int "halo_color", int "lsp", int "fade", int "fade2") { base = BlankClip(c, 1, pixel_type="RGB32", color=$888888).ResetMask() subs = base.FreeSub(text, x=x, y=y, align=align, font=font, \ halo_width=halo_width, halo_height=halo_height, text_color=text_color, halo_color=halo_color, lsp=lsp).ColorKeyMask($888888) (fade == first_frame && fade2 == last_frame )\ ? c.ApplyRange(first_frame, last_frame, "Layer", subs) \ : c.Animate(first_frame-1, last_frame+1, "LayerFade", \ subs, first_frame-1, first_frame, last_frame, fade, fade2, \ subs, last_frame+1, first_frame, last_frame, fade, fade2) } # Used with Animate, layers a clip and linearly fades from black. Specify 1 frame before desired start and 1 frame after # desired end for both animation length and the interpolated value to get a fade that starts at 0.0/1.0 and ends at 1.0/0.0. function LayerFade(clip c, clip overlayClip, float curFrame, int first_frame, int last_frame, int fadeEnd, int fadeBegin) { curFrame = Int(curFrame) y = curFrame <= fadeEnd \ ? Max(0, curFrame - first_frame) * (1.0 / (fadeEnd - first_frame)) \ : curFrame >= fadeBegin \ ? Max(0,last_frame - curFrame) * (1.0 / (last_frame - fadeBegin)) \ : 1.0 f = BlankClip(overlayClip) g = Overlay(overlayClip, f, opacity=1.0-y) return ((curFrame == first_frame-1) || (curFrame == Last_frame+1)) ? c : c.Layer(g) }
#################################### ### Nintendo DS Layout Automater ### #################################### # Based on layouts by Spikestuff # Adapted by Zinfidel ################# ### Importing ### ################# # In the importing script, the following variables must be defined before importing: # vid (clip) # The video dump. # resX (int) # Final output width. # resY (int) # Final output height. # vertGap (int) # Sets a gap between the screens in the Top and Bottom layout to simulate the actual screen separation, # and also adds borders to the top and bottom of other layouts to keep everything aligned. This value is # relative to the *native* size of the screens, and will be scaled to the final output resolution. Setting # this to 90 pixels gets the screens pretty close to lined up exactly. # bookGap (int) # Sets a gap between the screens in the Book Mode layout to simulate the actual screen separation. This does # not add any extra borders to other layouts. Can be combined with vertGap if the game uses both Book Mode and # Top and Bottom mode with a gap. Setting this to 90 pixels gets the screens pretty close to lined up exactly. # # The dimensions must define a resolution with an aspect ratio of 2:1. Some examples of output resolutions are: # - Native: 768x384 (256*3 x 192*2) # - 4K : 3840x1920 # Note that the final output vertical resolution will be increased by vertGap (scaled) if it is greater than 0. ############# ### Usage ### ############# # There are 7 shortcut functions defined to change the layout. They are: gt, gb, st, sb, ss, tb, and bm, which are # Gameplay (Top), Gameplay (Bottom), Single (Top), Single (Bottom), Side by Side, Top and Bottom, and Book Mode, # respectively. These functions automatically append to the video that they build, and each takes an integer as its # first argument: the frame number on which to change the layout. # # Two of the functions (tb and bm) also take an optional second argument that overrides the gap size. This value in # pixels is not scaled or relative to the native resolution, and is used raw. This is useful for eliminating the gap # (by setting it to 0) for scenes that need no gap. The output dimensions are fixed based on resX, resY, vertGap, and # bookGap - setting the gap override will adjust borders to make sure the layouts work together. # # These functions start with the full video being set to the last variable, and then the functions are chained to # create the video. For example: # # vid = AviSource("example.avi") # resX = 768 # resY = 384 # vertGap = 0 # bookGap = 90 # Import("dslayout.avsi") # last = vid # ss(0) # tb(1000) # gt(2000).gb(3000) # bm(4000, 0) # # This would create an output video that starts in Side by Side, changes to Top and Bottom at frame 1000, # changes to Gameplay (Top) on frame 2000, then changes to Gameplay (Bottom) on frame 3000. On frame 4000, # the layout is changed to Book Mode, but with the gap removed by setting the override to 0. It does not # matter if there is a line break or a dot between calls, they are functionally equivalent in AviSynth. ############# ### Setup ### ############# cr = vid.Height / 2 global top = vid.Crop(0, 0, -0, -cr) global bot = vid.Crop(0, cr, -0, -0) # Calculated Screen Sizes global screenWidth = resX / 3 global screenHeight = resY / 2 global bookWidth = (resY * 2) / 3 global bookHeight = resY # Calculated Gap Sizes global vGap = round((screenHeight * vertGap) / 192) global vertBorder = vGap / 2 global bGap = round((bookWidth * bookGap) / 192) global bookBorder = (resX - (bookWidth*2) - bGap) / 2 ############################# ### Pure Layout Functions ### ############################# function GameplayTop(clip t, clip b, int trimStart, int trimEnd) { t = t.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2) b = b.Trim(trimStart, trimEnd).PointResize(screenWidth, screenHeight).AddBorders(0, screenHeight, 0, 0) return StackHorizontal(t, b).AddBorders(0, vertBorder, 0, vertBorder) } function GameplayBottom(clip t, clip b, int trimStart, int trimEnd) { t = t.Trim(trimStart, trimEnd).PointResize(screenWidth, screenHeight).AddBorders(0, 0, 0, screenHeight) b = b.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2) return StackHorizontal(b, t).AddBorders(0, vertBorder, 0, vertBorder) } function SingleTop(clip t, clip b, int trimStart, int trimEnd) { ret = t.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).AddBorders(screenWidth/2, 0, screenWidth/2, 0) return ret.AddBorders(0, vertBorder, 0, vertBorder) } function SingleBottom(clip t, clip b, int trimStart, int trimEnd) { ret = b.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).AddBorders(screenWidth/2, 0, screenWidth/2, 0) return ret.AddBorders(0, vertBorder, 0, vertBorder) } function SideBySide(clip t, clip b, int trimStart, int trimEnd) { t = t.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).LanczosResize((screenWidth*3)/2, (screenHeight*3)/2) b = b.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).LanczosResize((screenWidth*3)/2, (screenHeight*3)/2) return StackHorizontal(t, b).AddBorders(0, screenHeight/4, 0, screenHeight/4).AddBorders(0, vertBorder, 0, vertBorder) } function TopAndBottom(clip t, clip b, int trimStart, int trimEnd, int "gap") { gap = defined(gap) ? gap : vGap t = t.Trim(trimStart, trimEnd).PointResize(screenWidth, screenHeight) b = b.Trim(trimStart, trimEnd).PointResize(screenWidth, screenHeight).AddBorders(0, gap, 0, 0) return StackVertical(t, b).AddBorders(screenWidth, (vGap-gap)/2, screenWidth, (vGap-gap)/2) } function BookMode(clip t, clip b, int trimStart, int trimEnd, int "gap") { gap = defined(gap) ? gap : bGap t = t.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).LanczosResize(bookHeight, bookWidth) b = b.Trim(trimStart, trimEnd).PointResize(screenWidth*2, screenHeight*2).LanczosResize(bookHeight, bookWidth).AddBorders(0, gap, 0 , 0) return StackVertical(t, b).TurnLeft().AddBorders(bookBorder+(bGap-gap)/2, vertBorder, bookBorder+(bGap-gap)/2, vertBorder) } ####################################### ### Auto-Appending Layout Shortcuts ### ####################################### function AutoAppend(clip prev, int startFrame, string func, int "gap") { ret = Eval(func + "(top, bot, startFrame, 0" + (defined(gap) ? ", "+string(gap) : "") + ")") return startFrame == 0 ? ret : prev.Trim(0, startFrame - 1) + ret } function gt(clip prev, int startFrame) { return AutoAppend(prev, startFrame, "GameplayTop") } function gb(clip prev, int startFrame) { return AutoAppend(prev, startFrame, "GameplayBottom") } function st(clip prev, int startFrame) { return AutoAppend(prev, startFrame, "SingleTop") } function sb(clip prev, int startFrame) { return AutoAppend(prev, startFrame, "SingleBottom") } function ss(clip prev, int startFrame) { return AutoAppend(prev, startFrame, "SideBySide") } function tb(clip prev, int startFrame, int "gap") { return AutoAppend(prev, startFrame, "TopAndBottom", gap) } function bm(clip prev, int startFrame, int "gap") { return AutoAppend(prev, startFrame, "BookMode", gap) }