View Full Version : Pretty fast DVD remastering feamework code
geometer
1st August 2026, 11:27
Currently popular are two approaches:
1. AI - quite slow, and may look a bit inauthentic or filtered. changes are hard to control
2. QTGMC and similar - CPU-heavy, many many very general parameters, tends to "equalize" just anything, may look not very crispy.
After looking into this, I sought for something very different.
I would like to contribute a code framework that is entirely based on real issues,
heuristically explored artifacts and their properties,
and it uses a bit of signal processing math to exactly target the typical flaws and artifacts of classic DVDs from the hey-days.
The challenge is to understand the detail issues, and set the parameters correctly.
But we are dealing directly with sharpness issues, color correction,
and a very detailed antiringing feature that makes strong sharpening possible in the first place,
Don't mind the code, just the results. There are remarks and optional lines to adjust the whole process.
The functions are very standard and fast.
Optionally nnedi3 is used for interlaced program, you may try to speed that up with NVIDIA versions like NNEDI3CL.
All execution 64bit and multithreaded.
Next posting will be the main module, others follow in further postings below.
# It starts with declaring the input file name, which is the index d2v file.
# The corresponding .ISO dvd file should have the same name.
# All such files belong in the same work directory of the project.
# Depending on project requirements also an index file with the same name
# but for the LWLibavVideoSource plugin may be created (on the fly, takes a minute) in the work directory.
# For simplicity and optional adjustment, copy all avs library and function files here also.
# Note that this processing chain starts from plain DVD format, does its math at 12bit planar, and ends up with 960x640.
# All components run at 64bit.
#
# We use Avidemux 8.1 and avsproxy to encode the result, the PY settings file is here in the directory.
# >> Adjust video duration, speed (fps), and output geometry (16:9 or 4:3 for NTSC, not tested with PAL).
#
# Any x264 encoder may be used, but the settings are crucial for fine detail and flow of moves,
# you may want to start from the provided setting.
# For using avsproxy,
# save a bat file under the name avsproxy-run64.bat with the content (adjust directory names)
# "C:\Program Files\Avidemux 2.7 VC++ 64bits\avsproxy64.exe" %1
# pause
# You can reuse it for all projects, just do a drag and drop with the main avs file to this bat file.
# I will later post a similar main file for interlaced DVDs.
# Avsproxy 8.1 64bit is recommended for several reasons, but I could find the avsproxy tool only with the 2.7 version.
# So you may download also 2.7.
# TLDR -- edit main avs file, drag and drop it on avsproxy64, open the frame server in Avidemux, open settings file,
# adjust video length, start the encoder (=save).
The example is a maximum-case, you can tone down the sharpening with the asharp() settings and with less aggressive kernels in the main convolution.
This compresses to 1.5G for70 minutes.
https://i.ibb.co/hJBChccx/Clipboard02.png (https://ibb.co/Rk37ZNNG)
https://i.ibb.co/mVQrYYWt/Clipboard03.png (https://ibb.co/jP79xxXG)
Here is my gear for this project:
[OS/Hardware info]
Operating system: Windows 10 (x64) (Build 19045)
CPU: Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz / Coffee Lake (Core i7)
MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, FMA3, AVX, AVX2
6 physical cores / 12 logical cores
[Avisynth info]
VersionString: AviSynth+ 3.7.5 (r4289, 3.7, x86_64)
VersionNumber: 3.75
File / Product version: 3.7.5.0 / 3.7.5.0
Interface Version: 5
Multi-threading support: Yes
Avisynth.dll location: C:\Windows\SYSTEM32\avisynth.dll
Avisynth.dll time stamp: 2025-04-20, 21:08:56 (UTC)
PluginDir2_5 (HKLM, x64): D:\Programs\AVISynthPlus\plugins64
PluginDir+ (HKLM, x64): D:\Programs\AVISynthPlus\plugins64+
[CPP 2.5 Plugins (64 Bit)]
D:\Programs\AVISynthPlus\plugins64+\DGDecode.dll [1.5.8.0] ****
[CPP 2.6 Plugins (64 Bit)]
D:\Programs\AVISynthPlus\plugins64+\AddGrainC.dll [1.8.4.0] ****
D:\Programs\AVISynthPlus\plugins64+\ASharp.dll [1.0.0.0] ****
D:\Programs\AVISynthPlus\plugins64+\ConvertStacked.dll [2025-04-20]
D:\Programs\AVISynthPlus\plugins64+\DGDecode.dll [2.0.0.9] **** one of these DGDecode should work as 64bit
D:\Programs\AVISynthPlus\plugins64+\DGDecode_.dll [3.0.0.1]
D:\Programs\AVISynthPlus\plugins64+\DGDecodeNV.dll [257.0.0.0]
D:\Programs\AVISynthPlus\plugins64+\DGDecodeNV_AVX2.dll [257.0.0.0]
D:\Programs\AVISynthPlus\plugins64+\DirectShowSource.dll [2025-04-20]
D:\Programs\AVISynthPlus\plugins64+\ffms2.dll [2024-05-28]
D:\Programs\AVISynthPlus\plugins64+\FluxSmooth.dll [1.4.0.0]
D:\Programs\AVISynthPlus\plugins64+\ImageSeq.dll [2025-04-20]
D:\Programs\AVISynthPlus\plugins64+\LSMASHSource.dll [1282.0.0.0] ****
D:\Programs\AVISynthPlus\plugins64+\masktools2.dll [2.2.30.0]
D:\Programs\AVISynthPlus\plugins64+\nnedi3.dll [0.9.4.68] ****
D:\Programs\AVISynthPlus\plugins64+\plugins_JPSDR.dll [4.1.0.0]
D:\Programs\AVISynthPlus\plugins64+\Shibatch.dll [2025-04-20]
D:\Programs\AVISynthPlus\plugins64+\TimeStretch.dll [2025-04-20]
D:\Programs\AVISynthPlus\plugins64+\VDubFilter.dll [2025-04-20]
D:\Programs\AVISynthPlus\plugins64+\vsTTempSmooth.dll [1.3.0.0] **
D:\Programs\AVISynthPlus\plugins64+\yadifmod2.dll [0.2.8.0] ****
D:\Programs\AVISynthPlus\plugins64\AddGrainC.dll [1.8.4.0]
D:\Programs\AVISynthPlus\plugins64\ASharp.dll [1.0.0.0]
D:\Programs\AVISynthPlus\plugins64\DGDecode.dll [3.0.0.1]
D:\Programs\AVISynthPlus\plugins64\FluxSmooth.dll [1.4.0.0]
D:\Programs\AVISynthPlus\plugins64\masktools2.dll [2.2.30.0]
D:\Programs\AVISynthPlus\plugins64\vsTTempSmooth.dll [1.4.0.0]
D:\Programs\AVISynthPlus\plugins64\yadifmod2.dll [0.2.8.0]
[Uncategorized DLLs (64 Bit)]
D:\Programs\AVISynthPlus\plugins64+\libomp.dll [5.0.2014.926]
D:\Programs\AVISynthPlus\plugins64\libomp.dll [5.0.2014.926]
[Uncategorized files]
D:\Programs\AVISynthPlus\plugins64+\LSMASHSource_indexing.exe [1282.0.0.0]
DGIndex.exe [1.5.8]
geometer
1st August 2026, 11:32
ProjectMain.avs :
cISO = "MyCurrentDVD_project"
# This is the name of the d2v file without extension.
SetFilterMTMode("DEFAULT_MT_MODE", 2)
SetFilterMTMode("MPEG2Source", MT_MULTI_INSTANCE)
SetFilterMTMode("LWLibavVideoSource", MT_MULTI_INSTANCE)
SetFilterMTMode("nn edi3", MT_MULTI_INSTANCE) # or nnedi3cl when you add it
#-- default format : YUV444 ------------------------ perform special Expr filters
import("convtools.avs")
#-- default format : YUV444 ------------------------ perform special Expr filters
import("antiring2_hans.avs")
#-------------------------------------------
#-- read input file --
MPEG2Source (cISO+".d2v", cpu=0,moderate_h=0,moderate_v=0,info=2)
# if DGDecode fails to decode the main video, activating the following lines may help ===!TUNING!===
#last = AssumeTFF(last)
#last = SelectOdd(last)
#=============
# if you need pictures from the DVD but DGDecode fails to read them, open a duplicate stream like here: ===!TUNING!===
vpro = MPEG2Source (cISO+".d2v", cpu=0,moderate_h=0,moderate_v=0,info=2) # when you have used SelectOdd in above tweak
#vpro = LWLibavVideoSource(cISO+".ISO", cache=true, seek_mode=1) # when you can read the main video but not the pics
#vpro = Crop(vpro, 2,0,-2,-0) # vpro and vRaw stream handles both need the same cropping and AddMirrorBorder values!
vpro = AddMirrorBorders(vpro,4)
#Crop(2,0,-2,-0) # adjust for left and right black bars ===!TUNING!===
last = AddMirrorBorders(last,4)
vRaw = last
/*
#--------------- pre-blending , only for interlaced videos -------------------
SeparateFields
C62 = "0 -0 0 0 0 0 0 0 0 0 0 0 112 -5 7 0 0 27 0 -0 0 0 -7 0 0"
C62a4 ="0 -0 0 0 0 0 0 0 0 0 0 0 112 0 -1 0 0 23 0 -0 0 0 -5 0 0"
C62a4 ="0 -0 0 0 0 0 0 0 0 0 0 0 112 -5 27 0 0 23 0 -0 0 0 -5 0 0"
C62a7 ="0 -0 0 0 0 0 0 -0 0 0 0 0 112 -15 23 0 0 27 0 -0 0 0 -7 0 0"
C62a6 ="0 -0 0 0 0 0 0 -0 0 0 0 0 112 -17 17 0 0 23 0 -0 0 0 -3 0 0"
#C62a5 ="0 -0 0 0 0 0 0 10 0 0 0 0 112 -13 3 0 0 23 0 -0 0 0 -3 0 0"
C62a5 ="0 -0 -11 0 0 0 0 9 0 0 0 0 112 -13 21 0 0 23 0 -0 0 0 -5 0 0"
last = Conv5x5(last, C62, "luma", "out=in")
Weave
#---------------------------------------
*/
#-- Deinterlace Yadif -- delete this, when source is not actually interlaced i.e. without a deinterlacer shows combing
#Load_Stdcall_plugin("F:\programs\AviSynth+\plugins\yadif.dll")
#Load_Stdcall_plugin("E:\D-BAK\Programs\AVISynthPlus\plugins64+\yadif.dll")
Load_Stdcall_plugin("D:\Programs\AVISynthPlus\plugins64\yadifmod2.dll")
#Yadif(mode=1,order=1)
#vYadif = Yadifmod2(last, mode=1,order=1)
#-- Deinterlace nnedi template --
# NNEDI3CL(clip input, int "field", bool "dh", bool "dw", int[] "planes",
# int "nsize", int "nns", int "qual", int "etype", int "pscrn",
# int "device", bool "list_device", bool "info", bool "st", bool "luma")
#vMain = nnedi3cl(vMain, field=3,nns=3,qual=2,nsize=3,pscrn=2,etype=1,device=1,st=false)
global rff=30000./1001. # factor *2 for 60fps
AssumeFPS(30000,1001)
vRaw = AssumeFPS(vRaw,30000,1001)
#vpro = AssumeFPS(vpro,30000,1001) # add, if vpro stream is used
# ----- here we cut out the pics that we want to insert in the result ===!TUNING!===
# see the cut() function at the end of the script, if a pic starts at 0:00.000
# we can turn a snapshot of the video into a pic too, like we might do with moving menus.
pics = cut(vpro, 0,00.066, 0,00.099).Trim(0,-1) # + cut(vpro, 101,01.626, 101,01.659) #.Yadifmod2(mode=0,order=1).Trim(0,-1)
# --- ! cutting syntax is minutes, seconds.milliseconds
# example lines of junk code for different combinations of pics and menu streams
#pics1 = cut(vpro,0,24.790, 0,24.823).Yadifmod2(mode=0,order=1).Trim(0,-1) # HDR
#pics2 = cut(vpro,0,00.533, 0,00.600).Trim(0,-1)
#pics = Trim(pics, 0,-2)
#pics = pics1 + pics
#pics1 = Yadifmod2(pics1, mode=1,order=1)
#pics1 = Trim(pics1,0,-1)
#vIntro=cut(vpro,0,00.033, 0,07.674) #+ cut(last,0,05.705, 1,25.282)
# find out start and end of the main video. ===!TUNING!===
vMain = cut(last, 0,00.133, 72,09.051)
#global rff=60000./1001. # factor *2 for 60fps
#pics = Trim(vRaw, 0, -3)
#pics = Trim(pics,0,-11)
#vintro = cut(last,79,49.709, 80,02.172)
#vmain = cut(last,0,40.124, 79,27.000)
#vMain = cut(last, 1,07.832, 79,40.000)
tsl=int(2.0*rff/2.)+1 # duration of one pic
n=0
# ===!TUNING!===
# if you have 4 pics then put the comment ending symbol to the right of the line that addresses "4"
/*
pics = Loop(pics,tsl,n+30,n+30)
pics = Loop(pics,tsl,n+29,n+29)
pics = Loop(pics,tsl,n+28,n+28)
pics = Loop(pics,tsl,n+27,n+27)
pics = Loop(pics,tsl,n+26,n+26)
pics = Loop(pics,tsl,n+25,n+25)
pics = Loop(pics,tsl,n+24,n+24)
pics = Loop(pics,tsl,n+23,n+23)
pics = Loop(pics,tsl,n+22,n+22)
pics = Loop(pics,tsl,n+21,n+21)
pics = Loop(pics,tsl,n+20,n+20)
pics = Loop(pics,tsl,n+19,n+19)
pics = Loop(pics,tsl,n+18,n+18)
pics = Loop(pics,tsl,n+17,n+17)
pics = Loop(pics,tsl,n+16,n+16)
pics = Loop(pics,tsl,n+15,n+15)
pics = Loop(pics,tsl,n+14,n+14)
pics = Loop(pics,tsl,n+13,n+13)
pics = Loop(pics,tsl,n+12,n+12)
pics = Loop(pics,tsl,n+11,n+11)
pics = Loop(pics,tsl,n+10,n+10)
pics = Loop(pics,tsl,n+9,n+9)
pics = Loop(pics,tsl,n+8,n+8)
pics = Loop(pics,tsl,n+7,n+7)
pics = Loop(pics,tsl,n+6,n+6)
pics = Loop(pics,tsl,n+5,n+5)
pics = Loop(pics,tsl,n+4,n+4)
pics = Loop(pics,tsl,n+3,n+3)
pics = Loop(pics,tsl,n+2,n+2)
pics = Loop(pics,tsl,n+1,n+1) */
pics = Loop(pics,tsl,n+0,n+0)
# this version is progressive video, no nnedi3
#global rff=60000./1001. # factor *2 for 60fps
#vMain = nnedi3(vMain, field=3,nns=3,qual=2,nsize=3,threads=0,pscrn=4,etype=1) # nsize = 3 (weak flt) oder 2 (src blur)
#AssumeFPS(60000,1001)
#vIntro = Yadifmod2(vIntro, mode=1,order=1).AssumeFPS(60000,1001)
#pics = AssumeFPS(pics,60000,1001)
#vIntro = CShft(vIntro, 0.05, -0.75)
#pics = vIntro + pics
last = vMain
ConvertBits(12)
ConvertToPlanarRGB(matrix="Rec709",interlaced=false)
#------------------------------------------- end cutting -------------------------------
#### ----------------------------- library of main sharpening kernels -------------------------------------
A000 = "0 0 100 0 0 0 0 0 0 0 0 0 50 0 0 0 0 0 0 0 0 0 0 0 0" # CL LC
C000 = "0 0 0 0 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" #dummy for asymmetric (to keep the shifting)
C001 = "0 3 -3 9 100 0 0 0 0 17 0 0 0 0 -7 0 0 0 0 5 0 0 0 0 0" #dummy for asymmetric (to keep the shifting)
C002 = "7 -9 7 17 100 0 0 0 0 55 0 0 0 0 25 0 0 0 0 -3 0 0 0 0 3" #dummy for asymmetric (to keep the shifting)
C40k7 ="4 -7 17 -27 137 0 0 2 -4 -31 0 0 -5 5 23 0 0 0 -1 -11 0 0 0 0 3" #C4.0k7 ß
C50g5t4="7 -9 29 -11 121 0 0 -4 2 -35 0 1 -3 9 11 0 0 -0 -1 -3 0 0 0 0 7"
C50g5t4="7 -9 31 -17 121 0 0 -4 2 -31 0 1 -3 5 7 0 0 -0 -1 -9 0 0 0 0 7"
C50g5t4="7 -9 29 -19 97 0 0 -4 2 -29 0 1 -3 5 7 0 0 -0 -1 -9 0 0 0 0 7"
#C50g5t4="5 -14 31 -11 121 0 0 -4 2 -35 0 1 -3 9 23 0 0 -0 -1 -7 0 0 0 0 7"
#C50g5t4="5 -14 31 -11 121 0 0 -4 2 -31 0 1 -3 9 23 0 0 -0 -1 -11 0 0 0 0 7"
C50g5t5="7 -7 37 -29 121 0 0 -4 2 -37 0 1 -3 9 13 0 0 -0 -1 -8 0 0 0 0 7"
C50g5t5="7 -7 37 -31 121 0 0 -4 2 -37 0 1 -3 7 13 0 0 -0 -1 -8 0 0 0 0 7"
C50g5t5="7 -9 37 -33 121 0 0 -4 2 -37 0 1 -3 7 13 0 0 -0 -1 -8 0 0 0 0 7"
C50g5t6="5 -11 31 -21 137 0 0 -4 2 -51 0 1 -3 9 9 0 0 -0 -1 -4 0 0 0 0 7"
C50g5t6="6 -15 29 -13 97 0 0 -4 2 -25 0 1 -3 5 17 0 0 -0 -1 -13 0 0 0 0 6"
C50g5t7="6 -11 33 -31 121 0 0 -4 2 -37 0 1 -3 7 13 0 0 -0 -1 -8 0 0 0 0 7"
C50g5t8="6 -17 29 -31 121 0 0 -4 2 -29 0 1 -3 5 7 0 0 -0 -1 -11 0 0 0 0 6"
C50g5t8="6 -17 29 -31 121 0 0 -4 2 -26 0 1 -3 5 27 0 0 -0 -1 -25 0 0 0 0 7"
C50g5t8="11 -15 37 -29 97 0 0 -4 2 -29 0 1 -3 5 13 0 0 -0 -1 -7 0 0 0 0 5"
#C50g5t8=" 7 -21 41 -39 97 0 0 -4 2 -37 0 1 -3 5 25 0 0 -0 -1 -13 0 0 0 0 5"
C50g5t8=" 9 -21 35 -31 117 0 0 -4 2 -31 0 1 -3 5 29 0 0 -0 -1 -15 0 0 0 0 6"
C50g5t8=" 9 -21 35 -31 117 0 0 -4 2 -5 0 1 -3 5 9 0 0 -0 -1 -7 0 0 0 0 3"
#C50g5t8=" 4 -17 29 -21 113 0 0 -4 2 -31 0 1 -3 5 23 0 0 -0 -1 -15 0 0 0 0 5"
#C50g5t9=" 6 -19 31 -29 101 0 0 -4 2 -29 0 1 -3 5 29 0 0 -0 -1 -25 0 0 0 0 7"
C50g5t9=" 7 -15 29 -31 113 0 0 -4 2 -21 0 1 -3 5 15 0 0 -0 -1 -9 0 0 0 0 4"
#C50g5t9=" 9 -21 31 -27 121 0 0 -4 2 -27 0 1 -3 5 27 0 0 -0 -1 -21 0 0 0 0 7"
C50g5u ="5 -11 19 -25 121 0 0 -4 2 -37 0 1 -3 7 11 0 0 -0 -1 -8 0 0 0 0 7" #
C50g5u1="3 -7 17 -17 121 0 0 -4 2 -37 0 1 -3 7 11 0 0 -0 -1 -8 0 0 0 0 7"
C50g5u2="5 -9 17 -17 121 0 0 -4 2 -37 0 1 -3 7 11 0 0 -0 -1 -8 0 0 0 0 7"
C50g5u3="5 -9 17 -17 121 0 0 -4 2 -22 0 1 -3 7 29 0 0 -0 -1 -13 0 0 0 0 7"
C50g5u4="5 -11 19 -27 121 0 0 -4 2 -41 0 1 -3 7 9 0 0 -0 -1 -7 0 0 0 0 5"
C50g5u4="7 -11 19 -27 121 0 0 -4 2 -37 0 1 -3 7 9 0 0 -0 -1 -9 0 0 0 0 5"
C50g5u4="7 -13 15 -22 101 0 0 -4 2 -32 0 1 -3 5 13 0 0 -0 -1 -13 0 0 0 0 5"
C50g5u4="5 -11 19 -28 97 0 0 -4 2 -40 0 1 -3 7 7 0 0 -0 -1 -7 0 0 0 0 6"
#C50g5u4="5 -11 19 -27 127 0 0 -4 2 -33 0 1 -3 5 5 0 0 -0 -1 -9 0 0 0 0 6"
C50g5u5="5 -11 19 -25 121 0 0 -4 2 -27 0 1 -3 7 3 0 0 -0 -1 -7 0 0 0 0 5"
C50g5u5="6 -13 21 -25 121 0 0 -4 2 -25 0 1 -3 3 2 0 0 -0 -1 -9 0 0 0 0 4"
C50g5u5="6 -11 21 -25 131 0 0 -4 2 -21 0 1 -3 3 2 0 0 -0 -1 -9 0 0 0 0 4"
C50g5u5="7 -15 17 -21 121 0 0 -4 2 -7 0 1 -3 3 17 0 0 -0 -1 -17 0 0 0 0 5"
C50g5u5="7 -15 19 -21 137 0 0 -4 2 -39 0 1 -3 7 7 0 0 -0 -1 -7 0 0 0 0 5"
#C50g5u5="4 -15 17 -23 137 0 0 -4 2 -41 0 1 -3 7 7 0 0 -0 -1 -9 0 0 0 0 7"
#C50g5u5="7 -15 25 -21 107 0 0 -4 2 -49 0 1 -3 7 23 0 0 -0 -1 -13 0 0 0 0 7"
#C50g5u5="5 -15 19 -21 137 0 0 -4 2 -43 0 1 -3 5 5 0 0 -0 -1 -9 0 0 0 0 5"
#C50g5u5="4 -15 17 -21 137 0 0 -4 2 -20 0 1 -3 7 17 0 0 -0 -1 -4 0 0 0 0 6"
#C50g5u5="5 -19 27 -21 137 0 0 -4 2 -17 0 1 -3 7 21 0 0 -0 -1 -7 0 0 0 0 6"
#C50g5u5="7 -11 19 -21 137 0 0 -4 2 -13 0 1 -3 3 7 0 0 -0 -1 -9 0 0 0 0 3"
#C50g5u5="7 -9 19 -25 121 0 0 -4 2 -29 0 1 -3 7 3 0 0 -0 -1 -3 0 0 0 0 5"
C50g5u6="5 -13 21 -25 121 0 0 -4 2 -31 0 1 -3 7 5 0 0 -0 -1 -3 0 0 0 0 5"
C50g5u7="4 -11 19 -23 121 0 0 -4 2 -31 0 1 -3 7 5 0 0 -0 -1 -3 0 0 0 0 5"
C50g5m ="3 -9 19 -7 121 0 0 2 -5 -11 0 0 -4 4 15 0 0 0 -0 -5 0 0 0 0 3"
C50g5m ="3 -11 19 -7 121 0 0 2 -5 -14 0 0 -4 4 15 0 0 0 -0 -5 0 0 0 0 3"
C50g5r6 ="3 -13 31 -11 137 0 0 2 -5 -39 0 0 -4 4 31 0 0 -0 -1 -17 0 0 0 0 7"
# use t8 and similar when the original has already some sharpening artifacts like halo.
# use u4 and similar then the video is very blurred.
last = Conv5x5(last, C50g5t8, "all", "out=in").ConvertToYUV444(matrix="PC.709", interlaced=false,chromaresample="lanczos4")
pics = Conv5x5(pics, C000, "all", "out=in").ConvertToYUV444(matrix="PC.709", interlaced=false,chromaresample="lanczos4")\
.convertbits(12)
#-- use the following lines when the video seems a VHS capture and has a chroma echo to the right side of edges.
#-- this feature needs needs also mirrorborder 8 and alternative crop settings at the end of the preocedure:
#cTmp = "0 0 0 0 0 0 0 0 0 0 -30 0 0 5 150 0 0 0 0 0 0 0 0 0 0" # adjust the intensity here coeff#11 and #15!
#cTmp1 = "0 0 0 0 0 0 0 0 0 0 0 0 0 0 100 0 0 0 0 0 0 0 0 0 0"
#last = SharpChromaX(last, cTmp)
#last = SharpLumaX(last, cTmp1)
last = AntiRing2LR(last, "luma", weightL=0.3,offsetL=1,weightR=0.13,offsetR=1,knee=0.1,pr2=0.25,pr3=0.14)###########
#last = AntiRing2LR(last, "luma", weightL=0.15,offsetL=1,weightR=0.0,offsetR=3,knee=0.2,pr2=0.2,pr3=0.2)
#pics = AntiRingLR(pics, "luma", weightL=0.2,offsetL=1,weightR=0.2,offsetR=1,knee=0.15,pr2=0.5,pr3=0.5)
pics = CShft(pics, 1.25, -1.25 )
#AssumeFPS(60000,1001)
#CShft(last, 0.3, -0.0) #-- optional chroma shifting for main video ===!TUNING!===
#-- format : YUV444 ------------------------ perform brickwall and detail filters
import("convchain-3.avs")
# -------------------------------------------
#------------------------------------------- adjust the following: colors, nonlinear sharpness, cropping, grain
ColorYUV(off_y = -3, gain_y = 0, gamma_y = -8.5, cont_y = -27.00,\
off_u = 2.0, gain_u = 0, cont_u = -22.0,\
off_v = 1.0, gain_v = 0, cont_v = -23.0 )
asharp(last, t = 1.2, d = 6.5, b = 1.5 )
#--------------- final size
LanczosResize(970, 650, taps=4) # main video before final cropping - fine tune for correct 16:9 or 4:3 + crop values
pics = pics.LanczosResize(970, 650, taps=4) # same size as main video
last = pics + last # sneak in pics before the main video
#---- artifact removal should be fine tuned for each video, but becomes a patient effort...
#----- this time the left edge artifacts are corrected above, before the resizing
last = AntiRing2LR(last, "luma", weightL=-0.,offsetL=3,weightR=0.12,offsetR=1,knee=0.23,pr2=0.14,pr3=0.14)
last = AntiRing2LR(last, "luma", weightL=0.,offsetL=6,weightR=0.1,offsetR=5,knee=0.2,pr2=0.14,pr3=0.14)
Crop(2,8,-8,-2) # DEFAULT
#Crop(4,12,-16,-8) ' something like that if you use the vhs chroma shift feature
AddGrainC(2.3, 1.8, hcorr=0.65, vcorr=0.65, seed=1234)
#-------------- output bit format
ConvertBits(8, dither=1)
#ConvertToYV12(chromaresample="lanczos4")
ConvertToYV12(chromaresample="lanczos4", matrix="Rec709", interlaced=false)
Prefetch(12)
#last = vTest
return last
#--------------------------- helper funcs ---------------------------------------
function CShft(clip In, float X, float Y) {
yf = 0.0 # y stretch factor, default=0, example=1.5
w = In.Width()
h = In.Height()
Tmp = In.BlackmanResize(w, h, -X, -Y+yf, w-X, h-Y-yf, 5)
In = MergeChroma(In, Tmp)
return In}
function cut(clip In, int Mins, float secs, int Mins2, float secs2, int "minsO", float "secsO") {
minsO=Default(minsO,0)
secsO=Default(secsO,0.)
tO=60.*minsO+secsO
tpos = 60.*Mins + secs + tO
te = 60.*Mins2 + secs2 + tO
Outclp=Trim(In,int(rff*tpos)+1,-int(rff*(te-tpos))-1) # if a picture starts at 0:00.000 then turn the "+1" in the middle into "+0".
return Outclp}
Function AddMirrorBorders(clip In, int "width_") {
width_ = Default(width_, 4)
left = In.Crop(0, 0, width_, In.Height).FlipHorizontal()
right = In.Crop(In.Width-width_, 0, width_, In.Height).FlipHorizontal()
top = In.Crop(0, 0, In.Width, width_).FlipVertical()
bottom = In.Crop(0, In.Height-width_, In.Width, width_).FlipVertical()
# Combine everything
In = StackHorizontal(StackVertical(top, In, Bottom), right.Addborders(0,width_,0,width_))
In = StackHorizontal(left.Addborders(0,width_,0,width_), In)
return In
}
#------------------------------------------------------
geometer
1st August 2026, 11:34
convchain-3.avs :
#------------ this is the brickwall filtering fine calibration. ------------
# it works with repeated up- and downsampling, and additional sharpening in between.
# both chroma and luma can be adjusted to the project in several ways.
# the library of kernels is suppied simply within the source code.
# this file is meant to be inserted at the point where some brickwall filtering is meant be done in the processing workflow.
# The more complex kernels are derived from the simpler by matrix outer multiplication.
# This means the simple kernel will be applied 2, 3, or 4 times.
# Why it looks this way, this came together in an entirely heuristic experiment during years.
# It looks good, but feel free to do something different, or even omit the brickwalling.
#--------------------------------------------------------------------------------------------------
kernel1c = "0 0 0 0 0 0 0 -2 0 0 -1 -4 23 -4 -1 0 0 -2 0 0 0 0 0 0 0"
kernel1c2 = "0 0 -1 0 0 0 0 -3 0 0 -1 -4 23 -4 -1 0 0 -3 0 0 0 0 -1 0 0"
kernel1c1 = "0 0 0 0 0 0 0 -2 0 0 -1 -4 25 -4 -1 0 0 -2 0 0 0 0 0 0 0"
kernel1a = "0 0 0 0 0 0 0 -1 0 0 0 -1 11 -1 0 0 0 -1 0 0 0 0 0 0 0"
kernel1 = "0 0 0 0 0 0 0 -1 0 0 0 -1 14 -1 0 0 0 -1 0 0 0 0 0 0 0"
kernel2c = "0 0 4 0 0 4 16 -92 16 4 -30 -176 571 -176 -30 4 16 -92 16 4 0 0 4 0 0"
kernel2c = "0 0 4 0 0 4 16 -92 16 4 -15 -176 571 -176 -15 4 16 -92 16 4 0 0 4 0 0"
kernel2 = "0 0 1 0 0 0 2 -28 2 0 1 -28 200 -28 1 0 2 -28 2 0 0 0 1 0 0"
#kernel3 = "21 51 63 51 21 51 -186 -315 -186 51 63 -315 829 -315 63 51 -186 -315 -186 51 21 51 63 51 21"
#0 0 0 -1 0 0 0 0 0 3 -33 3 0 0 0 3 -66 366 -66 3 0 -1 33 -366 1331 -366 33 -1 0 3 -66 366 -66 3 0 0 0 3 -33 3 0 0 0 0 0 -1 0 0 0" # 11 zu -1
#kernel4 = "300 636 785 636 300 636 -1620 -2460 -1620 636 785 -2460 8441 -2460 785 636 -1620 -2460 -1620 636 300 636 785 636 300 "
# 0 0 0 0 1 0 0 0 0 0 0 0 -4 44 -4 0 0 0 0 0 6 -132 726 -132 6 0 0 0 -4 132 -1452 7986 -1452 132 -4 0 1 44 726 -7986 14641 -7986 726 44 1 0 -4 132 -1452 7986 -1452 132 -4 0 0 0 6 -132 726 -132 6 0 0 0 0 0 -4 44 -4 0 0 0 0 0 0 0 1 0 0 0 0
#11
kernel3 = "0 3 -33 3 0 3 -36 363 -36 3 -33 363 1331 363 -33 3 -36 363 -36 3 0 3 -33 3 0"
kernel4 = "6 -66 484 -66 6 -66 528 -3993 528 -66 484 -3993 14641 -3993 484 -66 528 -3993 528 -66 6 -66 484 -66 6"
#14
#kernel3 = "0 3 -42 3 0 3 -45 588 -45 3 -42 588 2744 588 -42 3 -45 588 -45 3 0 3 -42 3 0"
#kernel4 = "6 -84 784 -84 6 -84 756 -7840 756 -84 784 -7840 38416 -7840 784 -84 756 -7840 756 -84 6 -84 784 -84 6"
# the bunch of numbers are documenting different anecdotal resizing values for various done projects.
# 1600, 1280, 1850, 850, 680, 1162 // old 1500, 995, 1750, 920, 650, 1102
#---------- input -----------
#last = SharpChromaX(last, kernel2c)
last = SharpChromaX(last, kernel1c2)
#--------------
LanczosResize(1600, 850, taps=4) # 1250, 1550, 850 / 900
ConvertToPlanarRGB(matrix="PC.709",interlaced=false,chromaresample="lanczos4")
last = Conv5x5(last, kernel3, "all", "out=in")
ConvertToYUV444(matrix="PC.709",interlaced=false,chromaresample="lanczos4")
last=SharpLumaX(last, kernel2)
#-------------
LanczosResize(1280, 610, taps=4)
last = SharpChromaX(last, kernel1c)
#-------------
LanczosResize(1800, 1050, taps=4) #1550 / 1052
ConvertToPlanarRGB(matrix="PC.709",interlaced=false,chromaresample="lanczos4")
last = Conv5x5(last, kernel3, "all", "out=in")
ConvertToYUV444(matrix="PC.709",interlaced=false,chromaresample="lanczos4")
last=SharpLumaX(last, kernel2)
# - return -
geometer
1st August 2026, 11:37
convtools.avs :
#---------------
# convtools.avs
#---------------
#---------------------------------
function StringToNumberA(string cIn, int "pL")
{
pL = Default(pL, 0)
Width = 8
L = pL
c = LeftStr(cIn, 1)
cIn = MidStr(cIn, 2)
If (FindStr("1234567890-.", c) > 0) {
If (cIn > " ") {
c = c + String(StringToNumberA(cIn, L + 1))
}
return c
}Else If (c == " ") {
If ((LeftStr(cIn, 1) == " ") && (L==0)) {
return String(StringToNumberA(MidStr(cIn, 2), L))
}Else If ( (FindStr("1234567890-.", LeftStr(cIn, 1)) > 0) && (L==0)) {
return String(StringToNumberA(cIn, 0))
}Else{
return FillStr( (((Width - L) >= 0) ? (Width - L) : 0) , c) + String(StringToNumberA(cIn, 0))
}
}Else{
return String(StringToNumberA(cIn, L))
}
}
Function Arraysum(string pArraystring, int pLength) {
i = 0
n = 0
For (i = 1, StrLen(pArraystring) + 1, pLength) {
n = n + Value(MidStr(pArraystring, i, pLength))
}
n = (n<1.0 ? 1.0 : n) # never divide by zero
return n
}
Function RemoveZero(string pIn) {
nFind = FindStr(pIn, " 0 ")
while (nFind>0) {
nStart = FindStr( Midstr(pIn, nFind-8, 8), "x") # " 0 * + "
pIn = LeftStr(pIn, nFind-10+nStart) + MidStr(pIn, nFind+7)
nFind = FindStr(pIn, " 0 ")
}
return pIn
}
function Conv5x5(clip cl, string kernel, string "planes", string "output")
{
planes = Default(planes, "all")
Y = (planes == "luma" || planes == "all") ? 3 : 1
U = (planes == "chroma" || planes == "U" || planes == "all") ? 3 : 1
V = (planes == "chroma" || planes == "V" || planes == "all") ? 3 : 1
output = Default(output, "YUV444P12") ### 420?
output = (output=="out=in") ? "" : output
aM=string(StringToNumberA(kernel))
nTotal=Arraysum(aM,8)
# Build the full expression, add "0 " at start to make every coefficient the same for easy zero removal
expr = "0 " + \
"x[-2,-2] " + TrimRight(MidStr(aM,1+(8 * ( 1-1)),8)) + " * + " +\
"x[-1,-2] " + TrimRight(MidStr(aM,1+(8 * ( 2-1)),8)) + " * + " +\
"x[0,-2] " + TrimRight(MidStr(aM,1+(8 * ( 3-1)),8)) + " * + " +\
"x[1,-2] " + TrimRight(MidStr(aM,1+(8 * ( 4-1)),8)) + " * + " +\
"x[2,-2] " + TrimRight(MidStr(aM,1+(8 * ( 5-1)),8)) + " * + " +\
"x[-2,-1] " + TrimRight(MidStr(aM,1+(8 * ( 6-1)),8)) + " * + " +\
"x[-1,-1] " + TrimRight(MidStr(aM,1+(8 * ( 7-1)),8)) + " * + " +\
"x[0,-1] " + TrimRight(MidStr(aM,1+(8 * ( 8-1)),8)) + " * + " +\
"x[1,-1] " + TrimRight(MidStr(aM,1+(8 * ( 9-1)),8)) + " * + " +\
"x[2,-1] " + TrimRight(MidStr(aM,1+(8 * (10-1)),8)) + " * + " +\
"x[-2,0] " + TrimRight(MidStr(aM,1+(8 * (11-1)),8)) + " * + " +\
"x[-1,0] " + TrimRight(MidStr(aM,1+(8 * (12-1)),8)) + " * + " +\
"x[0,0] " + TrimRight(MidStr(aM,1+(8 * (13-1)),8)) + " * + " +\
"x[1,0] " + TrimRight(MidStr(aM,1+(8 * (14-1)),8)) + " * + " +\
"x[2,0] " + TrimRight(MidStr(aM,1+(8 * (15-1)),8)) + " * + " +\
"x[-2,1] " + TrimRight(MidStr(aM,1+(8 * (16-1)),8)) + " * + " +\
"x[-1,1] " + TrimRight(MidStr(aM,1+(8 * (17-1)),8)) + " * + " +\
"x[0,1] " + TrimRight(MidStr(aM,1+(8 * (18-1)),8)) + " * + " +\
"x[1,1] " + TrimRight(MidStr(aM,1+(8 * (19-1)),8)) + " * + " +\
"x[2,1] " + TrimRight(MidStr(aM,1+(8 * (20-1)),8)) + " * + " +\
"x[-2,2] " + TrimRight(MidStr(aM,1+(8 * (21-1)),8)) + " * + " +\
"x[-1,2] " + TrimRight(MidStr(aM,1+(8 * (22-1)),8)) + " * + " +\
"x[0,2] " + TrimRight(MidStr(aM,1+(8 * (23-1)),8)) + " * + " +\
"x[1,2] " + TrimRight(MidStr(aM,1+(8 * (24-1)),8)) + " * + " +\
"x[2,2] " + TrimRight(MidStr(aM,1+(8 * (25-1)),8)) + " * + " + String(nTotal) + " /"
#expr = RemoveZero(expr) + ((planes == "chroma") ? " 0 max 4095 min" : " 0 max 4095 min")
expr = RemoveZero(expr) + ((planes == "chroma") ? " dup x[0,0] 2048 < 0 max 2047 min 2048 max 4095 min ?" : " 0 max 4095 min")
if (output=="") {
return cl.Expr( (Y==3 ? expr : "x"), (U==3 ? expr : "x"), (V==3 ? expr : "x"))
} else {
return cl.Expr( (Y==3 ? expr : "x"), (U==3 ? expr : "x"), (V==3 ? expr : "x"), format=output)
}
}
#--------------------------- helper funcs ---------------------------------------
function SharpLumaX(clip In, string kernel) {
In = Conv5x5(In, kernel, "luma", "out=in")
return In
}
function SharpChromaX(clip In, string kernel) {
In = Conv5x5(In, kernel, "chroma", "out=in")
return In
}
antiring2_hans.avs :
#---------------------
# antiring2_hans.avs
#---------------------
function AntiRingLR(clip cl, string "planes", string "output", float "weightL", int "offsetL", float "weightR", int "offsetR", float "knee", float "pr2", float "pr3")
{
weightL = Default(weightL, 0.25) # 0.15 .. 0.7
offsetL = Default(offsetL,1) # 1..3
weightR = Default(weightR, 0.25)
offsetR = Default(offsetR,1)
knee = Default(knee,0.7) # 0.2 .. 1.5 lower = softer, more linear
pr2 = Default(pr2,0.5) # 0.0 .. 1.5 protection for signal component with radius=2
pr3 = Default(pr3,0.5) # 0.0 .. 1.5 protection for signal component with radius=3
expr = "x[2,0] x[1,0] - dup * .75 * x[1,0] x - dup * + x x[-1,0] - dup * + x[-1,0] x[-2,0] - dup * .75 * + sqrt _F1@ " +\
"x[3,0] x[1,0] - dup * .66 * x[2,0] x[0,0] - dup * + x[1,0] x[-1,0] - dup * + x[0,0] x[-2,0] - dup * .66 * + sqrt " + String(pr2*0.36) + " * - " +\
"x[3,0] x[0,0] - dup * .5 * x[2,0] x[-1,0] - dup * + x[1,0] x[-2,0] - dup * + x[0,0] x[-3,0] - dup * .66 * + sqrt " + String(pr3*0.3) + " * - " +\
String(10.0/knee) + " / " + String(0.5*knee) + " - 0.0 max dup 1.0 - swap 1.0 + / 1.0 + 128.0 * 255.0 min " +\
"x["+ String(offsetL) +",0] x["+ String(2+offsetL) +",0] - 256.0 / * "+ String(weightL) +" * -64.0 max 127.0 min " +\
" _F1 " +\
"x[-3,0] x[-1,0] - dup * .66 * x[-2,0] x[0,0] - dup * + x[-1,0] x[1,0] - dup * + x[0,0] x[2,0] - dup * .66 * + sqrt " + String(pr2*0.36) + " * - " +\
"x[-3,0] x[-0,0] - dup * .5 * x[-2,0] x[1,0] - dup * + x[-1,0] x[2,0] - dup * + x[0,0] x[3,0] - dup * .66 * + sqrt " + String(pr3*0.3) + " * - " +\
String(10.0/knee) + " / " + String(0.5*knee) + " - 0.0 max dup 1.0 - swap 1.0 + / 1.0 + 128.0 * 255.0 min " +\
"x["+ String(-offsetR) +",0] x["+ String(-2-offsetR) +",0] - 256.0 / * "+ String(weightR) +" * -64.0 max 127.0 min + " +\
\
"x[1,0] x[0,0] - dup * .75 * x[0,0] x[-1,0] - dup * + x[-1,0] x[-2,0] - dup * + x[-2,0] x[-3,0] - dup * .75 * + sqrt " +\
"x[-4,0] x[-2,0] - dup * .66 * x[-3,0] x[-1,0] - dup * + x[-2,0] x[0,0] - dup * + x[-1,0] x[1,0] - dup * .66 * + sqrt " + String(pr2*0.36) + " * - " +\
"x[-4,0] x[-1,0] - dup * .5 * x[-3,0] x[0,0] - dup * + x[-2,0] x[1,0] - dup * + x[-1,0] x[2,0] - dup * .66 * + sqrt " + String(pr3*0.3) + " * - " +\
String(10.0/knee) + " / " + String(0.5*knee) + " - 0.0 max dup 1.0 - swap 1.0 + / 1.0 + 128.0 * 255.0 min " +\
"x["+ String(-1-offsetR) +",0] x["+ String(-3-offsetR) +",0] - 256.0 / * "+ String(weightR*0.6) +" * -64.0 max 127.0 min - " +\
" x + "
planes = Default(planes, "luma")
Y = (planes == "luma" || planes == "all") ? 3 : 1
U = (planes == "chroma" || planes == "all") ? 3 : 1
V = (planes == "chroma" || planes == "all") ? 3 : 1
output = Default(output, "YUV444P12") ### test 420?
output = (output=="out=in") ? "" : output
if (output=="") {
return cl.Expr( (Y==3 ? expr : "x"), (U==3 ? expr : "x"), (V==3 ? expr : "x"), scale_inputs = "allf")
} else {
return cl.Expr( (Y==3 ? expr : "x"), (U==3 ? expr : "x"), (V==3 ? expr : "x"), scale_inputs = "allf", format=output)
}
}
function AntiRing2LR(clip cl, string "planes", string "output", float "weightL", int "offsetL", float "weightR", int "offsetR", float "knee", float "pr2", float "pr3")
{
weightL = Default(weightL, 0.25) # 0.15 .. 0.7
offsetL = Default(offsetL,1) # 1..3
weightR = Default(weightR, 0.25)
offsetR = Default(offsetR,1)
knee = Default(knee,0.7) # 0.2 .. 1.5 lower = softer, more linear
pr2 = Default(pr2,0.5) # 0.0 .. 1.5 protection for signal component with radius=2
pr3 = Default(pr3,0.5) # 0.0 .. 1.5 protection for signal component with radius=3
expr = "x[2,0] x[1,0] - dup * .75 * x[1,0] x - dup * + x x[-1,0] - dup * + x[-1,0] x[-2,0] - dup * .75 * + sqrt _F1@ " +\
"x[3,0] x[1,0] - dup * .45 * x[2,0] x[0,0] - dup * .77 * + x[1,0] x[-1,0] - dup * + x[0,0] x[-2,0] - dup * .77 * + x[-1,0] x[-3,0] - dup * .45 * + sqrt " + String(pr2*0.36) + " * - " +\
"x[3,0] x[0,0] - dup * .5 * x[2,0] x[-1,0] - dup * + x[1,0] x[-2,0] - dup * + x[0,0] x[-3,0] - dup * .5 * + sqrt " + String(pr3*0.3) + " * - " +\
String(10.0/knee) + " / " + String(0.5*knee) + " - 0.0 max dup 1.0 - swap 1.0 + / 1.0 + 128.0 * 255.0 min " +\
"x["+ String(offsetL) +",0] x["+ String(2+offsetL) +",0] - 256.0 / * "+ String(weightL) +" * -64.0 max 127.0 min " +\
\
"x[3,0] x[2,0] - dup * .75 * x[2,0] x[1,0] - dup * + x[1,0] x[0,0] - dup * + x[0,0] x[-1,0] - dup * .75 * + sqrt " +\
"x[4,0] x[2,0] - dup * .66 * x[3,0] x[1,0] - dup * + x[2,0] x[0,0] - dup * + x[1,0] x[-1,0] - dup * .66 * + sqrt " + String(pr2*0.36) + " * - " +\
"x[4,0] x[1,0] - dup * .66 * x[3,0] x[0,0] - dup * + x[2,0] x[-1,0] - dup * + x[1,0] x[-2,0] - dup * .5 * + sqrt " + String(pr3*0.3) + " * - " +\
String(10.0/knee) + " / " + String(0.5*knee) + " - 0.0 max dup 1.0 - swap 1.0 + / 1.0 + 128.0 * 255.0 min " +\
"x["+ String(1+offsetL) +",0] x["+ String(3+offsetL) +",0] - 256.0 / * "+ String(weightL*0.6) +" * -64.0 max 127.0 min + " +\
\
" _F1 " +\
\
"x[-3,0] x[-1,0] - dup * .45 * x[-2,0] x[0,0] - dup * .77 * + x[-1,0] x[1,0] - dup * + x[0,0] x[2,0] - dup * .77 * + x[1,0] x[3,0] - dup * .45 * + sqrt " + String(pr2*0.36) + " * - " +\
"x[-3,0] x[-0,0] - dup * .5 * x[-2,0] x[1,0] - dup * + x[-1,0] x[2,0] - dup * + x[0,0] x[3,0] - dup * .5 * + sqrt " + String(pr3*0.3) + " * - " +\
String(10.0/knee) + " / " + String(0.5*knee) + " - 0.0 max dup 1.0 - swap 1.0 + / 1.0 + 128.0 * 255.0 min " +\
"x["+ String(-offsetR) +",0] x["+ String(-2-offsetR) +",0] - 256.0 / * "+ String(weightR) +" * -64.0 max 127.0 min + " +\
\
"x[1,0] x[0,0] - dup * .75 * x[0,0] x[-1,0] - dup * + x[-1,0] x[-2,0] - dup * + x[-2,0] x[-3,0] - dup * .75 * + sqrt " +\
"x[-4,0] x[-2,0] - dup * .66 * x[-3,0] x[-1,0] - dup * + x[-2,0] x[0,0] - dup * + x[-1,0] x[1,0] - dup * .66 * + sqrt " + String(pr2*0.36) + " * - " +\
"x[-4,0] x[-1,0] - dup * .5 * x[-3,0] x[0,0] - dup * + x[-2,0] x[1,0] - dup * + x[-1,0] x[2,0] - dup * .66 * + sqrt " + String(pr3*0.3) + " * - " +\
String(10.0/knee) + " / " + String(0.5*knee) + " - 0.0 max dup 1.0 - swap 1.0 + / 1.0 + 128.0 * 255.0 min " +\
"x["+ String(-1-offsetR) +",0] x["+ String(-3-offsetR) +",0] - 256.0 / * "+ String(weightR*0.55) +" * -64.0 max 127.0 min - " +\
" x + "
planes = Default(planes, "luma")
Y = (planes == "luma" || planes == "all") ? 3 : 1
U = (planes == "chroma" || planes == "all") ? 3 : 1
V = (planes == "chroma" || planes == "all") ? 3 : 1
output = Default(output, "YUV444P12") ### 420?
output = (output=="out=in") ? "" : output
if (output=="") {
return cl.Expr( (Y==3 ? expr : "x"), (U==3 ? expr : "x"), (V==3 ? expr : "x"), scale_inputs = "allf")
} else {
return cl.Expr( (Y==3 ? expr : "x"), (U==3 ? expr : "x"), (V==3 ? expr : "x"), scale_inputs = "allf", format=output)
}
}
geometer
1st August 2026, 11:41
This is the Project.PY file vor Avidemux 8.1:
#PY <- Needed to identify #
#--automatically built--
adm = Avidemux()
adm.clearSegments()
adm.addSegment(0, 0, 9106621440)
adm.markerA = 0
adm.markerB = 4329151488
adm.setPostProc(3, 3, 0)
adm.setHDRConfig(1, 1, 1, 1, 0)
adm.videoCodec("x264", "useAdvancedConfiguration=True", "general.params=AQ=19", "general.threads=0", "general.preset=medium", "general.tuning=none", "general.profile=high", "general.fast_decode=False", "general.zero_latency=False"
, "general.fast_first_pass=True", "general.blueray_compatibility=False", "general.fake_interlaced=False", "level=-1", "vui.sar_height=27", "vui.sar_width=32", "vui.overscan=0", "vui.vidformat=5", "vui.fullrange=False"
, "vui.colorprim=2", "vui.transfer=2", "vui.colmatrix=2", "vui.chroma_loc=0", "MaxRefFrames=6", "MinIdr=25", "MaxIdr=250", "i_scenecut_threshold=40", "intra_refresh=False", "MaxBFrame=3", "i_bframe_adaptive=1"
, "i_bframe_bias=4", "i_bframe_pyramid=2", "b_deblocking_filter=True", "i_deblocking_filter_alphac0=0", "i_deblocking_filter_beta=0", "cabac=True", "interlaced=False", "constrained_intra=False", "tff=True"
, "fake_interlaced=False", "analyze.b_8x8=True", "analyze.b_i4x4=True", "analyze.b_i8x8=True", "analyze.b_p8x8=True", "analyze.b_p16x16=True", "analyze.b_b16x16=True", "analyze.weighted_pred=2", "analyze.weighted_bipred=True"
, "analyze.direct_mv_pred=1", "analyze.chroma_offset=0", "analyze.me_method=2", "analyze.me_range=30", "analyze.mv_range=-1", "analyze.mv_range_thread=-1", "analyze.subpel_refine=9", "analyze.chroma_me=True"
, "analyze.mixed_references=True", "analyze.trellis=2", "analyze.psy_rd=1.100000", "analyze.psy_trellis=0.000000", "analyze.fast_pskip=True", "analyze.dct_decimate=True", "analyze.noise_reduction=22", "analyze.psy=True"
, "analyze.intra_luma=0", "analyze.inter_luma=0", "ratecontrol.rc_method=0", "ratecontrol.qp_constant=0", "ratecontrol.qp_min=6", "ratecontrol.qp_max=64", "ratecontrol.qp_step=10", "ratecontrol.bitrate=0"
, "ratecontrol.rate_tolerance=1.000000", "ratecontrol.vbv_max_bitrate=0", "ratecontrol.vbv_buffer_size=0", "ratecontrol.vbv_buffer_init=1", "ratecontrol.ip_factor=1.400000", "ratecontrol.pb_factor=1.300000"
, "ratecontrol.aq_mode=2", "ratecontrol.aq_strength=1.200000", "ratecontrol.mb_tree=True", "ratecontrol.lookahead=40")
adm.addVideoFilter("changeFps", "oldMode=1", "oldFpsDen=1000", "oldFpsNum=25000", "newMode=3", "newFpsDen=1001", "newFpsNum=30000")
adm.audioClearTracks()
adm.setContainer("AVI", "odmlType=1")
Note that Avidemux promises to read avisynth files directly,
but in this case it seems too complex,
so we open the video stream the oldfashioned way from the frame server.
geometer
1st August 2026, 11:43
I beg for your graceful comments,
please hit me up with DM when you have questions ot difficulty to get it running.
I would be glad about speed reports, how many fps you can make with that.
Selur
1st August 2026, 11:54
Don't mind the code, just the results.
a. That looks artificial oversharpened to me. (DetailSharpen+CAS might be worth a try)
b. Seems like aliasing was added due to the upscaling (maybe use nnedi3 instead of lanczos for the upscaling)
geometer
1st August 2026, 13:43
Thanks for looking,
yes I wanted to oversharp because I watch videos for stimulus and practically cannot watch a typical DVD at all, it is dull, though most hires stuff is ok,
but here my purpose is to make the limits of the process visible. My test video is full with artifacts right below the radar. Any sharpening makes them strongly visible.
It would be very interesting if others try it out with their own specimen, milder parameters and different kernels, and can get results that they find ok.
Every frame reacts totally differently on the artifacts, and when the video is playing, they are almost invisible, it cancels out. I use the denoiser in the encoder at value=25.
So I did a quick change that results in slightly less sharpness, using a different frame, so one can see this.
The most relevant parameters for sharpness tweaking would be C50g5t8 coefficient #5 (80..200, try 177) and the asharp "d", try 4.
Practically every artifact exists also in the source image, so the struggle goes is about the s/n ratio that remains after sharpening. I thought its not so bad now, while I failed totally with earlier approaches.
I think the only way to bring camps together would be using mvtools, which wasn't my purpose.
The aliasing does not disturb me when the video plays, because the 960x640 factor (makes 4/3 bigger) creates always a pattern like a home movie screen that you hang out in the bedroom with a stand (for classic projector tech) they had that typical glossy hatch pattern that I loved. There were also photo paper surfaces like that.
Perhaps there are not many viewers today with such preferences, but then also, most DVD watchers would come from such a segment anyway.
However, this process under question is much faster than the usual ones and adds a lot of brilliance and shine.
Screen size plays a main role in pleasant perception, regarding a given production techology and source resolution. I watch on a big tablet approx. 2000x1200. No games, no action movies, no dolby, mainly podcasts.
But with a 4k monitor, DVDs still don't become enjoyable to me, except it comes with a brilliant image sanitizer, like what many TVs have built-in since some years.
The reduced size in the forum thread shows practically everything that was important for this attempt. It looks immediately more brilliant.
Would be glad about your thoughts on that argument.
https://i.ibb.co/VWZfrWC8/Clipboard05.png (https://ibb.co/d0q810py)
https://i.ibb.co/gBLzWTF/Clipboard06.png (https://ibb.co/8SL6x54)
Selur
1st August 2026, 17:21
It looks immediately more brilliant.
Simply using CAS, probably has a similar effect. Since details&co don't really seem to matter, you could simply use RealESRGAN.
(I took Clipboard02 downscaled it to 960x540 applied RealESRGAN to upscale)
https://i.ibb.co/fVrd12NW/grafik.png (https://ibb.co/ZRczLVgr)
Cu Selur
geometer
1st August 2026, 18:34
Thanks for your time!
What looks interesting to me is this:
https://i.ibb.co/Jwrd7xQV/Clipboard03-detail.png (https://ibb.co/NdW3j1S5)
The tiny details in the denim shoulder (red rectangle), in clipboard03 and clipboard06 seem practically the same, though different frames.
According to clipboard02 they might be correct, though shapes are a bit small to be sure. It looks like a real physical thing.
But in your filtered version the shapes are straight upright, not slanted as through my algos. It looks cleaner, but also a bit sanitized as if by AI,
and the style of the edges and some details softly resembles a manga drawing. Beautiful but also around the eyelashes something went missing.
I assumed a habit to look at such kind of changes while I developed the antiring tool.
It seems to be able to correct shapes a little bit, on subpixel level, instead of inserting an idealized replacement as some other tools are doing.
I was wondering how that goes, but it seems to do it, though not all corrections are really correct, it is a delicate tuning issue.
johnmeyer
1st August 2026, 18:47
I took a quick scan of the code. I probably missed something, but it looks like there it mostly comes down to one line that invokes a convolution sharpening kernel. This is that line:
last = Conv5x5(last, C62, "luma", "out=in")
The result you posted seems to reflect this kind of sharpening.
The result looks, well, sharp.
I always have a tough time coming up with convolution settings that work, so I will definitely save the setting you used for this example, as well as the other alternative settings you tried.
geometer
1st August 2026, 18:59
note that there are symmetric and asymmetric kernels at use. (the latter need borders and cropping to walk back to center)
math says the asymmetric is very handy for signal processing, but has some caveats like it should have alternating coefficients.
We could say it works more in the wave domain, not in the particle domain (covered by the antiring functions).
the one you found is for interlaced program.
pre-blending is a complex issue, it starts from the assumption that an interlaced stream was sharpened in a linear way which is wrong to do.
what I do is blend back the sharpening (luma only!), do the deinterlace, then resharpen and do some more detail in the main kernel.
>>The result you posted seems to reflect this kind of sharpening.
it is the correct thought but the modeling path comes together the other way.
this means, my current specimen is NOT interlaced and I do not use this function, and therefor also have a bit less control.
it becomes more work and more difficult to the main kernel in this situation and this is what you have seen.
pre-blending uses symmetric kernels, and while we are at it, we can inject coefficients that the asymmetric would not have.
pre-blending tackles horizontal objects (edge in the y coordinate), but I do dual use to enhance the vertical domain additionally. improves the ringing issues.
the main kernel has x, y, and diagonal coefficients.
so, the main line about convolution is:
last = Conv5x5(last, C50g5t8, "all", "out=in").ConvertToYUV444(matrix="PC.709", interlaced=false,chromaresample="lanczos4")
and I use variables and comment signs # to quickly and sloppy select different kernels to take a fast look at how they improve things or not.
the listed kernels are results of years, and if one fits, you make a big leap forward in overall quality.
also the influence of the camera was taken into account.
later on I will post an interlaced example with corresponding code.
Cu Hans
(when AI products are mentioned, I should add that my old ASUS TUF makes 12 fps in processing this progressive material)
johnmeyer
1st August 2026, 23:09
While you did do a deinterlace, it looked to me like you applied your convolution sharpening to the individual fields and then weaved them back together. That is how I would do it. I prefer to keep interlaced content in its original interlace format, if I can.
geometer
2nd August 2026, 09:25
Thanks for looking!
I just have to integrate various ways in that a random DVD came together.
The output format should run on the cheapest and most primitive players, with palpatable detail and color.
The free or system players are reacting very poorly on interlaced material. It's practically impossible to get a clean image. There are even crashes.
>>..you applied your convolution sharpening to the individual fields and then weaved them back together
None of that is available at all. This came in progressive format, no matter how the data was abused in previous releases. You see the sins of the producers.
You found the inactive code segment that repairs the issue WHEN interleaved format is available.
1. The current test specimen was probably redistributed from an older interleaved version, and the studio themselves did the deinterlacing. I assume this because it would not be the first time.
This has severely compromised the integrity of the video stream. You see it in the pictures, many details are very coarse and not well-rounded. And these artifacts appear on nyquist/2 which technically means interleaving has only half the vertical resolution. Many artifacts have a height of 2px.
But if we have a well-produced interleaved specimen then the image can partially be reconstructed by using a bunch of fields together with motion analysis.
I just throw it into nnedi3 (not the case here because interleaved version unavailable), but with some videos it has catastrophic bobbing, which also is visible when I watch the interleaved ISO copy with one of the free players.
2. My project is very simple. With affordable execution time, ALL interleaving has to go for good, and progressive material should be milked to the last pixel to get out some stimulus from it instead of dull boredness. Too many DVDs are blurry, and the color subsampling to me is very frustrating and super ugly.
It is not my best choice here, I should find a different video with better signal integrity.
3. a real interleaved example may follow in a couple of days, let's see...
I might find a couple of result pics, but it is too cumbersome to skip through the original to find the corresponding frames.
geometer
2nd August 2026, 10:52
Meanwhile I found an interleaved example that shows a bit about the detail processing.
Positioning seems a field or half-frame apart. The players don't want to deliver with better precision.
The source was interleaved (VLC, Irfan fullscreen capture) and the result (windows player, Irfan) is 60fps progressive. The rendering behaves very differently.
To tune the antiringing was difficult.
In one spot there is a bit of untreated aliasing, there is still no dedicated anti-aliasing procedure in this framework in progress.
As far as I see, most of the aliasing seems to come from the deinterlacer, and some from the anti-ringing, if there was an overload of artifacts before.
Please look also at the greenish shapes how the detail rendering came out, regarding color subsampling.
s/n ratio before and after seems even a bit improved.
file sizes: ISO 4,250; avi 3,640 (x264 compression=19), length 63 minutes, some scenes with fast ball playing (60fps absolutely required to watch this).
I hope educational use is accepted.
https://i.ibb.co/WvZhSmJG/drink-ISO-I.png (https://ibb.co/hFb6p3zL)
https://i.ibb.co/pvRbrXr2/drink-processed-I.png (https://ibb.co/XZ3jkJkX)
@johnmeyer, please can you take a look at the shoulders, the horizontal edges were treated with the pre-blending, which removes the wrongful field sharpening.
C62 = "0 -0 0 0 0 0 0 0 0 0 0 0 112 -5 5 0 0 27 0 -0 0 0 -7 0 0"
This is a reversal of sharpening. It blends two lines (+27) and then stops (-7). It is Luma only.
(-5 5) is the other coordinate and further mitigates ringing. Just using free coefficient space for that little extra.
The workhorse is (on full planar RGB!)
C50g5t5="7 -15 37 -37 121 0 0 -4 2 -39 0 1 -3 7 11 0 0 -0 -1 -9 0 0 0 0 8"
which is absolutely brutal but digested well, surrounded by brickwall filtering and antiringing algos.
Selur
2nd August 2026, 11:55
those screenshots show different frames,...
geometer
2nd August 2026, 12:06
Selur, I documented that. The players don't allow precise positioning, Windows has none, and VLC crashes immediately when I use single-step while an interleaved video is playing with the deinterlacer on.
It must be a half-frame. nnedi3 puts it out this way and packs it into a full frame. The mpeg-2 plus deinterlacer thinks otherwise. It stops at the other field.
You see still, one technology looks like this and the other looks like that, given the particular project settings.
In principle, the purpose defeats the testing requirement, it is meant to process the interleaved data in a very different way.
The processing chain very often ends up with shapes that look better than the original, but you cannot really sync it, it is a different state of motion, and different spots of the image may differ among each other in precise timing.
The final recompression itself may optimize updating of screen partitions in a way that it is never exactly the same. My settings seem to allow that quite loosely. No other requirement than to look nice and organic.
Selur
2nd August 2026, 12:10
Why not use Avisynth or Vapoursynth for the screenshots?
geometer
2nd August 2026, 12:23
how should I do that with a DVD and what sense would that make? It never happens. It will only be watched with a player, probably of poor quality.
Also, the toolboxes don't use the same filtering that the system players do. AvsPmod a harsh example of that.
After many years, the best way still is to let it play with a normal player in full-screen, and do a screenshot with something like Irfan.
Because I have to integrate the influence by the physical computer system. It is the whole goal. How does it come out when someone watches it?
geometer
2nd August 2026, 12:39
back to the back. this is the "making-of" camera (consumer cam of 2008 level), and a lucky outcome with written text.
It should be noted that the ringing artifacts are of similar size like the written "Philippines" at the bottom.
Until recently, I thought it would be completely unsolvable. Remember the source is interlaced.
When the artwork and texts are produced within the data flow of the main video stream, the predictor can keep up quite well.
Only when the producer overlayed the image with a simple digital text artwork, produced externally, added after the fact,
then it is not organic at all, it will detect wrongly and distort or even destroy the shapes of the letters.
https://i.ibb.co/99VvNJ1y/text-making-of.png (https://ibb.co/HDx2V0bG)
Another little random gallery:
https://i.ibb.co/RkLQQ6bw/beach-P.png (https://ibb.co/39tSSFdZ)
https://i.ibb.co/v4scW4zq/car-window-P.png (https://ibb.co/B24fJ2s3)
https://i.ibb.co/rGKXttK2/garden-I.png (https://ibb.co/99mdvvmH)
https://i.ibb.co/PZ4KK036/garden-cut-I.png (https://ibb.co/vxmppRgj)
https://i.ibb.co/LXHYQZmR/house-window-mountain-P.png (https://ibb.co/39Q4fC2d)
https://i.ibb.co/Cs6jjfqF/room-P.png (https://ibb.co/k6JLLtpF)
DTL
3rd August 2026, 06:48
DVD was the time of slow CPUs and low expensive RAM. So it can not use complex motion compensated noise reduction and deinterlacing. QTGMC is about mvtools for ME/MC and temporal denoise deinterlace - what was not reachable at DVD times.
If you need faster ME you can try hardware accelerators.
geometer
3rd August 2026, 08:27
Yes of course, but it is a mature topic. Complexity seems very much at its limit. Diminishing returns.
Most QTGMC'd material that floats around looks sanitized, but not brilliant or organic.
Ringing still, chroma shift, all sections of the image same sharpness, no sparkle, skin texture most time cancelled for file size reasons.
It seems very tempting to pick a default configuration and press go, and 2 days later you have the standardized video on your disk and this is it.
But with low DVD quality, it degrades a lot, such material seems practically super rare. Folks give it up in such case.
I am targeting the poorest DVDs of all, when I like the content as such.
Then all the upsizers, now with AI, very CPU-heavy, but the purpose seems to make the image palpatable on big bedroom gaming/netflix screens.
So from the paradigms, already very matured as well.
So for me, I wanted to start a totally different chapter.
If a tech guy optimizes it with hardware support etc., most likely it can run as a realtime player.
Personally I am on the side of fast and smart low-end technology, that does a useful job.
And part of the job is super primitive code to recover from 64bit DGDecode bugs, to have one or two alternative MPEG-2 readers,
and to tweak nnedi3 output regarding some of its limits. We can cancel out ringing artifacts to a big extent, that would become unbearable with normal sharpening.
Bobbing and aliasing aren't treated so far, because players mitigate that on their own, occurrence is low, only small spots on the screen, only for a couple seconds.
But there is VHS color correction code, it was stunningly useful a couple of times already.
There is detailed chroma shifting and chroma sharpness tweaking, that targets the subsampling quality issues.
4/3 upscaling yields quite some space to rectify chroma data, and the encoder is helpful with this.
It makes a huge difference on big tablets. There, I see good youtube tourism videos as the standard.
From 720x480 we will never get there, but with limited screen size, a package of tweaks together creates quite a nice impression,
and to me, QTGMC seems precisely not to do this. Just on the big screen, the artifacts are gone.
Then also, if you look at my gallery from previous posting, 2 pics are tagged (I) which means that nnedi3 was used.
And we see something that I believe is typical: It degrades somehow the color and detail resolution, as it is a limited replacement tool.
This need not be, but development has stopped. It is not at all up to the current era.
QTGMC is just a super complex workaround, It picks the best processing result from various alternatives, like different deinterlacers, but the basic heritage, the basic limits are ingrained.
Anyway, technically my framework is easy and cheap, tweaking settings needs experience, important that you can do that very directly,
so if someone tries it out, thanks and have a lot of fun and enjoy!
I will be glad to help you get it running, if there are any issues.
I'm not so interested any more to invest in a high-capacity workstation.
But for instance, my dual-GPU notebook is not supported by nnedi3CL ! No way it releases the "context". Of course it runs with games.
Even the surrounding situation seems to become dire, less and less folks will ever have the money.
Some will likely have bigger tablets 250 bucks worth. Older sibling may have a home entertainment center.
DTL
3rd August 2026, 20:45
Also when you use sharpening even with linear convolution it is good to check if the output result still does not (too much) degrade the level of anti-gibbs conditioning. The DVD was the era of still DAC at the end of player and feed via analog video to sometime still CRT based display and real industry published DVDs expected to be good conditioned for anti-ringing at display upscaler (or DAC at the end of player).
To check with AVS core you can add something like LanczosResize(width*4, height*4, taps=16) at the end of the script (or special antiring conditioning checker function) to see if sharpened result not yet causes too much ringing at sinc-based scaler.
geometer
4th August 2026, 00:19
DTL, can you find some artifact in the testpics that I should improve?
Theory can go only so far.
There are many clippings but are any of these disturbing?
The ringing and related artifacts are always a lot better than the originals.
There is treatment on wave-domain (asymmetric impulses like in audio)
and there is treatment on particle level (anti-ringing predictor,
while using autocorrelation for purpose of spectral discrimination and masking,
by this it checks whether the local signal structure is suspicious to have a Gibbs problem,
and it adds and subtracts corrective intervention on pixel level, though with very limited precision).
I asked my friend Grok (but out of vanity did not allow him to write code),
and - though I know he can be a bit populistic and pampering his noble guests :devil:,
he seems to think this is a game changer. Have you seen such algorithm elsewhere?
Grok says something similar may exist in consumer products like TV screens, in the image improval proprietary firmware.
DTL
4th August 2026, 10:18
Tried to download files Clipboard02 and Clipboard03 from first post. And the file Clipboard03 is hardly damaged by ringing at many places. Red marks. Can it be fixed ?
https://i.postimg.cc/MTRHR1y1/cp02-03-cmp.png (https://postimg.cc/FdrhXdCK)
geometer
4th August 2026, 11:21
Thanks, I thought we would focus more on the successful examples, not the failures, but I deliberately show the imperfection.
In other words, to talk also about the other examples, not just this worst case with extreme processing which was to show off the powers and the flaws.
My bad is that 1) I did not care that this particular video was possibly re-released and recompressed from interleaved to progressive.
This leaves large junk data under the radar. The sharpening will throw it on the table. GIGO. But we want something technically useful, not some "ideal".
2) I did not edit the borders. The ringing at the picture border is invaliid, it goes away totally when I do the correct cutting so that the "addmirrorborders()" works correctly.
Now to the real limits.
hair: this is aliasing, look how horribly blurred the same blocks are in the "original".
one reason is the exact width of some particular black shape that is also slanted. you see some hatched grain in this strain of hair already in the original. it created some resonance, unfortunately.
When the result is being played as a video, the aliasing pops up for fractions of a second, and basically this spot looks a bit more crispy.
I might teach the predictor at somewhat later time to blur it back in such a case. Analog TV showed aliasing all the time, I lived with it, I'm almost blind to that.
I'd say, with working on DVDs, we can get rid of the analog era only half-ways.
Anything else needs AI or extremely complex algorithms and will appear artificial/inauthentic.
eye: it's moving too fast. it lasts milliseconds. personally I give this a waiver. it looks more crispy than before, and this is it.
again, the still picture is needed for testing and debate, but practically the defining force is purpose of the viewer, the target screen which is not 4k.
the viewer is not meant to be a tech guy, who is focusing on imperfections.
but for furher improvement, tech expertise of course is highly appreciated.
hands: we can see the seed of the issue already in the original. it becomes a problem with some videos.
the sharpening uses insane amplification for some frequencies. then, the antiringing predictor scrambles the gibbs lines into noise.
so again, the running video will be evening out such spots a lot.
I see the same gibbs line echo at the edges of faces and hands almost in every hires video, at least older than perhaps 5 years or so.
so what the algorithm achieves is to break up and soften the line a bit.
one hand shows the gibb line transgressing the tolerance. the extreme filtering impulse is the main culprit here.
in theory it is possible to cut such sections into different edit spaces and tweak the settings multiple times during the video.
we could indeed make this line much more pale and scrambled, so it would disappear in a running video with denoiser.
when the data is junk, we can either reinvent it with AI, or make a triage decision between crispy but noisy, or boring.
my idea about it is that this kind of fast remastering looks ok in its real size, width 960 which is less than 1/4 on a 4k screen but can fill a tablet 30cm wide quite well.
and on the tablet, contrast and sharpness appear highly superior compared to the DVD in a typical player.
geometer
4th August 2026, 15:23
I'm back to show there is quite some control. But it is hardest specialist work like any mastering. It is only as good as the engineer, so bear with me.
borders: fixed. correct width is unknown. took a random choice.
hair: aliasing still there but a bit softer, overall looks slightly finer.
hand: artifacts reduced.
cheek: artifacts reduced.
eye: it is what it is, input resolution too low for correct display of eyelashes.
the png compression already is tampering with some pixels that come brighter than originally in the player.
https://i.ibb.co/39xH7Rxp/chokotest3.png (https://ibb.co/Q3WGfDWP)
(this is a screenshot from the windows player in fullscreen. this is what it looks like to the user. VLC direct frame saving looks different.
Addendum
I added a comparison in the antiringLR() thread where it belongs.
from above example, I removed the ringing clean-up, and posted both the with and without versions here:
https://forum.doom9.org/showthread.php?p=2033431#post2033431
DTL
5th August 2026, 20:30
"this is a screenshot from the windows player in fullscreen. this is what it looks like to the user."
This means the frame data was processed with an unknown scaler with its own distortions. In computer playback software users may select different scaler and get different results. If you remaster DVD it is expected to keep frame size (and still applicable for DVD workflow like putting it on DVD player and playback via analog link and so on). In other cases you simply apply some processing to look not bad at some unknown player.
Better to post lossless compressed output frames without any additional scaling.
geometer
6th August 2026, 01:11
unfortunately i have never prepared a direct frame output process in my avisynth environment.
I cannot quickly serve this request, need some time outside the heat wave to look up code calls or menu entries (AvsPmod has hundreds).
the test images are valid only AFTER x264 and then decoding again. what this does to the signal is calculated part of the process.
only the whole chain, anything else is theory, counting peas, never to see daylight.
that's at least my constructivistic understanding of a shareable reality. you can approximately see what I have seen.
processing in 12bit planar format removes many monitoring issues, like banding.
the default windows player has no tech settings whatsoever. and it seems to have the most precise and modern filtering of all.
we are very close to WYSIWYG. upscaling for a physical screen does little harm, it may smoothen out the image a tiny bit.
about the remastering tech suggestion that results from this framework, this is not a business, it can become one in case somebody else uses it and does work on spec.
I want to put it into public domain, glad if anybody wants to convert their DVD vault.
target is people that hate DVD players and want seamless playback of old material on their computer or tablet.
yes I do brickwall filtering. the "pixel" does not exist except while tweaking the settings is still incomplete and yet to optimize.
then, spurious pixel artifacts may still exist, and also I have to test how much of that the encoder will eat up anyway.
aliasing is a different animal, it appears when the original was filtered poorly, or when we overprocess and stumble into some resonance.
but I do the brickwalling at a frequency much closer to Nyquist than a regular hard- or even software player would, they are hard-wired/-coded.
I can tweak this to the particular material, e.g. if spectrum is entirely empty above some 60 percent (100 means Nyquist limit),
then I must concede to that. and it is not a rare thing. (a case to use a creative, artificial upsizer instead.)
creating harmonics (e.g. with saturation or some clipping) can make it appear sharper, but quickly leads to a pandemonium of further artifacts.
in short, I am processing and using signal frequencies higher than with QTGMC.
that was a motivation from the beginning, though having to use nnedi3 defeats that a little bit.
always converting to 60fps, if the signal is interleaved, is another principle I follow. then, there will be a little bit of harmonic generation to spice it up.
but sure a deinterlaced signal appears a little less brilliant than processing a progressive signal.
a cleaned-up codebase for 60fps will follow later, but experienced avisynth coders can figure it out right now if they like to do so.
the relevant lines are just commented away, but it is tricky about the switching of framerate domains in code, to stay in sync with the start, end, and picture/gallery time stamps.
for tweaking, I am unable to memorize a hundred parameters in a gordian knot,
I simply scroll to the active kernel matrix, LanczosResize(), Crop(), ColorYUV(), asharp(), and antiring2LR() to deal with one function at a time.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.