A collection of spatial and temporal tiling and padding utilities for VapourSynth. The original idea was just a tiling function to make AI filters less VRAM-hungry and to provide additional options that built-in solutions might not. Over time, more related functions were added.
The functions often come in pairs, with one doing a thing and the other inversing it. For example:
import vs_tiletools
clip = vs_tiletools.tile(clip, width=256, height=256) # splits frames into 256x256 tiles
clip = core.someheavyfilter.AIUpscale(clip) # placeholder resource intensive filter
clip = vs_tiletools.untile(clip) # reassembles the tiles into full frames- Requirements
- Setup
- Usage Examples
- Spatial Functions
Tiling
⚬ Tile - Splits each frame into tiles of fixed dimensions
⚬ Untile - Auto reassembles tiles fromtile(), even if resized
Padding/Cropping
⚬ Pad - Pads a clip with various padding modes
⚬ Mod - Pads or crops a clip so width and height are multiples of the given modulus
⚬ Crop - Auto crops padded clip frompad()ormod(), even if resized
⚬ Croprandom - Crops to given dimensions, but randomly repositions the window each frame
Filling/Inpainting
⚬ Fill - Fills the borders of a clip with various filling modes
⚬ Autofill - Auto detects borders and fills them with various fill modes
⚬ Inpaint - Inpaints areas based on a mask with various inpainting modes - Temporal Functions
Duplicate Detection
⚬ Markdups - Marks identical frames as duplicates, which can later be skipped usingskipdups()
⚬ Skipdups - Skips processing of duplicate frames marked bymarkdups()
Overlapping
⚬ Insert Overlaps - Inserts temporal overlaps at fixed intervals
⚬ Trim Overlaps - Auto trims or crossfades overlaps added byinsert_overlaps()
Extending/Trimming
⚬ Extend - Extends a clip with various temporal padding modes
⚬ Trim - Auto trims extended clip fromextend()
Other
⚬ Crossfade - Crossfades between two clips - Mode Explanations
- fillborders (pad mode fixborders needs v3 or newer)
- cv_inpaint
- autocrop (optional, only for autofill)
- akarin (optional, only for markdups/skipdups)
- libvship (optional, only for markdups/skipdups, requires v4.0.0 or newer)
Put the vs_tiletools.py file into your vapoursynth scripts folder.
Or install via pip: pip install -U git+https://github.com/pifroggi/vs_tiletools.git
Examples of how the paired functions can be used together.
-
import vs_tiletools clip = vs_tiletools.tile(clip, width=256, height=256, overlap=16) # splits frames into 256x256 tiles with an overlap of 16 clip = core.trt.Model(clip, engine_path="2x_heavy_model.engine") # heavy AI upscale model clip = vs_tiletools.untile(clip, fade=True) # reassembles the tiles and uses the overlap to feather
-
import vs_tiletools clip = vs_tiletools.pad(clip, left=8, right=8, top=8, bottom=8) # pad 8 pixels on all sides clip = core.trt.Model(clip, engine_path="model.engine") # AI model with issues near borders clip = vs_tiletools.crop(clip) # automatically crop the padding
-
import vs_tiletools clip = vs_tiletools.mod(clip, modulus=16) # pad to make width and height divisible by 16 clip = core.trt.Model(clip, engine_path="2x_DAT_model.engine") # DAT and HAT based AI models have this constraint clip = vs_tiletools.crop(clip) # automatically crop the padding
-
import vs_tiletools clip = vs_tiletools.markdups(clip, thresh=0.3) # marks duplicate frames with a low threshhold clip = core.trt.Model(clip, engine_path="2x_heavy_model.engine") # heavy AI upscale model clip = vs_tiletools.skipdups(clip) # skips duplicates and replaces them with a previous frame
-
import vs_tiletools clip = vs_tiletools.insert_overlaps(clip, length=10, overlap=4) # creates a temporal overlap of 4 frames clip = vs_undistort.tensorrt(clip, temp_window=10) # filter has 10 input frames and 10 output frames clip = vs_tiletools.trim_overlaps(clip, fade=True) # uses the overlap to fade between chunks/windows
-
import vs_tiletools clip = vs_tiletools.extend(clip, start=10, end=10) # extend clip by 10 frames at the start and end clip = some.temporal_filter(clip) # temporal filters can have this issue clip = vs_tiletools.trim(clip) # automatically trims the added frames
-
Splits each frame into tiles of fixed dimensions to reduce resource requirements. Outputs a clip with all tiles in order. All filters applied to the tiled clip should be spatial only.
import vs_tiletools clip = vs_tiletools.tile(clip, width=256, height=256, overlap=16, padding="mirror")
clip
Clip to tile. Any format.width,height
Tile size of a single tile in pixel.overlap
Overlap from one tile to the next. When overlap is increased the tile size is not altered, so the amount of tiles per frame increases. Can be a single value or a pair for horizontal and vertical[16, 32].padding
How to handle tiles that are smaller than tile size. These can be padded with modesmirror,wrap,repeat,fillmargins,telea,ns,fsr,black, a custom color in 8-bit scale[128, 128, 128], or just discarded withdiscard. For a full explanation of each padding mode, click here.
-
Automatically reassembles a clip tiled with
tile(), even if tiles were since resized. Exampleimport vs_tiletools clip = vs_tiletools.untile(clip, fade=False) # automatic clip = vs_tiletools.untile(clip, fade=False, full_width=None, full_height=None, overlap=None) # manual
clip
Tiled clip. Any format.fade
If fade is True, the overlap will be used to feather/blend between the tiles to remove visible seams.
If fade is False, the overlap will be cropped.full_width,full_height,overlap(optional)
You can also enter untile parameters manually. Needed is the full assembled frame dimensions and the overlap between tiles. In manual mode you have to account for resized or discarded tiles yourself.
Tip: If tiles were discarded, the full_width/full_height are now smaller and a multiple of the original tile size.
Tip: If tiles were resized 2x, simply double all values.
-
Pads a clip with various padding modes.
import vs_tiletools clip = vs_tiletools.pad(clip, left=0, right=0, top=0, bottom=0, mode="mirror")
clip
Clip to be padded. Any format.left,right,top,bottom
Padding amount in pixel.mode
Padding mode can bemirror,wrap,repeat,fillmargins,telea,ns,fsr,black, or a custom color in 8-bit scale[128, 128, 128]. For a full explanation of each mode, click here.
-
Pads or crops a clip so width and height are multiples of the given modulus.
import vs_tiletools clip = vs_tiletools.mod(clip, modulus=64, mode="mirror")
clip
Source clip. Any format.modulus
Dimensions will be a multiple of this value. Can be a single value, or a pair for width and height[64, 32].mode
Mode to reach the next upper multiple via padding can bemirror,wrap,repeat,fillmargins,telea,ns,fsr,black, a custom color in 8-bit scale[128, 128, 128], ordiscardto crop to the next lower multiple. For a full explanation of each padding mode, click here.
-
Automatically crops padding added by
pad()ormod(), even if the clip was since resized. Example1 Example2import vs_tiletools clip = vs_tiletools.crop(clip) # automatic clip = vs_tiletools.crop(clip, left=0, right=0, top=0, bottom=0) # manual
clip
Padded clip. Any format.left,right,top,bottom(optional)
Optionally you can also enter crop values manually.
-
Crops to the given dimensions, but randomly repositions the crop window each frame.
import vs_tiletools clip = vs_tiletools.croprandom(clip, width=256, height=256, seed=0)
clip
Clip to be cropped. Any format.width,height
Cropped window dimensions in pixels.seed
Seed used for deterministic crop randomization.
-
Fills the borders of a clip with various filling modes. Basically padding, but inwards.
import vs_tiletools clip = vs_tiletools.fill(clip, left=0, right=0, top=0, bottom=0, mode="mirror")
clip
Clip to be filled. Any format.left,right,top,bottom
Fill amount in pixel.mode
Filling mode can bemirror,wrap,repeat,fillmargins,telea,ns,fsr,black, or a custom color in 8-bit scale[128, 128, 128]. For a full explanation of each mode, click here.
-
Detects uniform colored borders (like letterboxes/pillarboxes) and fills them with various filling modes.
import vs_tiletools clip = vs_tiletools.autofill(clip, left=0, right=0, top=0, bottom=0, offset=0, color=[16,128,128], tol=16, fill="mirror")
clip
Source clip. Only YUV formats are supported.left,right,top,bottom
Maximum border fill amount in pixels.offset
Offsets the detected fill area by an extra amount in pixels. Useful if the borders are slightly blurry.
Does not offset sides that have detected 0 pixels.color
Source clip border color in 8-bit scale[16, 128, 128].tol
Tolerance to account for fluctuations in border color. Can be a single value or a list[16, 16, 16].fill
Filling mode can bemirror,repeat,fillmargins,telea,ns,fsr,black, or a custom color in 8-bit scale[128, 128, 128]. For a full explanation of each mode, click here.
-
Inpaints areas in a clip based on a mask with various inpainting modes.
import vs_tiletools clip = vs_tiletools.inpaint(clip, mask, mode="telea")
clip
Clip to be inpainted. Any format.mask
Black and white mask clip where white means inpainting. Can be a single frame long, or longer and different each frame. If too short, the last frame will be looped. Can be any format and doesn't have to match the base clip.mode
Inpainting mode can betelea,ns,fsrorshiftmap. For a full explanation of each mode, click here.
-
Marks up to 5 consecutive frames as duplicates if they are near identical, which can later be skipped using
skipdups(). Exampleimport vs_tiletools clip = vs_tiletools.markdups(clip, thresh=0.3)
clip
Clip were duplicates should be marked. Any format.thresh
Similarity threshold. If the difference between two consecutive frames is lower than this value, the frame is marked as a duplicate. If the value is 0, only 100% identical frames will be marked as duplicate. Keep it a little above 0 due to noise and compression. The default worked nicely for me on anime.
-
Skips processing of up to 5 consecutive duplicate frames marked by
markdups(). That means the marked frames will copy one of the previous 5 frames instead of submitting the current frame for processing. This speeds up heavy filters sandwiched inbetweenmarkdups()andskipdups(). ExampleKeep in mind that if you use a heavy spatial filter, followed by a temporal filter, both inside of the sandwich, the speedup will be negated, because the temporal filter will request the marked frames anyway. For this reason, it is recommended to use temporal filters outside the sandwich.
import vs_tiletools clip = vs_tiletools.skipdups(clip, debug=False) # automatic clip = vs_tiletools.skipdups(clip, prop_src=None, debug=False) # manual
clip
Clip with marked duplicates. Any format.prop_src(optional)
Frame properties source clip. This should be detected automatically. But if the frame props of the first clip got lost, you can set it here manually. It should be the clip directly returned bymarkdups().debug
Overlays the frame number of the selected frame and the difference value to the previous frame onto the output. This is useful to finetune the sensitivity threshold inmarkdups().
-
Inserts temporal overlaps at fixed intervals into the clip. That means a chunk with
length=20andoverlap=5will produce a clip with this frame pattern:0–19,15–34,30–49, and so on. In combination with thetrim_overlapsfunction, the overlap can then be used to crossfade between chunks/windows and eliminate sudden jumps/hitches that can occur on chunk/window based functions like vs_undistort. Exampleimport vs_tiletools clip = vs_tiletools.insert_overlaps(clip, length=20, overlap=5, padding="mirror")
clip
Clip that should get overlaps inserted. Any format.length
Chunk/temporal window length.overlap
Overlap from one window to the next. When overlap is increased, the temporal window length is not altered, so the total amount of windows per clip increases.padding
How to handle the last window of the clip if it is smaller than length. It can be padded with modesmirror,loop,repeat,black, a custom color in 8-bit scale[128, 128, 128], discarded withdiscard, or left as is withNone. For a full explanation of each padding mode, click here.
-
Automatically removes the overlaps inserted by
insert_overlaps()and optionally uses them to crossfade between chunks/windows. Exampleimport vs_tiletools clip = vs_tiletools.trim_overlaps(clip, fade=False) # automatic clip = vs_tiletools.trim_overlaps(clip, fade=False, full_length=None, window_length=None, overlap=None) # manual
clip
Clip with inserted overlaps. Any format.fade
If fade is True, the overlap will be used to crossfade between the chunks/windows.
If fade is False, the overlap will be trimmed.full_length,window_length,overlap(optional)
You can also enter trim_overlaps parameters manually. Needed is the full clip length, window length and the overlap between windows. In manual mode you have to account for a discarded window yourself.
Tip: If the last chunk/window was discarded, the full_length is now smaller and a multiple of window_length.
Tip: If the clip was interpolated to 2x after inserting overlaps, simply double all values.
-
Extends (temporally pads) a clip using various padding modes.
import vs_tiletools clip = vs_tiletools.extend(clip, start=0, end=0, length=None, mode="mirror")
clip
Clip to extend. Any format.start,end
Number of frames to add at the start and/or end. Mutually exclusive withlength.length
Extends clip to exactly this many frames. Mutually exclusive withstart/end.mode
Padding mode can bemirror,loop,repeat,black, or a custom color in 8-bit scale[128, 128, 128]. For a full explanation of each mode, click here.
-
Automatically trims temporal padding added by
extend(). Exampleimport vs_tiletools clip = vs_tiletools.trim(clip) # automatic clip = vs_tiletools.trim(clip, start=0, end=0, length=None) # manual
clip
Temporally padded clip. Any format.start,end(optional)
Optional manual number of frames to remove from start and/or end. End is mutually exclusive withlength.length(optional)
Optional manual trim to exactly this many frames, starting from start. Mutually exclusive withend.
-
Crossfades between two clips.
import vs_tiletools clip = vs_tiletools.crossfade(clipa, clipb, length=10)
clipa,clipb
Input clips to crossfade. Any format, as long as they match.length
Length of the crossfade. For examplelength=10will fade the last 10 frames of clipa into the first 10 frames of clipb.
Full explanations for all padding/filling/inpainting modes.
-
Spatial
mirrorReflects the image into the padded/filled region.wrapWraps the image around to create a periodic tiling.repeatRepeats the outermost pixel row/column.fillmarginsSimilar to repeat, but the top and bottom pad/fill gets more blurry the further away it is.fixbordersA direction aware fillmargins that also works on all four sides, not just top and bottom.teleaGets more blurry the further away it is.nsNavier-Stokes algorithm. Similar to telea, but less blurry.fsrFrequency Selective Reconstruction algorithm. Better at keeping patterns/textures, but is slow.shiftmapShifts part of the existing image to fill the holes. Only for inpainting.blackSolid black.[128, 128, 128]Solid custom color. 8-bit values per plane in the clip’s color family.
-
Temporal
mirrorReverses the clip at the start/end.loopLoops the clip to start over.repeatRepeats the first/last frame.blackAppends solid black frames.[128, 128, 128]Appends frames in a solid custom color. 8-bit values per plane in the clip’s color family.
Note
The padded/filled/inpainted regions may be generated at a lower bit depth due to plugin limitations (16-bit for fillborders, 8-bit for cv_inpaint), then upsampled and merged onto the original high depth frames. This should usually not be an issue.
Modes fillmargins and fixborders, which are partially broken on some formats when using the fillborders plugin directly, are also fixed here.