View Full Version : How to combine many parts of a clip?
Arx1meD
26th February 2026, 17:42
How to combine many parts of a clip?
Need help with an easy way to combine many parts of a clip. Sometimes I need to split a clip into many parts and process these parts with different filters. Then I need to combine these parts back into a whole clip.
For example:
p1 = last.Trim(n1,n2).Filter_1(...)
p2 = last.Trim(n3,n4).Filter_2(...)
p3 = last.Trim(n5,n6).Filter_3(...)
...
pn = last.Trim(ni,nj).Filter_i(...)
p1+p2+p3+...+pn
Sometimes there can be over 100 parts of a clip.
For example, I tried to combine parts of the clip like this:
j = NULL()
for(i = 1, 30) { j = String(j)+"+"+"p"+String(i) }
return MidStr(j, 2) - AviSynth gives an error: Not a clip.
or this:
MidStr(j, 2) - AviSynth ignores this line.
or this:
Value(MidStr(j, 2)) - AviSynth ignores this line.
Is there a simple way to combine parts of a clip?
VoodooFX
26th February 2026, 19:39
What about something like this:
LWLibAvVideoSource("D:\video.mkv")
Effect1=last.SomeFilter1()
Effect2=last.SomeFilter2()
# Func from RemapFrames plugin. Stuff in "[]" are ranges
# BTW, you can use multiple ranges like that: ReplaceFramesSimple(Effect1, mappings="[10819 10835] [46845 70777]")
ReplaceFramesSimple(Effect1, mappings="[10819 10835]")
ReplaceFramesSimple(Effect2, mappings="[25545 43543]")
ReplaceFramesSimple(Effect1, mappings="[46845 70777]")
Lately, I've been using this method since it's the most convenient for me.
EDIT:
I previously used StainlessS' ClipClop. There you can find some examples: https://forum.doom9.org/showthread.php?p=1957654#post1957654
StainlessS
26th February 2026, 21:22
~Arx1meD,
ClipClop thread:- https://forum.doom9.org/showthread.php?t=162266
With brief note on usage,
ClipClop() v1.10, Range/Frame Replacement Plugin for Avisynth v2.5+ by StainlessS.
Planar, YUY2, RGB32, RGB24.
Does NOT affect Audio (as source clip).
Clipclop is a simple plugin to replace ranges in a source clip with the same range, from a replacement clip.
Supports up to 255 replacement clips, with unlimited number of replacements into output clip.
If you wanted to do 1000 single frame replacements in script, that would require 3 trims and 2 splices for each
replaced frame, ie 3000 trims and 2000 splices. This would involve 5000 'zero cost' filters which together will
cost a little more than zero. With ClipClop(), this is reduced to 1 single filter with an overhead of approx
1 trim or splice filter. There is a small overhead setting up the filter (before the very 1st frame is fetched)
while parsing the file/string commands, but then parsing and setting up 5000 trim/splice filters in a script
would not be without cost either. Clipclop can parse in the region of 40000 commands (from file) in about 1 second
[guessed, based on timing the sister plugin Prune(), a trim/splice plugin].
v1.10, Implements 'Nickname's, Pseudonyms for the replacement clips, ie instead of '17 100,200' you could use eg 'dn 100,200',
in this case it might be to replace frames 100 to 200 of the source clip with the same frames of a denoised clip (clip 17).
OR, 'cp 345' to replace frame 345 with a clip where frame n was copied from frame n-1 of the source clip, ie CopyFromPrevious
[this could be generated via 'SelectEvery(1,-1)', or 'CopyFromNext' clip by 'SelectEvery(1,1)].
Supports Nicknames of up to 31 characters in length so you could use eg 'PredictFromPrevious 1234', or 'FlippedVertical 666,999'.
Nicknames allow you to think in terms of functionality rather than to keep looking up which clip index holds a modified clip
and you could actually write your command file/string before you even know how many clips you need, what clip index they will be,
or even how you will actually create/process the clip.
Once you've tried ClipClop(), you will wonder why you spent all those years doing it the hard way.
(Repeat after me, "I dooo believe in Fairies!".)
EDIT: Above brief note from some time back, so long as you dont use any clipclop implemented on-frame text output, then can also use with additional colorspaces including HBD.
EDIT: Actually, I'm not sure but I think I did latest version with DDigit text renderer, so above about on-frame text output no longer a problem. (I think)
Example from ClipClop thread:
Example usage script using NickNames:
###
Avisource("D:\avs\test.avi")
ORG=Last
V1 = FFT3DFilter(Plane=0,Sigma=1.6) # Light Luma
V2 = FFT3DFilter(Plane=0,Sigma=2.0) # Med Luma
V3 = FFT3DFilter(Plane=0,Sigma=4.0) # High Luma
V4 = FFT3DFilter(Plane=3,Sigma=1.6) # Light Chroma
V5 = FFT3DFilter(Plane=3,Sigma=2.0) # Med Chroma
V6 = FFT3DFilter(Plane=3,Sigma=4.0) # High Chroma
V7 = FFT3DFilter(Plane=4,Sigma=1.6) # Light Luma+Chroma
V8 = FFT3DFilter(Plane=4,Sigma=2.0) # Med Luma+Chroma
V9 = FFT3DFilter(Plane=4,Sigma=4.0) # High Luma+Chroma
V10= FlipHorizontal() # Flip-H
V11= FlipVertical() # Flip-V
V12= Invert() # Invert
NickNames =""" # Psuedonyms for clips
L0 = 1 # Light Luma
L1 = 2 # Med Luma
L2 = 3 # High Luma
C0 = 4 # Light Chroma
C1 = 5 # Med Chroma
C2 = 6 # High Chroma
LC0 = 7 # Light Luma + Chroma
LC1 = 8 # Med Luma + Chroma
LC2 = 9 # High Luma + Chroma
FH = 10 # Flip-H
FV = 11 # Flip-V
INV = 12 # Invert
"""
SCMD=""" # Clip editing commands in string, can also use commands in file
C0 0,99 # Light Chroma frames @ 0 -> 99
L0 100,-200 # Light Luma frames @ 100, 200 frames ie frames 100->299
INV 300,399 # Invert 300->399
L0 400,499 # Light Luma frames 400->499
FH 500,599 # Flip-H 500->599
LC2 600,699 # High Luma + Chroma
C1 800 # Med Chroma, Single frame
1 900,999 # Light Luma, We used the clip number instead of a NickName
FV 1000,1099 # Flip-V
LC1 2000,0 # Med Luma + Chroma, 2000 -> lastframe
"""
SHOW=True
ClipClop(ORG,V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,scmd=SCMD,nickname=NickNames,show=SHOW)
EDIT: From last post in ClipClop thread
ClipClop v1.27, see 1st post.
[Available only on MediaFire in sig below this post, having problems getting into my SendSpace account].
02/Nov/2017 - ver 1.25 - Recompile vs 2008
27/Oct/2018 - ver 1.26 - Add x64.
27/Jul/2021 - ver 1.27 - Add HBD text render [Show/Ver] using DDigit v2.0.
Would previously work just fine with HBD clips, except where Show = true OR Ver = True, ie printing metrics text on frame.
So yes, on-frame text render is implemented for HBD clips.
hello_hello
27th February 2026, 14:11
For example, I tried to combine parts of the clip like this:
j = NULL()
for(i = 1, 30) { j = String(j)+"+"+"p"+String(i) }
return MidStr(j, 2) - AviSynth gives an error: Not a clip.
or this:
MidStr(j, 2) - AviSynth ignores this line.
or this:
Value(MidStr(j, 2)) - AviSynth ignores this line.
Is there a simple way to combine parts of a clip?
Try this:
P1 = BlankClip()
P2 = BlankClip(color=color_red)
P3 = BlankClip(color=color_blue)
P4 = BlankClip(color=color_yellow)
Output = P1
for(i = 2, 4) { Output = Output + Eval("P" + String(i)) }
return Output
By the way, if any of the filters require access to earlier or later frames as well as the current one (some denoising, for example) it might be better to do it this way.
P1 = last.Filter_1(...).Trim(n1,n2)
P2 = last.Filter_2(...).Trim(n3,n4)
P3 = last.Filter_3(...).Trim(n5,n6)
Or this way to make it easier to repeat the same filtering:
A = last.Filter_1(...)
B = last.Filter_2(...)
C = last.Filter_3(...)
P1 = A.Trim(n1,n2)
P2 = B.Trim(n3,n4)
P3 = C.Trim(n5,n6)
P4 = B.Trim(n7,n8)
Or if the parts are already in order you could just do it like this:
A = last.Filter_1(...)
B = last.Filter_2(...)
C = last.Filter_3(...)
A.Trim(n1,n2) + \
B.Trim(n3,n4) + \
C.Trim(n5,n6) + \
B.Trim(n7,n8)
gispos
27th February 2026, 16:30
I'm not sure if I understood everything correctly.
So, to add filters only to certain areas, I use AvsPmod selections with ApplyFilter or ClipClop.
If you only want to use short sections of the clip, you first need to write the selections as trims into the script (Timeline context menu 'All as trim').
Take a look at these two videos.
https://drive.google.com/file/d/1ziKU-LMAk5dmb5PbJ-_XkVwuEml1Jk_t/view?usp=drive_link
https://drive.google.com/file/d/1hB4LIfMLT5muAF9jTNfHOHqLCJUIEl6E/view?usp=drive_link
Columbo
27th February 2026, 16:44
I think he just doesn't want to type p1+p2+p3+...+pn when it includes hundreds of parts. On the other hand, he had to type hundreds of trims. :confused:
hello_hello
27th February 2026, 17:09
gispos,
I've never used ApplyFilter in AvsPmod, although I'll play around with it sometime soon, but for filters that might benefit from being able to request frames outside of the Trim range, would something like this work? Just replacing the two lines in green with the line in blue.
function ApplyFilter(clip c, int "start", int "end", string "filter"){
start = default(start, 0)
end = default(end, 0)
c
end = end <= 0 ? FrameCount()-1 : end
# seg2 = Trim(start, end)
# seg2 = Eval("seg2." + filter)
seg2 = Eval("c." + filter).Trim(start, end)
re = start == 0 ? seg2 : start == 1 ? Trim(0, -1) ++ seg2 : Trim(0, start-1) ++ seg2
re = end < FrameCount-1 ? re ++ Trim(end + 1, 0) : re
return re
}
VoodooFX
27th February 2026, 17:32
I think he just doesn't want to type p1+p2+p3+...+pn when it includes hundreds of parts. On the other hand, he had to type hundreds of trims. :confused:
You don't need to type such sequences yourself anymore, ChatGPT can easily generate that. You need to type only the frame ranges.
Columbo
27th February 2026, 19:49
Ah good point, that's his answer then. He can ask Claude (I hate ChatGPT) to generate the entire script.
gispos
27th February 2026, 22:37
gispos,
I've never used ApplyFilter in AvsPmod, although I'll play around with it sometime soon, but for filters that might benefit from being able to request frames outside of the Trim range, would something like this work? Just replacing the two lines in green with the line in blue.
function ApplyFilter(clip c, int "start", int "end", string "filter"){
start = default(start, 0)
end = default(end, 0)
c
end = end <= 0 ? FrameCount()-1 : end
# seg2 = Trim(start, end)
# seg2 = Eval("seg2." + filter)
seg2 = Eval("c." + filter).Trim(start, end)
re = start == 0 ? seg2 : start == 1 ? Trim(0, -1) ++ seg2 : Trim(0, start-1) ++ seg2
re = end < FrameCount-1 ? re ++ Trim(end + 1, 0) : re
return re
}
Hmm, I hadn't thought about that; I almost exclusively use ApplyFilter and ClipClop for color and sharpening adjustments.
I'll gladly accept your suggestion for the change, though; it's simply written more elegantly. What still needs to be checked is whether there is a difference in speed.
I don't know if that makes a difference for a filter that wants to work with frames outside the trim area.
I rather think not, because 'seg2' is added to the other areas with a trim, and I think ClipClop behaves no differently, or does it?
But... isn't that a bit too strict a view? Normally, a different/additional filter is applied when a scene changes, and even if not during a scene change, what significant visible changes would there be in just one or two images?
And because it's so easy, I can live with the minor drawbacks.:)
StainlessS
27th February 2026, 23:55
and I think ClipClop behaves no differently, or does it?
You can apply some kind of temporal filtering to a 'replacement clip' and use only required frames from that clip,
so clipclop DOES behave no differently.
EDIT: Any temporally processed Replacement clip should handle its own scene change detection.
hello_hello
28th February 2026, 04:14
But... isn't that a bit too strict a view? Normally, a different/additional filter is applied when a scene changes, and even if not during a scene change, what significant visible changes would there be in just one or two images?
It probably doesn't make a difference most of the time, although someone asked about a problem with TFM combined with QTGMC in progressive mode recently, and apparently trimming after the filtering fixed it.
I suspect it might have been because TFM could look for matches outside of the Trim range, but I'm not sure.
https://forum.videohelp.com/threads/419639-TFM()-followed-by-QTGMC(InputType-1)
If you don't want to change the order, this should work if you want to reduce it to a single line. :)
seg2 = Trim(start, end).Eval(filter)
And even the line I suggested could be condensed a little.
seg2 = Eval(filter).Trim(start, end)
Arx1meD
28th February 2026, 06:31
Thanks everyone for helping.
StainlessS
28th February 2026, 12:30
@Arx1meD,
This (FrameSurgeon.avsi) a part of a combo utility, other part being Sawbones (AutoIt script used with Vdub2 and NotePad, maybe problems with sawbones and NotePad on W11).
/*
FrameSurgeon() v1.12, by StainlessS @ Doom9
Requires Either AVS+ or GScript[(c) Gavino], MvTools[(c) Manao], RT_Stats, FrameSel, ClipClop & Prune Plugins [(c) StainlessS].
Any v2.60 colorspace,
Interpolation commands in FrameSurgeon for Planar and YUY2 only (colorspaces supported by mvTools, may differ by mvtools version)
Replace/Delete noisy/damaged frames using commands in a either command string or file (one command per line in both file and string).
If both string (SCmd) and file (Cmd) commands supplied, then File Processed first and then String later (relevant as later
replacements take precedence where a frame replaced more than once). Any deletes take place AFTER ALL replacements have been done.
Interpolation Commands are available for Planar and YUY2 only due to MVTools usage (fails if 'Id' commands used in non supported
colorspaces).
Args-:
c, Source clip.
SCmd, Default "", Commands supplied as string.
Cmd, Default "", Commands supplied as FileName. (Either SCmd or Cmd MUST be supplied).
Show: Default False, Show Info on Frame.
ShowMode: Default 0, When Show==true, then 0=Show ClipClop metrics(post replacement), else if 1 Show Prune Metrics(post Delete).
Dv, Default 0, ClipClop and Prune DebugView level (0 - 4, Need DebugView utility)
FX1-FX9, Default c, Defaults to source clip, and if Show==True then Subtitled as eg "FX1" in frame center.
User Replacement clips. eg could use FX1 clip as Light Denoise, FX2 as Medium Denoise or whatever.
See Also Final and NoErr below.
Interpolation args:- MvTools args. Used for 'Id' commands (where d = digit 1 to 9).
pel Default 2, Default as for MSuper(), ie 2, range=1 or 2 or 4
sharp Default 2, Default as for MSuper(), ie 2, range=0 -> 2
rfilter Default 2, Default as for MSuper(), ie 2, range=0 -> 4
ml Default 100.0, Default as for MFlowInter(), ie 100.0, range=greater than 0.0.
NOTE, all exposed Interpolation args are the MvTools Defaults, there has been no attempt to tweak anything.
Final Default True, If False, then DOES NOT Delete any ranges, replace only. Delete Operations only occur if this arg is True.
Set False, when using SawBones together with NotePad and VirtualDub2 (with Script Editor Window Open).
When False, will not do deletions, will instead show frames marked with "DUMMY DELETE" in frame center.
Purpose, to avoid editing errors using SawBones "Save & Refresh" AVS, keyboard command. (Not a
good idea to edit clip where deletions have already been done, ie edits after first deletion, would all be wrong).
Change to FINAL=True, when all edits including deletions are complete, where real deletions will ensue.
If later adding some edits to a command file using SawBones, then set FINAL=False until editing complete.
NoErr Default False, If NoErr=False and Final=True and Show=False, and any FXd clip command exists for an unsupplied FXd clip,
in either SCmd or Cmd commands, then produces an error alert showing undefined clips for which commands are being used.
Set NoErr=True, to ignore the commands for undefined clips, where source clip will be used instead.
Purpose, when Final=False, can issue FXd command for ranges before actually implementing an FXd clip (you may not as
yet have decided how some bad range need be processed).
When Final=True, then is assumed that user has forgotten to implement an FXd clip, and so issues error alert. But,
this error alert can be overridden and FXd commands ignored when NoErr=True.
Supported commands In SCmd and Cmd.
(where n=frame number, s= range start frame, e=range end frame, d is a digit, '1' to '9', i is a count.
NOTE, e range End Frame behaves as in trim eg -20 means 20 frames starting at frame s, e=0 means to last frame):-
"CP n" CopyFromPrevious ie replace source clip c frame n with source clip c frame n - 1.
"CN n" CopyFromNext ie replace source clip c frame n with source clip c frame n + 1.
#
"I1 n" Interpolate 1 frame n (using source frames n-1 and n+1 as Interpolation source frames, (Id commands Planar, YUY2 only).
"I2 n" Interpolate 2 frames starting at frame n, (using source frames n-1 and n+2).
"I3 n" Interpolate 3 frames starting at frame n, (using source frames n-1 and n+3).
"I4 n" Interpolate 4 frames starting at frame n, (using source frames n-1 and n+4).
"I5 n" Interpolate 5 frames starting at frame n, (using source frames n-1 and n+5).
"I6 n" Interpolate 6 frames starting at frame n, (using source frames n-1 and n+6).
"I7 n" Interpolate 7 frames starting at frame n, (using source frames n-1 and n+7).
"I8 n" Interpolate 8 frames starting at frame n, (using source frames n-1 and n+8).
"I9 n" Interpolate 9 frames starting at frame n, (using source frames n-1 and n+9).
"I n" Interpolate 1 frame n (using source frames n-1 and n+1 as Interpolation source frames.
"I s,e" Interpolate range s to e (max range 9 frames, using source frames s-1 and e+1 as source frames).
"I s,-i" Interpolate frame count i, range s to s+i-1, (i max 9 frames, using source frames s-1 and s+i as source frames).
#
"FXd n" Replace frame n with same frame from FXd clip, eg "FX3 100" replace source frame 100 with same frame from FX3 clip.
"FXd s,e" Replace range s to e with same range from FXd clip.
"FXd s,0" Replace range s to end of clip with same range from FXd clip.
"FXd s,-i" Replace frame count i, range s to s+i-1, with same range from FXd clip.
(the hyphen '-' indicates that i is a count rather than the end frame of a range).
#
"DEL n" Delete frame n (Deletes are processed AFTER ALL Interpolations/replacements)
"DEL s,e" Delete frames s to e
"DEL s,0" Delete frames s to end of clip.
"DEL s,-i" Delete frame count i, range s to s+i-1.
"-n" Delete frame n
"-s,e" Delete frames s to e
"-s,0" Delete frames s to end of clip.
"-s,-i" Delete frame count i, range s to s+i-1.
NOTE, FrameSurgeon frame/range deletes have a 1ms linear FadeOut/FadeIn at splices simulating zero crossing, to prevent 'Cracks' in audio.
*/
FrameSurgeon() can be used on its own, but if using W10 can use with Sawbones/VDub2/Notepad(W10) to create FrameSurgeon EDIT commands using VDub2 as GUI.
SawBones(includes FrameSurgeon.avsi) D9 Thread :- https://forum.doom9.org/showthread.php?t=173158
Sawbones(Incl FrameSurgeon) On MediaFire:- https://www.mediafire.com/file/png0ujb7cb761pv/SawBones-v1.12_20220813.zip/file
EDIT: By the way, for anybody that does use AutoIt (BASIC-like scripting language used by SawBones), it was updated in Sept 2025, prior update was in Sept 2022.
AutoIt:- https://www.autoitscript.com/site/
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.