FrameSel

From Avisynth wiki
(Difference between revisions)
Jump to: navigation, search
m (added category (previous comment was a typo))
(FrameSel: add documentation)
 
Line 1: Line 1:
#REDIRECT [[External_filters#Frame_Replacement.2FRange_Processing]]
+
{{FilterCat5|External_filters|Plugins|Plugins_x64|Adjustment_filters|Range_Processing}}
 +
[[Category:Plugins]]
 +
{{Filter3
 +
|1={{Author/StainlessS}}
 +
|2=v2.20
 +
|3=[https://web.archive.org/web/20200526164026if_/https://files.videohelp.com/u/223002/FrameSel_x86_x64_dll_v2-20_20180420.zip FrameSel_x86_x64_dll_v2-20_20180420.zip]
 +
|4=Frame Replacement / Range Processing
 +
|5=[https://www.gnu.org/licenses/gpl-2.0.txt GPLv2]
 +
|6=[https://forum.doom9.org/showthread.php?t=167971 Doom9 Forum]
 +
}}
 +
<br>
 +
== Description ==
 +
FrameSel() is a simple plugin to select individual frames from a clip.
  
{{FilterCat|External_filters|Adjustment_filters|Range_Processing}}
+
Can select frames numbers by direct arguments to filter, or in a string, or in a command file.
 +
<br>
 +
<br>
 +
== Requirements ==
 +
* [x86]: [[AviSynth+]] or [https://sourceforge.net/projects/avisynth2/ AviSynth 2.6]
 +
* [x64]: [[AviSynth+]]
 +
* Supported color formats: [[RGB24]], [[RGB32]], [[YUY2]], [[Y8]], [[YV12]], [[YV16]], [[YV24]], [[YV411]]
 +
<br>
 +
* [https://www.microsoft.com/en-us/download/details.aspx?id=26368 Microsoft Visual C++ 2008 Redistributable Package (x86 / x64)]
 +
:<span style="color:red">***</span> <tt>vcredist_x86.exe</tt> is required for <tt>FrameSel-x86</tt>
 +
:<span style="color:red">***</span> <tt>vcredist_x64.exe</tt> is required for <tt>FrameSel-x64</tt>
 +
<br>
 +
 
 +
== [[Script variables|Syntax and Parameters]] ==
 +
<pre>
 +
FrameSel(Clip, int F1, ... , int Fn, string 'scmd',string 'cmd', bool 'show', bool 'ver',bool "reject",bool "ordered",
 +
            \ bool "debug", int "Extract"=1)
 +
 
 +
Compulsory args:
 +
 
 +
        Clip,  No Default, source clip.
 +
 
 +
 
 +
Optional args:  (at least one of the frame select options must be supplied).
 +
 
 +
    F1...Fn Un-named. Zero or more frame numbers.
 +
 
 +
        SCmd,  string, Default= "", Not set.
 +
                Command String, frame numbers supplied in a string.
 +
 
 +
        Cmd,    string, Default= "", Not set.
 +
                Command file, frame numbers supplied in a file. Use eg "Select.txt" for command file in your script directory.
 +
 
 +
        Show    bool, Default= false.
 +
                true = Show info. (Requires v2.6 dll if a v2.6 colorspace, except Y8 OK in 2.5 dll).
 +
 
 +
        Ver    bool, Default=false.
 +
                true = Show version. (Requires v2.6 dll if a v2.6 colorspace, except Y8 OK in 2.5 dll).
 +
 
 +
        Reject  bool, Default False. If true then selects frames NOT specified rather than specified frames.
 +
                eg if you have a 5 frame clip (0->4) and have commands to select 4,2 and 0, then reject=true would actually
 +
                select frames 1 and 3 instead.
 +
                If reject=true, then orderering occurs no matter whether Ordered is set true or false and the frames are returned
 +
                in sequential order.
 +
                Reject might be of use to view all frames NOT in a frames command set.
 +
 
 +
        Ordered bool, Default true. No effect if reject is true, where Ordered will ALWAYS be as if set true.
 +
                If true then all selected frames are sequentially ordered and only unique frames are selected
 +
                and returned in sequential order. If Ordered is set false, no frame number ordering is done and eg if
 +
                frames 10,20,30,20,10 were selected in commands, then it would select 5 frames; 10 and 20 and 30 and 20 and 10,
 +
                are returned and in that order. If Ordered is set default true, then for same example it would return 10 and 20
 +
                and 30, in that sequential order.
 +
                So, the purpose of Ordered=true (default), is to remove duplicates and return sequential frames.
 +
                Only change Ordered to false if you are convinced you know what you are doing.
 +
 
 +
        Debug  bool, Default false. If true sends a little debug info to debugview window during Plugin initialization. (Google DebugView).
 +
 
 +
        Extract Int, Default 1, MUST be ODD, 1 to 11. Error if not default 1 AND neither Ordered nor Reject == True.
 +
                Let us call the UNIQUE resultant frames after Ordered and/or Reject Processing 'Target' frames.
 +
                The number of frames pulled out on either side of Target frame is Extract / 2 (integer divide), so when Extract=3, it will
 +
                extract 1 frame before target, the Target frame, and 1 frame after target, for each and every Target frame.
 +
                This arg allows you to select eg 3 frames for each Target frame, the previous frame, Target frame and next frame.
 +
                May be of use to extract bad frames together with eg 1 frame either side for saving as bitmaps and editing
 +
                in some kind of RotoScope editor to repair bad frames using image from adjacent frames. The edited frames could
 +
                then be re-loaded, middle one selected via SelectEvery(3,1), and then put back into original source clip via FrameRep().
 +
                Another simple use could be when you have a clip where each frame before a scene change is bad, with Ordered=True
 +
                and Extract=3, you pull out 3 frames, a SelectEvery(3,0) would select the frames previous to the bad frames and
 +
                then use Framerep() to replace the bad frames with those previous to them. A SelectEvery(3,2) would select the frames
 +
                after Target frames.
 +
                The total number of frames pulled out of the source clip will be (Extract * number of Target frames).
 +
                Reject is less likely to be of use with Extract, unless frame select commands specify good frames rather than bad,
 +
                where Reject in FrameRep should also be true (same as in FrameSel, as always).
 +
                See FrameRep() for example uses of Extract.
 +
 
 +
 
 +
Either the direct frame numbers, Command string (SCmd), or command file (Cmd) must be supplied.
 +
*** NOTE ***,  if more than one supplied, the commands in the Command File are processed
 +
first followed by those in the SCmd String, and finally the directly supplied frame numbers, relevant when Ordered=false
 +
 
 +
 
 +
NOTE, You can use frame ranges for both command file & command string (not possible for directly supplied frame number args).
 +
 
 +
 
 +
The 'Cmd' Command file allows one command per line and can contain comments eg:
 +
 
 +
#------------- # below contents of a text file.
 +
100      # This is a comment
 +
200      # and so is this
 +
300,400  # This is a frame range, specifies all 101 frames between 300 and 400 inclusive [As Trim(300,400)].
 +
500,-2    # Specifies 2 frames starting at frame 500, ie 500 and 501 [As Trim(500,-2)].
 +
600,0    # Specifies ALL frames from frame 600 to the end of the source clip [As Trim(600,0)].
 +
#-------------
 +
So in a command file, a single number specifies a frame, and a comma(,) separator indicates a frame range.
 +
SPACE's are also now accepted as range separators, and can be used instead of commas as in above example.
 +
 
 +
The "SCmd" string accepts more than 1 command per line, but MUST be separated by a semi colon (;).
 +
The Semi colon is processed as a sort of soft newline and will terminate a comment, so you CANNOT
 +
have a semi colon in a comment. eg
 +
 
 +
SCMD = "
 +
      1000  # This is a comment ; 2000 # the 2nd arg is 2000; 3000 # the third arg on a single line.
 +
      4000 ; 5000 ; 6000
 +
      7000,8000 ; 9000,-2 ; 10000,0  # Frames 7000-8000, 2 frames starting at 9000, and frame 10000 to end of clip.
 +
"
 +
So in a command string, a comma(,) specifies a frame range, and a semi colon(;) a new command.
 +
SPACE's are also now accepted as range separators, and can be used instead of commas as in above example.
 +
 
 +
 
 +
example commands:
 +
 
 +
FrameSel(clip, 1,2,3,4,5)                              as Trim(1,1) + Trim(2,2) + Trim(3,3) + Trim(4,4) + Trim(5,5)
 +
FrameSel(clip,"100,110;200,-2;300,0")                  as Trim(100,110) + Trim(200,-2) + Trim(300,0)
 +
FrameSel(clip, 1,2,3,4,5,"100;200;300","Select.txt")
 +
FrameSel(clip, 1,2,3,4,5,"100;200;300")
 +
FrameSel(clip, 1,2,3,4,5,"","Select.txt")
 +
FrameSel(clip,"100;200;300","Select.txt")
 +
FrameSel(clip,"","Select.txt")
 +
 
 +
--------------------------------------
 +
--------------------------------------
 +
--------------------------------------
 +
 
 +
FrameRep(Clip c,Clip c2 int F1, ... , int Fn, string 'scmd',string 'cmd', bool 'show', bool 'ver',bool "reject",bool "debug")
 +
 
 +
Video:- Planar, YUY2, RGB32, RGB24.
 +
 
 +
Audio:- Returns source clip c audio.
 +
 
 +
Args identical to FrameSel, with exception of the compulsory 2nd clip arg which is a clip of frames to replace into the 1st source clip,
 +
and also does not have an Ordered argument, as it is ALWAYS Ordered, and FrameRep, does not have the Extract arg.
 +
 
 +
See FrameSel() description for other arguments.
 +
 
 +
FrameRep() is complimentary to FrameSel, whereas FrameSel extracts frames, FrameRep replaces or reseats them (from the c2 clip) back from
 +
whence they came (into the c clip) and using the EXACT same arguments and commands (whether directly supplied or in string command or
 +
file command). If you wish to extract some frames and later replace back into the source clip, you MUST use the default Ordered=True in
 +
FrameSel or the frames may not be replaced back into the positions they originally came from.
 +
 
 +
The number of Unique Selected frames in the combined frames commands MUST EQUAL the number of frames in the c2 clip (after taking Reject
 +
into account), or it WILL throw an error, (will not know where to put the remainder or frame shortage). This is the reason you should
 +
use the same frame commands in both FrameSel and FrameRep so that there will be an identical number of unique frames and Ordered
 +
sequential. If Debug is set true, it will show a little info in DebugView (Google), eg number of unique frames in a command set.
 +
 
 +
# ----------------
 +
 
 +
Here, Example to do some simple editing on selected frames, try changing REJECT to True.
 +
 
 +
Colorbars.Trim(0,-10).ShowFrameNumber()                            # 10 frames
 +
sCmd="2;5;6"                                                      # Frames in SCmd string
 +
REJECT=False                                                      # False=modify SCmd frames : True=modify frames NOT in SCmd
 +
SELECTED=FrameSel(scmd=sCMD,ordered=TRUE,reject=REJECT,debug=true) # We are going to use FrameRep, must use ORDERED=True (OR REJECT=True)
 +
SELECTED=Invert(SELECTED)                                          # Do some editing
 +
FrameRep(Last,SELECTED,scmd=sCMD,reject=REJECT,debug=true)        # Put edited frames back into original Last clip (audio from Last)
 +
return Last
 +
 
 +
# ----------------
 +
 
 +
Example use when NOT selecting/replacing in exact same position:
 +
  Lets say you have a clip with a bad frame before each scene change and you want to replace these bad frames with the frame immediately
 +
before it.
 +
 
 +
    C=Colorbars().Trim(0,-50).ShowFrameNumber()                    # 50 frames (0 -> 49)
 +
    BADFRAMES = "10;20;30;40"                                      # 4 bad frames in source clip
 +
    PREBAD    = " 9;19;29;39"                                      # 4 frames immediately before bad frames
 +
    REPAIR=FrameSel(C,scmd=PREBAD)                                # Get the 4 frames we will duplicate
 +
    Return FrameRep(C,REPAIR,scmd=BADFRAMES)                      # fix bad frames with REPAIR clip from PREBAD frames
 +
 
 +
Will produce a duplicate at frames 10, 20, 30, and 40 in source clip.
 +
 
 +
When used as above you must ensure that eg BADFRAMES and PREBAD have the same number of unique frames and sequential or results
 +
may not be as expected (ie use Ordered).
 +
 
 +
# ----------------
 +
 
 +
Same Example again using Extract arg:-
 +
 
 +
    C=Colorbars().Trim(0,-50).ShowFrameNumber()                    # 50 frames (0 -> 49)
 +
    BADFRAMES = "10;20;30;40"                                      # 4 bad frames in source clip
 +
    EXTRACT=FrameSel(C,scmd=BADFRAMES,ordered=True,extract=3)      # Extract Previous, Target and Next frames for each Target frame
 +
    REPAIR=EXTRACT.SelectEvery(3,0)                                # Select each frame previous to Target bad frames, 1st of each triplet
 +
    #REPAIR=REPAIR.Invert()                                        # So we can easily see repaired frames
 +
    Return FrameRep(C,REPAIR,scmd=BADFRAMES)                        # Fix bad frames with REPAIR clip using exact same BADFRAMES spec.
 +
 
 +
# ----------------
 +
 
 +
Example scripts to show use with a paint program for manual frame repair.
 +
 
 +
    # Extract Script
 +
    C=Colorbars().Trim(0,-50).ShowFrameNumber.ConvertToRGB24        # 50 frames (0 -> 49), RGB24
 +
    BADFRAMES = "10;20;30;40"                                      # 4 bad frames in source clip
 +
    EDITCLIP=FrameSel(C,scmd=BADFRAMES,ordered=True)                # Extract BAD frames
 +
    EDITCLIP.ImageWriter(file="Pic%06d.bmp",type="bmp",info=true)  # Write bitmaps to edit
 +
    return Last
 +
    # Need to play all way through for ImageWriter to work properly.
 +
 
 +
    # Here, EDIT bad frames in paint program
 +
 
 +
    # Replace Script, after editing
 +
    C=Colorbars().Trim(0,-50).ShowFrameNumber.ConvertToRGB24        # 50 frames (0 -> 49), RGB24
 +
    BADFRAMES = "10;20;30;40"                                      # 4 bad frames in source clip
 +
    END = 3                                                        # unique_bad_frames - 1 (number of frames in BADFRAMES-1)
 +
    REPAIRED=ImageReader(file="Pic%06d.bmp",end=END)
 +
    #REPAIRED=REPAIRED.Invert()                                    # Hilite repaired frames, easier to see
 +
    Return FrameRep(C,REPAIRED,scmd=BADFRAMES,show=true)            # Fix bad frames with REPAIRED clip using exact same BADFRAMES spec.
 +
    # NOTE, you need to tell ImageReader the last frame number to read,
 +
    # the default for End is 1000, so imagereader will read in 4 frames (0 to 3) and 997 duplicates,
 +
    # FrameRep would throw an error as it does not know what to do with the unwanted 997 duplicate frames that were 'helpfully' appended.
 +
    # The 1st script, ImageWriter(Info=True) arg, shows the FrameNumber and name for each frame, and the number shown on the last frame
 +
    # can be assigned to END in 2nd script, shows eg "Frame 3 written to: D:\Pic000003.bmp".
 +
    # The Last frame number shown by Info=True, will be correct even if BADFRAMES list (in eg string or command file) has duplicates
 +
    # as they will be sorted and only unique frames delivered by FrameSel when Ordered=True is used, eg
 +
    #  BADFRAMES="40;30;20;10;20;30;40", if used in 1st script FrameSel will select exactly the same frames as BADFRAMES="10;20;30;40",
 +
    # ie 4 frames and in sequential order (Ordered=True).
 +
# ----------------
 +
 
 +
Example scripts to show use with a paint/rotoscope program that can read in bad frames together with previous and next frames,
 +
  and manually fix frames using image data from previous or next frames to repair damage.
 +
    # Extract Script
 +
    C=Colorbars().Trim(0,-50).ShowFrameNumber.ConvertToRGB24        # 50 frames (0 -> 49), RGB24
 +
    BADFRAMES = "10;20;30;40"                                      # 4 bad frames in source clip
 +
    EDITCLIP=FrameSel(C,scmd=BADFRAMES,ordered=True,extract=3)      # Extract Previous, Target and Next frames for each BAD frame
 +
    EDITCLIP.ImageWriter(file="Pic%06d.bmp",type="bmp",info=true)  # Write bitmaps to edit
 +
    return Last
 +
 
 +
    # Here, EDIT in Triple frame paint/rotoscope editing program
 +
 
 +
    # Replace Script, after editing triplets
 +
    C=Colorbars().Trim(0,-50).ShowFrameNumber.ConvertToRGB24        # 50 frames (0 -> 49), RGB24
 +
    END = 11                                                        # unique_bad_frames * Extract - 1
 +
    BADFRAMES = "10;20;30;40"                                      # 4 bad frames in source clip
 +
    EDITCLIP=ImageReader(file="Pic%06d.bmp",end=END)
 +
    REPAIRED=EDITCLIP.SelectEvery(3,1)                              # Select repaired BAD frames, 2nd of each triplet
 +
    #REPAIRED=REPAIRED.Invert()                                    # Hilite repaired frames, easier to see
 +
    Return FrameRep(C,REPAIRED,scmd=BADFRAMES,show=true)            # Fix bad frames with REPAIRED clip using exact same BADFRAMES spec.
 +
 
 +
--------------------------------------
 +
--------------------------------------
 +
--------------------------------------
 +
 
 +
FrameSel_CmdReWrite(Clip c,String ofn, int F1, ... , int FN, String "SCmd"="", String "Cmd"="", \
 +
      Bool "Reject"=False, Bool "Ordered"=True, Bool "Debug"=False, Bool "Range"=True, Bool "Space"=False, Bool "Prune"=False)
 +
 
 +
Args identical to FrameSel (up to Debug), with exception of the additional compulsory 2nd String arg which is
 +
an output filename, and missing Ver and Show and Extract args.
 +
See FrameSel() description for other arguments.
 +
 
 +
      ofn,      String, Compulsory.
 +
                Output file name. It is advised to use a different name to the Cmd file, although there is nothing to stop you
 +
                overwriting an original Cmd file if you like a little gamble.(Output file only written after fully read in and
 +
                all Ordering, Rejecting etc already processed. Only likely error would be during file writing eg eject floppy disk).
 +
 
 +
      Range,    bool, Default=True
 +
                False = Write individual frame numbers only, to output file.
 +
                True  = (Default) Write comma separated Frame Ranges to output file (only where adjacent frames).
 +
 
 +
      Space,    bool, Default=False
 +
                False = (Default) Write comma separators in output file for ranges.
 +
                True  = Write SPACE separators in output file  instead of comma for ranges.
 +
 
 +
      Prune,    bool, Default=False
 +
                False = (Default) Write FrameSel style frames or ranges to output file.
 +
                True  = Write Prune style frames or ranges to output file (with a clip index first eg '0,10,20' instead of '10,20').
 +
                Prune supports up to 256 input clips that is the reason it needs a clip index.
 +
                Prune Supports Audio (whereas FrameSel does not) and also allows you to audio fadein/out at splices.
 +
                This function can only output Prune command files, it cannot read Prune command files.
 +
 
 +
FrameSel_CmdReWrite, takes either Frame numbers as direct arguments, or in the SCmd string, or in the Cmd file (at least one must
 +
be specified). If more than one command method is used, will process Cmd file first, then SCmd string second and lastly
 +
directly supplied frame numbers. The command frames will be acted upon via the Reject, and Ordered, args (as in FrameSel)
 +
and then re-written to the output command file. Any comments in SCmd string or Cmd file will not be written to the output
 +
command file.
 +
 
 +
The FrameSel_CmdReWrite() function returns the total number of frames written to the output file (including ranges).
 +
 
 +
This function could have several uses:-
 +
  To combine multiple frame specifying command methods into a single command file, and if Ordered, then remove duplicates.
 +
  Convert single frame command files to frame range command files, (smaller and perhaps easier to peruse).
 +
  Convert frame range command files to single frame command files, for use in another plugin that expects only frame numbers.
 +
  Convert a Reject=True command set to Reject=False command file, and vice versa.
 +
  Convert a command file of single frames/ranges to reject from a clip, into a Prune command file (Prune does not itself have a
 +
    Reject arg but it does fadein/out audio at splices and can also coalesce single frames into ranges before splicing so that
 +
    it does not fadein/out at every single individually specified frame).
 +
  Perhaps more uses.
 +
 
 +
  *** NOTE ***, if you would normally use Reject=True in FrameSel, and you do a conversion with Reject=True, then the resultant
 +
  command file should be used with Reject=False in FrameSel.
 +
 
 +
--------------------------------------
 +
Example:
 +
    avisource("d:\avs\flashtest.avi").trim(1000,-10).showframenumber
 +
 
 +
    # Delete list of frames, No Audio returned
 +
 
 +
    # Uncomment one of the below three lines
 +
 
 +
    #FrameSel(3,5,7,reject=true)            # delete frames using direct arg frame numbers, return no audio (ranges not supported in direct arg framenos)
 +
 
 +
    #FrameSel(SCmd="3;5;7",reject=true)    # delete frames using scmd string of frame numbers, return no audio (';' or Chr(10)=separator, ','=range)
 +
 
 +
                                            # del.txt = file containing eg "3"+chr(10)+"5"+chr(10)+"7"+chr(10)
 +
    #FrameSel(Cmd="del.txt",reject=true)    # delete frames using cmd file of newline separated frame numbers, return no audio
 +
---
 +
Example: (Uses Prune and RT_Stats, these two examples also included in AVS directory):-
 +
 
 +
    Function SelectRanges(clip c,String "SCmd",String "Cmd",Bool "TrimAudio",Float "FadeMS",Bool "Ordered") {
 +
        # SelectRanges() by StainlessS. Required:- FrameSel, Prune, RT_Stats
 +
        # Wrapper to Select frames/ranges along with audio, can supply frames/ranges in SCmd string And/Or Cmd file.
 +
        #  The wrapper makes for easier usage of Prune() which supports up to 256 input clips, but requires a clip index,
 +
        #  eg '3, 100,200' would specify clip 3, range 100 to 200. The wrapper does away with the necessity for the clip index as we
 +
        #  are only using a single clip here.
 +
        #
 +
        # SCmd: Frames/Ranges specified in String (Frames/Ranges either Chr(10) or ';' separated, infix ',' specifies range, eg 'start,end').
 +
        # Cmd:  Frames/Ranges specified in file (one frame/range per line, comments allowed, see FrameSel for Further info).
 +
        #  *** NOTE ***, If both Cmd and SCmd supplied AND Ordered == False, then will process Cmd file and then SCmd string afterwards, ie
 +
        #    Will select ranges in Cmd file and in order specified (rather than auto ordering ranges) and then append ranges specified in
 +
        #    SCmd string (and in order specified).
 +
        # TrimAudio:
 +
        #  True(default), selects audio belonging to selected frames/ranges
 +
        #  False, returns original audio, probably out of sync (maybe totally out of whack if Ordered == false and selected ranges out of order).
 +
        # FadeMS: (default 1.0 millisec). Linear Audio Fade duration at splices when TrimAudio==true, 0 = dont fade (might result in audio 'clicks/cracks').
 +
        # Ordered:
 +
        #  True(default), all frames/ranges are returned in sequencial order. Any frame specified more than once will return only 1 instance.
 +
        #  False, All frames/Ranges are returned in specified order, Cmd processed first and then SCmd. Frames/ranges specified more than once
 +
        #    will return multiple instances. Allows out-of-order trimming of clip, eg re-sequencing of scenes in movie.
 +
        #
 +
        # Does not make much sense to select individual frames with audio, best used with ranges.
 +
        # Will coalesce individually selected adjacent frames/ranges before any Fade, ie only audio fade where sensible to do so.
 +
        # TrimAudio==false with non Ordered selection will result in completely out of sync audio.
 +
        c
 +
        TrimAudio=Default(TrimAudio,True)  # default true trims audio, false returns original audio (audiodubbed, as Framesel returns no audio)
 +
        FadeMS=Float(Default(FadeMS,1.0))  # 1 millisecond linear fadeout/fadein at splices
 +
        Ordered=Default(Ordered,True)      # True (default) frames/ranges will be Ordered and selected only once even if specified more than once.
 +
                                            # False, frames/ranges returned in specified order, Cmd processed 1st and then SCmd.
 +
        PruneCmd = (TrimAudio) ? "~Prune_"+RT_LocalTimeString+".txt" : ""
 +
        (!TrimAudio)
 +
            \ ? FrameSel(scmd=SCmd,cmd=Cmd,Ordered=Ordered)
 +
            \ : FrameSel_CmdReWrite(PruneCmd,scmd=SCmd,cmd=Cmd,Ordered=Ordered,Prune=True,range=true)
 +
        (TrimAudio) ? Prune(Cmd=PruneCmd,FadeIn=True,FadeSplice=True,FadeOut=True,Fade=FadeMS) : NOP
 +
        # If TrimAudio==true then delete Prune temp file, Else restore original Audio to the now audio-less clip
 +
        (TrimAudio)
 +
            \ ? RT_FileDelete(PruneCmd)
 +
            \ : (c.HasAudio) ? AudioDub(c) : NOP
 +
        Return Last
 +
    }
 +
 
 +
    avisource("d:\avs\flashtest.avi").trim(1000,-20).showframenumber # 20 frames
 +
 
 +
    SCMD="""    # This is a comment
 +
        1,3    # Select Range 1 to 3
 +
        9,11    # Select Range 9 to 11
 +
        14,15  # Select Range 14 to 15
 +
        2,5    # Select Range 2 to 5, If Ordered==True then already previously selected 1st range above (1,3) extended to 1,5
 +
    """
 +
 
 +
    ORDERED=True
 +
    SelectRanges(scmd=SCMD,Ordered=ORDERED)                    # Select SCmd ranges, trim audio 1 ms fade.
 +
    #SelectRanges(scmd="1,3;9,11;14,15;2,5",Ordered=ORDERED)    # Exactly the same as above
 +
 
 +
--------------------------------------
 +
Example:
 +
 
 +
    Function RejectRanges(clip c,String "SCmd",String "Cmd",Bool "TrimAudio",Float "FadeMS") {
 +
        # RejectRanges() by StainlessS. Required:- FrameSel, Prune, RT_Stats
 +
        # Wrapper to delete frames/ranges along with audio, can supply frames/ranges in SCmd string And/Or Cmd file.
 +
        #  The wrapper makes for easier usage of Prune() which supports up to 256 input clips, but requires a clip index,
 +
        #  eg '3, 100,200' would specify clip 3, range 100 to 200. The wrapper does away with the necessity for the clip index as we
 +
        #  are only using a single clip here. Prune also does not have a 'reject' arg to delete specified frames rather than select them,
 +
        #  this wrapper also converts a list of frames to delete into a list of frames to select so that we can use Prune and its audio
 +
        #  capability.
 +
        #
 +
        # SCmd: Frames/Ranges specified in String (Frames/Ranges either Chr(10) or ';' separated, infix ',' specifies range, eg 'start,end').
 +
        # Cmd:  Frames/Ranges specified in file (one frame/range per line, comments also allowed, see FrameSel for Further info).
 +
        # TrimAudio:
 +
        #  True(default), deletes audio belonging to deleted frames
 +
        #  False, returns original audio, probably out of sync.
 +
        # FadeMS: (default 1.0 millisec). Linear Audio Fade duration at splices when TrimAudio==true, 0 = dont fade (might result in audio 'clicks/cracks').
 +
        c
 +
        TrimAudio=Default(TrimAudio,True)  # default true trims audio, false returns original audio (audiodubbed, as Framesel returns no audio)
 +
        FadeMS=Float(Default(FadeMS,1.0))  # 1 millisecond linear fadeout/fadein at splices
 +
        PruneCmd = (TrimAudio) ? "~Prune_"+RT_LocalTimeString+".txt" : ""
 +
        (!TrimAudio)
 +
            \ ? FrameSel(scmd=SCmd,cmd=Cmd,reject=true)
 +
            \ : FrameSel_CmdReWrite(PruneCmd,scmd=SCmd,cmd=Cmd,reject=true,Prune=True,range=true)
 +
        (TrimAudio) ? Prune(Cmd=PruneCmd,FadeIn=True,FadeSplice=True,FadeOut=True,Fade=FadeMS) : NOP
 +
        # If TrimAudio==true then delete Prune temp file, Else restore original Audio to the now audio-less clip
 +
        (TrimAudio)
 +
            \ ? RT_FileDelete(PruneCmd)
 +
            \ : (c.HasAudio) ? AudioDub(c) : NOP
 +
        Return Last
 +
    }
 +
 
 +
    avisource("d:\avs\flashtest.avi").trim(1000,-20).showframenumber # 20 frames
 +
 
 +
    SCMD="""    # This is a comment
 +
        1      # delete frame 1
 +
        9      # delete frame 9
 +
        11,15  # delete range 11 to 15
 +
    """
 +
 
 +
    # del.txt = file containing eg "3"+chr(10)+"5"+chr(10)+"7"+chr(10)
 +
    RejectRanges(scmd=SCMD,cmd="del.txt")          # Delete frames 1 & 9, 11 to 15, and frames in del.txt 3 and 5 and 7, trim audio 1 ms fade
 +
    #RejectRanges(scmd="1;9;11,15",cmd="del.txt")  # Exactly the same as above
 +
 
 +
 
 +
--------------------------------------
 +
--------------------------------------
 +
--------------------------------------
 +
 
 +
FrameSel_MakeReDupCmd(Clip c,String ofn, int F1, ... , int FN, String "SCmd"="", String "Cmd"="", \
 +
      Bool "Reject"=False, Bool "Debug"=False, Bool "Range"=True, Bool "Comments"=False)
 +
 
 +
    FrameSel_MakeReDupCmd(), a function to take a duplicates frames command file and convert it to a FrameSel command file to
 +
    replace duplicates in source clip with duplicates that are identical to the predecessor frame of the first duplicate.
 +
    You could eg pull out non duplicates using FrameSel (with Reject=True), and do some kind of processing on those frames,
 +
    and then re-create duplicates but with identical duplicates using the processed clip as source for the newly inserted
 +
    identical duplicates. Motion Compensated processing would likely work better with duplicates removed first.
 +
    Identical Duplicates may be of some use in creating VFR (Variable Frame Rate) encodes, or in better compression where
 +
    many duplicates present.
 +
        The Reject arg provides you with the option of using a non dupe frames list rather that a dupe frames list and achieve
 +
    identical results, see later example.
 +
 
 +
    Args identical to FrameSel (up to Reject), with exception of the additional compulsory 2nd String arg which is
 +
    an output filename, and missing Ordered (is always ordered), Ver and Show and Extract args.
 +
    See FrameSel() description for other arguments.
 +
 
 +
      ofn,      String, Compulsory.
 +
                Output file name. It is advised to use a different name to the Cmd file, although there is nothing to stop you
 +
                overwriting an original Cmd file if you like a little gamble.(Output file only written after fully read in and
 +
                all Ordering, Rejecting etc already processed. Only likely error would be during file writing eg eject floppy disk).
 +
 
 +
      Range,    bool, Default=True
 +
                False = Write individual frame numbers only, to output file.
 +
                True  = (Default) Write comma separated Frame Ranges to output file (only where adjacent frames).
 +
 
 +
      Comments, Bool, default False.
 +
                If true, then write additional descriptive comments to output file, else no comments written.
 +
 
 +
    FrameSel_MakeReDupCmd, takes either Frame numbers as direct arguments, or in the SCmd string, or in the Cmd file (at least one must
 +
    be specified). If more than one command method is used, will process Cmd file first, then SCmd string second and lastly
 +
    directly supplied frame numbers. The command frames will be acted upon via the Reject arg (as in FrameSel, and here Ordered is ALWAYS
 +
    implied) and then re-written to the output command file. Any comments in SCmd string or Cmd file will not be written to the output
 +
    command file, where arg Comments=True, comments are auto generated to help decipher the output.
 +
 
 +
    The FrameSel_MakeReDupCmd() function returns the total number of duplicate frames written to the output file.
 +
 
 +
    Example:
 +
        # Script to test identical results if commands specified as either duplicates or non duplicates.
 +
        # Duplicates are synthesized as Blank Frames and will be replaced with duplicate of frame prior to first blank/dupe.
 +
        # Req ClipClop, RT_Stats, FrameSel plugins.
 +
        #######
 +
        CB=ColorBars.KillAudio.Trim(0,-20).ShowFrameNumber  # 20 frames
 +
        BK=Last.BlankClip
 +
        #
 +
        CCDupeFrames=""" # ClipClop Duplicate Frame Numbers for creating test clip
 +
            1 3,5
 +
            1 9,11
 +
            1 15,17
 +
        """
 +
        FSDupeFrames=""" # FrameSel Duplicate Frame Numbers (MUST NOT INLCUDE 0)
 +
            3,5
 +
            9,11
 +
            15,17
 +
        """
 +
        #
 +
        CCNonDupeFrames=""" # ClipClop Non Duplicates  Frame Numbers for creating test clip
 +
            1 0,2
 +
            1 6,8
 +
            1 12,14
 +
            1 18,19
 +
        """
 +
        FSNonDupeFrames=""" #  FrameSel Non Duplicates (MUST INCLUDE FRAME 0)
 +
            0,2
 +
            6,8
 +
            12,14
 +
            18,19
 +
        """
 +
        ####### CONFIG #####
 +
        AreDupes=True        # If True then SCmd=list of duplicates, else list of non duplicates (SHOULD GET SAME RESULT)
 +
        ####################
 +
        CCSCmd = (AreDupes) ? CCDupeFrames : CCNonDupeFrames
 +
        SCmd  = (AreDupes) ? FSDupeFrames : FSNonDupeFrames
 +
        ORG    = (AreDupes) ? ClipClop(CB,BK,scmd=CCSCmd) : ClipClop(BK,CB,scmd=CCSCmd)
 +
        #Return ORG
 +
        #######
 +
        ReDupFrames = "ReDupFrames.txt"      # FrameSel command to re-assemble clip after processing. (created by FrameSel_MakeReDupCmd).
 +
        ReDupFrames = RT_GetFullPathName(ReDupFrames)
 +
        # Select Non Dupes Only for processing (Ordered always implied if Reject)
 +
        PreProc    = Org.FrameSel(SCmd=SCmd,Reject=AreDupes,Ordered=True) # MUST be Ordered, Ordered=True, for when Reject=False
 +
        Processed  = PreProc.McDegrainSharp(Frames=3)    # Whatever Processing of non dupes
 +
        # Make Cmd file to recreate dups from processed predecessor (Reject=False if SCmd file specifies duplicates. else true if is non dupes)
 +
        FrameSel_MakeReDupCmd(ORG,ReDupFrames,Scmd=SCmd,Reject=!AreDupes,Debug=True,Range=True,Comments=True)
 +
        ReDupped=Processed.FrameSel(Cmd=ReDupFrames,Ordered=False)      # Recreate Dups. (duplicates so cannot be Ordered)
 +
        #######
 +
        #return ReDupped
 +
        StackVertical(ORG,ReDupped)
 +
        #AudioDubEx(Last,ORG)    # Restore audio
 +
        Return Last
 +
 
 +
        Result for above script in ReDupFrames.txt command file.
 +
        Numbers in comments are output frame numbers, those prefixed by a 'D' are duplicates.
 +
        Below shows why you need in line ReDupped=Processed.FrameSel(Cmd=ReDupFrames,Ordered=False), Ordered=False, as we have
 +
        at beginning of file frames 0,2 ;2;2;2, so must not be ordered.
 +
        >>>>>>>>>>>>
 +
            0    ,2      #  0,2 [Len=3]
 +
            2            # D 3    # These are duplicates
 +
            2            # D 4
 +
            2            # D 5
 +
            3    ,5      #  6,8 [Len=3]
 +
            5            # D 9
 +
            5            # D 10
 +
            5            # D 11
 +
            6    ,8      #  12,14 [Len=3]
 +
            8            # D 15
 +
            8            # D 16
 +
            8            # D 17
 +
            9    ,10    #  18,19 [Len=2]
 +
        <<<<<<<<<<<<<
 +
--------------------------------------
 +
</pre>
 +
<br>
 +
 
 +
== Examples ==
 +
[[TODO]]
 +
<br>
 +
<br>
 +
== Changelog ==
 +
<pre>
 +
v1.00 - 23 Mar 2012 : 1st release.
 +
v1.01 - 24 Dec 2012 : Added frame ranges to CMD and SCMD.
 +
v1.02 - 27 Apr 2013 : Added FrameRep
 +
v1.03 - 14 May 2013 : Added FrameSel Reject mode.
 +
 
 +
Renamed to FrameSel/FrameRep, reversioned to v2.0
 +
 
 +
v2.00 - 30 May 2013 : Implemented ordered, and SPACE separator in command file.
 +
v2.10 - 23 Feb 2014 :
 +
Fixed All Frames Rejected bug (zero length return clip), best throw an error.
 +
Implemented Unique_Sort(), much faster in unlikely event that frames are in random order (when Ordered or Reject) .
 +
Added function FrameSel_CmdReWrite();
 +
v2.11 - 27 Feb 2014 :
 +
Fixed, v2.5 dll only worked with YV12 or Y8, (FrameRep when Show or Ver, throw error) oops.
 +
Added Extract arg to FrameSel().
 +
v2.12 - 02 Mar 2014 :
 +
Increased FrameSel maximum Extract to 11. Added FrameSel Extract offset indicator when show = true.
 +
v2.13 - 30 Mar 2015. Recompile v2.6 dll with Avisynth Version 6 Header.
 +
v2.20 - 20 Apr 2018. Add FrameSel_MakeReDupCmd, and x64. Recompile VS2008.
 +
</pre>
 +
<br>
 +
 
 +
== Archived Downloads ==
 +
{| class="wikitable" border="1"; width="500px"
 +
|-
 +
!!width="100px"| Version
 +
!!width="200px"| Download
 +
!!width="200px"| Mirror
 +
|-
 +
!v2.20
 +
|[https://web.archive.org/web/20200526164026if_/https://files.videohelp.com/u/223002/FrameSel_x86_x64_dll_v2-20_20180420.zip FrameSel_x86_x64_dll_v2-20_20180420.zip]
 +
|[http://download1509.mediafire.com/2xd5ly6g5nxg/41rgfbuddalv9bb/FrameSel_x86_x64_dll_v2-20_20180420.zip FrameSel_x86_x64_dll_v2-20_20180420.zip]
 +
|}
 +
<br>
 +
== External Links ==
 +
<br>
 +
<br>
 +
-----------------------------------------------
 +
'''Back to [[External_filters#Frame_Replacement/Range_Processing|External Filters]] &larr;'''
 +
-----------------------------------------------

Latest revision as of 17:49, 26 May 2020

Abstract
Author StainlessS
Version v2.20
Download FrameSel_x86_x64_dll_v2-20_20180420.zip
Category Frame Replacement / Range Processing
License GPLv2
Discussion Doom9 Forum


Contents

[edit] Description

FrameSel() is a simple plugin to select individual frames from a clip.

Can select frames numbers by direct arguments to filter, or in a string, or in a command file.

[edit] Requirements


*** vcredist_x86.exe is required for FrameSel-x86
*** vcredist_x64.exe is required for FrameSel-x64


[edit] Syntax and Parameters

FrameSel(Clip, int F1, ... , int Fn, string 'scmd',string 'cmd', bool 'show', bool 'ver',bool "reject",bool "ordered",
            \ bool "debug", int "Extract"=1)

Compulsory args:

        Clip,   No Default, source clip.


Optional args:  (at least one of the frame select options must be supplied).

    F1...Fn Un-named. Zero or more frame numbers.

        SCmd,   string, Default= "", Not set.
                Command String, frame numbers supplied in a string.

        Cmd,    string, Default= "", Not set.
                Command file, frame numbers supplied in a file. Use eg "Select.txt" for command file in your script directory.

        Show    bool, Default= false.
                true = Show info. (Requires v2.6 dll if a v2.6 colorspace, except Y8 OK in 2.5 dll).

        Ver     bool, Default=false.
                true = Show version. (Requires v2.6 dll if a v2.6 colorspace, except Y8 OK in 2.5 dll).

        Reject  bool, Default False. If true then selects frames NOT specified rather than specified frames.
                eg if you have a 5 frame clip (0->4) and have commands to select 4,2 and 0, then reject=true would actually
                select frames 1 and 3 instead.
                If reject=true, then orderering occurs no matter whether Ordered is set true or false and the frames are returned
                in sequential order.
                Reject might be of use to view all frames NOT in a frames command set.

        Ordered bool, Default true. No effect if reject is true, where Ordered will ALWAYS be as if set true.
                If true then all selected frames are sequentially ordered and only unique frames are selected
                and returned in sequential order. If Ordered is set false, no frame number ordering is done and eg if
                frames 10,20,30,20,10 were selected in commands, then it would select 5 frames; 10 and 20 and 30 and 20 and 10,
                are returned and in that order. If Ordered is set default true, then for same example it would return 10 and 20
                and 30, in that sequential order.
                So, the purpose of Ordered=true (default), is to remove duplicates and return sequential frames.
                Only change Ordered to false if you are convinced you know what you are doing.

        Debug   bool, Default false. If true sends a little debug info to debugview window during Plugin initialization. (Google DebugView).

        Extract Int, Default 1, MUST be ODD, 1 to 11. Error if not default 1 AND neither Ordered nor Reject == True.
                Let us call the UNIQUE resultant frames after Ordered and/or Reject Processing 'Target' frames.
                The number of frames pulled out on either side of Target frame is Extract / 2 (integer divide), so when Extract=3, it will
                extract 1 frame before target, the Target frame, and 1 frame after target, for each and every Target frame.
                This arg allows you to select eg 3 frames for each Target frame, the previous frame, Target frame and next frame.
                May be of use to extract bad frames together with eg 1 frame either side for saving as bitmaps and editing
                in some kind of RotoScope editor to repair bad frames using image from adjacent frames. The edited frames could
                then be re-loaded, middle one selected via SelectEvery(3,1), and then put back into original source clip via FrameRep().
                Another simple use could be when you have a clip where each frame before a scene change is bad, with Ordered=True
                and Extract=3, you pull out 3 frames, a SelectEvery(3,0) would select the frames previous to the bad frames and
                then use Framerep() to replace the bad frames with those previous to them. A SelectEvery(3,2) would select the frames
                after Target frames.
                The total number of frames pulled out of the source clip will be (Extract * number of Target frames).
                Reject is less likely to be of use with Extract, unless frame select commands specify good frames rather than bad,
                where Reject in FrameRep should also be true (same as in FrameSel, as always).
                See FrameRep() for example uses of Extract.


Either the direct frame numbers, Command string (SCmd), or command file (Cmd) must be supplied.
*** NOTE ***,  if more than one supplied, the commands in the Command File are processed
first followed by those in the SCmd String, and finally the directly supplied frame numbers, relevant when Ordered=false


NOTE, You can use frame ranges for both command file & command string (not possible for directly supplied frame number args).


The 'Cmd' Command file allows one command per line and can contain comments eg:

#------------- # below contents of a text file.
100       # This is a comment
200       # and so is this
300,400   # This is a frame range, specifies all 101 frames between 300 and 400 inclusive [As Trim(300,400)].
500,-2    # Specifies 2 frames starting at frame 500, ie 500 and 501 [As Trim(500,-2)].
600,0     # Specifies ALL frames from frame 600 to the end of the source clip [As Trim(600,0)].
#-------------
So in a command file, a single number specifies a frame, and a comma(,) separator indicates a frame range.
SPACE's are also now accepted as range separators, and can be used instead of commas as in above example.

The "SCmd" string accepts more than 1 command per line, but MUST be separated by a semi colon (;).
The Semi colon is processed as a sort of soft newline and will terminate a comment, so you CANNOT
have a semi colon in a comment. eg

SCMD = "
       1000  # This is a comment ; 2000 # the 2nd arg is 2000; 3000 # the third arg on a single line.
       4000 ; 5000 ; 6000
       7000,8000 ; 9000,-2 ; 10000,0  # Frames 7000-8000, 2 frames starting at 9000, and frame 10000 to end of clip.
"
So in a command string, a comma(,) specifies a frame range, and a semi colon(;) a new command.
SPACE's are also now accepted as range separators, and can be used instead of commas as in above example.


example commands:

FrameSel(clip, 1,2,3,4,5)                               as Trim(1,1) + Trim(2,2) + Trim(3,3) + Trim(4,4) + Trim(5,5)
FrameSel(clip,"100,110;200,-2;300,0")                   as Trim(100,110) + Trim(200,-2) + Trim(300,0)
FrameSel(clip, 1,2,3,4,5,"100;200;300","Select.txt")
FrameSel(clip, 1,2,3,4,5,"100;200;300")
FrameSel(clip, 1,2,3,4,5,"","Select.txt")
FrameSel(clip,"100;200;300","Select.txt")
FrameSel(clip,"","Select.txt")

--------------------------------------
--------------------------------------
--------------------------------------

FrameRep(Clip c,Clip c2 int F1, ... , int Fn, string 'scmd',string 'cmd', bool 'show', bool 'ver',bool "reject",bool "debug")

Video:- Planar, YUY2, RGB32, RGB24.

Audio:- Returns source clip c audio.

Args identical to FrameSel, with exception of the compulsory 2nd clip arg which is a clip of frames to replace into the 1st source clip,
and also does not have an Ordered argument, as it is ALWAYS Ordered, and FrameRep, does not have the Extract arg.

See FrameSel() description for other arguments.

FrameRep() is complimentary to FrameSel, whereas FrameSel extracts frames, FrameRep replaces or reseats them (from the c2 clip) back from
whence they came (into the c clip) and using the EXACT same arguments and commands (whether directly supplied or in string command or
file command). If you wish to extract some frames and later replace back into the source clip, you MUST use the default Ordered=True in
FrameSel or the frames may not be replaced back into the positions they originally came from.

The number of Unique Selected frames in the combined frames commands MUST EQUAL the number of frames in the c2 clip (after taking Reject
into account), or it WILL throw an error, (will not know where to put the remainder or frame shortage). This is the reason you should
use the same frame commands in both FrameSel and FrameRep so that there will be an identical number of unique frames and Ordered
sequential. If Debug is set true, it will show a little info in DebugView (Google), eg number of unique frames in a command set.

# ----------------

Here, Example to do some simple editing on selected frames, try changing REJECT to True.

Colorbars.Trim(0,-10).ShowFrameNumber()                            # 10 frames
sCmd="2;5;6"                                                       # Frames in SCmd string
REJECT=False                                                       # False=modify SCmd frames : True=modify frames NOT in SCmd
SELECTED=FrameSel(scmd=sCMD,ordered=TRUE,reject=REJECT,debug=true) # We are going to use FrameRep, must use ORDERED=True (OR REJECT=True)
SELECTED=Invert(SELECTED)                                          # Do some editing
FrameRep(Last,SELECTED,scmd=sCMD,reject=REJECT,debug=true)         # Put edited frames back into original Last clip (audio from Last)
return Last

# ----------------

Example use when NOT selecting/replacing in exact same position:
  Lets say you have a clip with a bad frame before each scene change and you want to replace these bad frames with the frame immediately
before it.

    C=Colorbars().Trim(0,-50).ShowFrameNumber()                    # 50 frames (0 -> 49)
    BADFRAMES = "10;20;30;40"                                      # 4 bad frames in source clip
    PREBAD    = " 9;19;29;39"                                      # 4 frames immediately before bad frames
    REPAIR=FrameSel(C,scmd=PREBAD)                                 # Get the 4 frames we will duplicate
    Return FrameRep(C,REPAIR,scmd=BADFRAMES)                       # fix bad frames with REPAIR clip from PREBAD frames

Will produce a duplicate at frames 10, 20, 30, and 40 in source clip.

When used as above you must ensure that eg BADFRAMES and PREBAD have the same number of unique frames and sequential or results
may not be as expected (ie use Ordered).

# ----------------

Same Example again using Extract arg:-

    C=Colorbars().Trim(0,-50).ShowFrameNumber()                     # 50 frames (0 -> 49)
    BADFRAMES = "10;20;30;40"                                       # 4 bad frames in source clip
    EXTRACT=FrameSel(C,scmd=BADFRAMES,ordered=True,extract=3)       # Extract Previous, Target and Next frames for each Target frame
    REPAIR=EXTRACT.SelectEvery(3,0)                                 # Select each frame previous to Target bad frames, 1st of each triplet
    #REPAIR=REPAIR.Invert()                                         # So we can easily see repaired frames
    Return FrameRep(C,REPAIR,scmd=BADFRAMES)                        # Fix bad frames with REPAIR clip using exact same BADFRAMES spec.

# ----------------

Example scripts to show use with a paint program for manual frame repair.

    # Extract Script
    C=Colorbars().Trim(0,-50).ShowFrameNumber.ConvertToRGB24        # 50 frames (0 -> 49), RGB24
    BADFRAMES = "10;20;30;40"                                       # 4 bad frames in source clip
    EDITCLIP=FrameSel(C,scmd=BADFRAMES,ordered=True)                # Extract BAD frames
    EDITCLIP.ImageWriter(file="Pic%06d.bmp",type="bmp",info=true)   # Write bitmaps to edit
    return Last
    # Need to play all way through for ImageWriter to work properly.

    # Here, EDIT bad frames in paint program

    # Replace Script, after editing
    C=Colorbars().Trim(0,-50).ShowFrameNumber.ConvertToRGB24        # 50 frames (0 -> 49), RGB24
    BADFRAMES = "10;20;30;40"                                       # 4 bad frames in source clip
    END = 3                                                         # unique_bad_frames - 1 (number of frames in BADFRAMES-1)
    REPAIRED=ImageReader(file="Pic%06d.bmp",end=END)
    #REPAIRED=REPAIRED.Invert()                                     # Hilite repaired frames, easier to see
    Return FrameRep(C,REPAIRED,scmd=BADFRAMES,show=true)            # Fix bad frames with REPAIRED clip using exact same BADFRAMES spec.
    # NOTE, you need to tell ImageReader the last frame number to read,
    # the default for End is 1000, so imagereader will read in 4 frames (0 to 3) and 997 duplicates,
    # FrameRep would throw an error as it does not know what to do with the unwanted 997 duplicate frames that were 'helpfully' appended.
    # The 1st script, ImageWriter(Info=True) arg, shows the FrameNumber and name for each frame, and the number shown on the last frame
    # can be assigned to END in 2nd script, shows eg "Frame 3 written to: D:\Pic000003.bmp".
    # The Last frame number shown by Info=True, will be correct even if BADFRAMES list (in eg string or command file) has duplicates
    # as they will be sorted and only unique frames delivered by FrameSel when Ordered=True is used, eg
    #  BADFRAMES="40;30;20;10;20;30;40", if used in 1st script FrameSel will select exactly the same frames as BADFRAMES="10;20;30;40",
    # ie 4 frames and in sequential order (Ordered=True).
# ----------------

Example scripts to show use with a paint/rotoscope program that can read in bad frames together with previous and next frames,
  and manually fix frames using image data from previous or next frames to repair damage.
    # Extract Script
    C=Colorbars().Trim(0,-50).ShowFrameNumber.ConvertToRGB24        # 50 frames (0 -> 49), RGB24
    BADFRAMES = "10;20;30;40"                                       # 4 bad frames in source clip
    EDITCLIP=FrameSel(C,scmd=BADFRAMES,ordered=True,extract=3)      # Extract Previous, Target and Next frames for each BAD frame
    EDITCLIP.ImageWriter(file="Pic%06d.bmp",type="bmp",info=true)   # Write bitmaps to edit
    return Last

    # Here, EDIT in Triple frame paint/rotoscope editing program

    # Replace Script, after editing triplets
    C=Colorbars().Trim(0,-50).ShowFrameNumber.ConvertToRGB24        # 50 frames (0 -> 49), RGB24
    END = 11                                                        # unique_bad_frames * Extract - 1
    BADFRAMES = "10;20;30;40"                                       # 4 bad frames in source clip
    EDITCLIP=ImageReader(file="Pic%06d.bmp",end=END)
    REPAIRED=EDITCLIP.SelectEvery(3,1)                              # Select repaired BAD frames, 2nd of each triplet
    #REPAIRED=REPAIRED.Invert()                                     # Hilite repaired frames, easier to see
    Return FrameRep(C,REPAIRED,scmd=BADFRAMES,show=true)            # Fix bad frames with REPAIRED clip using exact same BADFRAMES spec.

--------------------------------------
--------------------------------------
--------------------------------------

FrameSel_CmdReWrite(Clip c,String ofn, int F1, ... , int FN, String "SCmd"="", String "Cmd"="", \
      Bool "Reject"=False, Bool "Ordered"=True, Bool "Debug"=False, Bool "Range"=True, Bool "Space"=False, Bool "Prune"=False)

Args identical to FrameSel (up to Debug), with exception of the additional compulsory 2nd String arg which is
an output filename, and missing Ver and Show and Extract args.
See FrameSel() description for other arguments.

      ofn,      String, Compulsory.
                Output file name. It is advised to use a different name to the Cmd file, although there is nothing to stop you
                overwriting an original Cmd file if you like a little gamble.(Output file only written after fully read in and
                all Ordering, Rejecting etc already processed. Only likely error would be during file writing eg eject floppy disk).

      Range,    bool, Default=True
                False = Write individual frame numbers only, to output file.
                True  = (Default) Write comma separated Frame Ranges to output file (only where adjacent frames).

      Space,    bool, Default=False
                False = (Default) Write comma separators in output file for ranges.
                True  = Write SPACE separators in output file  instead of comma for ranges.

      Prune,    bool, Default=False
                False = (Default) Write FrameSel style frames or ranges to output file.
                True  = Write Prune style frames or ranges to output file (with a clip index first eg '0,10,20' instead of '10,20').
                Prune supports up to 256 input clips that is the reason it needs a clip index.
                Prune Supports Audio (whereas FrameSel does not) and also allows you to audio fadein/out at splices.
                This function can only output Prune command files, it cannot read Prune command files.

FrameSel_CmdReWrite, takes either Frame numbers as direct arguments, or in the SCmd string, or in the Cmd file (at least one must
be specified). If more than one command method is used, will process Cmd file first, then SCmd string second and lastly
directly supplied frame numbers. The command frames will be acted upon via the Reject, and Ordered, args (as in FrameSel)
and then re-written to the output command file. Any comments in SCmd string or Cmd file will not be written to the output
command file.

The FrameSel_CmdReWrite() function returns the total number of frames written to the output file (including ranges).

This function could have several uses:-
  To combine multiple frame specifying command methods into a single command file, and if Ordered, then remove duplicates.
  Convert single frame command files to frame range command files, (smaller and perhaps easier to peruse).
  Convert frame range command files to single frame command files, for use in another plugin that expects only frame numbers.
  Convert a Reject=True command set to Reject=False command file, and vice versa.
  Convert a command file of single frames/ranges to reject from a clip, into a Prune command file (Prune does not itself have a
    Reject arg but it does fadein/out audio at splices and can also coalesce single frames into ranges before splicing so that
    it does not fadein/out at every single individually specified frame).
  Perhaps more uses.

  *** NOTE ***, if you would normally use Reject=True in FrameSel, and you do a conversion with Reject=True, then the resultant
  command file should be used with Reject=False in FrameSel.

--------------------------------------
Example:
    avisource("d:\avs\flashtest.avi").trim(1000,-10).showframenumber

    # Delete list of frames, No Audio returned

    # Uncomment one of the below three lines

    #FrameSel(3,5,7,reject=true)            # delete frames using direct arg frame numbers, return no audio (ranges not supported in direct arg framenos)

    #FrameSel(SCmd="3;5;7",reject=true)     # delete frames using scmd string of frame numbers, return no audio (';' or Chr(10)=separator, ','=range)

                                            # del.txt = file containing eg "3"+chr(10)+"5"+chr(10)+"7"+chr(10)
    #FrameSel(Cmd="del.txt",reject=true)    # delete frames using cmd file of newline separated frame numbers, return no audio
---
Example: (Uses Prune and RT_Stats, these two examples also included in AVS directory):-

    Function SelectRanges(clip c,String "SCmd",String "Cmd",Bool "TrimAudio",Float "FadeMS",Bool "Ordered") {
        # SelectRanges() by StainlessS. Required:- FrameSel, Prune, RT_Stats
        # Wrapper to Select frames/ranges along with audio, can supply frames/ranges in SCmd string And/Or Cmd file.
        #   The wrapper makes for easier usage of Prune() which supports up to 256 input clips, but requires a clip index,
        #   eg '3, 100,200' would specify clip 3, range 100 to 200. The wrapper does away with the necessity for the clip index as we
        #   are only using a single clip here.
        #
        # SCmd: Frames/Ranges specified in String (Frames/Ranges either Chr(10) or ';' separated, infix ',' specifies range, eg 'start,end').
        # Cmd:  Frames/Ranges specified in file (one frame/range per line, comments allowed, see FrameSel for Further info).
        #  *** NOTE ***, If both Cmd and SCmd supplied AND Ordered == False, then will process Cmd file and then SCmd string afterwards, ie
        #    Will select ranges in Cmd file and in order specified (rather than auto ordering ranges) and then append ranges specified in
        #    SCmd string (and in order specified).
        # TrimAudio:
        #   True(default), selects audio belonging to selected frames/ranges
        #   False, returns original audio, probably out of sync (maybe totally out of whack if Ordered == false and selected ranges out of order).
        # FadeMS: (default 1.0 millisec). Linear Audio Fade duration at splices when TrimAudio==true, 0 = dont fade (might result in audio 'clicks/cracks').
        # Ordered:
        #   True(default), all frames/ranges are returned in sequencial order. Any frame specified more than once will return only 1 instance.
        #   False, All frames/Ranges are returned in specified order, Cmd processed first and then SCmd. Frames/ranges specified more than once
        #     will return multiple instances. Allows out-of-order trimming of clip, eg re-sequencing of scenes in movie.
        #
        # Does not make much sense to select individual frames with audio, best used with ranges.
        # Will coalesce individually selected adjacent frames/ranges before any Fade, ie only audio fade where sensible to do so.
        # TrimAudio==false with non Ordered selection will result in completely out of sync audio.
        c
        TrimAudio=Default(TrimAudio,True)   # default true trims audio, false returns original audio (audiodubbed, as Framesel returns no audio)
        FadeMS=Float(Default(FadeMS,1.0))   # 1 millisecond linear fadeout/fadein at splices
        Ordered=Default(Ordered,True)       # True (default) frames/ranges will be Ordered and selected only once even if specified more than once.
                                            # False, frames/ranges returned in specified order, Cmd processed 1st and then SCmd.
        PruneCmd = (TrimAudio) ? "~Prune_"+RT_LocalTimeString+".txt" : ""
        (!TrimAudio)
            \ ? FrameSel(scmd=SCmd,cmd=Cmd,Ordered=Ordered)
            \ : FrameSel_CmdReWrite(PruneCmd,scmd=SCmd,cmd=Cmd,Ordered=Ordered,Prune=True,range=true)
        (TrimAudio) ? Prune(Cmd=PruneCmd,FadeIn=True,FadeSplice=True,FadeOut=True,Fade=FadeMS) : NOP
        # If TrimAudio==true then delete Prune temp file, Else restore original Audio to the now audio-less clip
        (TrimAudio)
            \ ? RT_FileDelete(PruneCmd)
            \ : (c.HasAudio) ? AudioDub(c) : NOP
        Return Last
    }

    avisource("d:\avs\flashtest.avi").trim(1000,-20).showframenumber # 20 frames

    SCMD="""    # This is a comment
        1,3     # Select Range 1 to 3
        9,11    # Select Range 9 to 11
        14,15   # Select Range 14 to 15
        2,5     # Select Range 2 to 5, If Ordered==True then already previously selected 1st range above (1,3) extended to 1,5
    """

    ORDERED=True
    SelectRanges(scmd=SCMD,Ordered=ORDERED)                     # Select SCmd ranges, trim audio 1 ms fade.
    #SelectRanges(scmd="1,3;9,11;14,15;2,5",Ordered=ORDERED)    # Exactly the same as above

--------------------------------------
Example:

    Function RejectRanges(clip c,String "SCmd",String "Cmd",Bool "TrimAudio",Float "FadeMS") {
        # RejectRanges() by StainlessS. Required:- FrameSel, Prune, RT_Stats
        # Wrapper to delete frames/ranges along with audio, can supply frames/ranges in SCmd string And/Or Cmd file.
        #   The wrapper makes for easier usage of Prune() which supports up to 256 input clips, but requires a clip index,
        #   eg '3, 100,200' would specify clip 3, range 100 to 200. The wrapper does away with the necessity for the clip index as we
        #   are only using a single clip here. Prune also does not have a 'reject' arg to delete specified frames rather than select them,
        #   this wrapper also converts a list of frames to delete into a list of frames to select so that we can use Prune and its audio
        #   capability.
        #
        # SCmd: Frames/Ranges specified in String (Frames/Ranges either Chr(10) or ';' separated, infix ',' specifies range, eg 'start,end').
        # Cmd:  Frames/Ranges specified in file (one frame/range per line, comments also allowed, see FrameSel for Further info).
        # TrimAudio:
        #   True(default), deletes audio belonging to deleted frames
        #   False, returns original audio, probably out of sync.
        # FadeMS: (default 1.0 millisec). Linear Audio Fade duration at splices when TrimAudio==true, 0 = dont fade (might result in audio 'clicks/cracks').
        c
        TrimAudio=Default(TrimAudio,True)   # default true trims audio, false returns original audio (audiodubbed, as Framesel returns no audio)
        FadeMS=Float(Default(FadeMS,1.0))   # 1 millisecond linear fadeout/fadein at splices
        PruneCmd = (TrimAudio) ? "~Prune_"+RT_LocalTimeString+".txt" : ""
        (!TrimAudio)
            \ ? FrameSel(scmd=SCmd,cmd=Cmd,reject=true)
            \ : FrameSel_CmdReWrite(PruneCmd,scmd=SCmd,cmd=Cmd,reject=true,Prune=True,range=true)
        (TrimAudio) ? Prune(Cmd=PruneCmd,FadeIn=True,FadeSplice=True,FadeOut=True,Fade=FadeMS) : NOP
        # If TrimAudio==true then delete Prune temp file, Else restore original Audio to the now audio-less clip
        (TrimAudio)
            \ ? RT_FileDelete(PruneCmd)
            \ : (c.HasAudio) ? AudioDub(c) : NOP
        Return Last
    }

    avisource("d:\avs\flashtest.avi").trim(1000,-20).showframenumber # 20 frames

    SCMD="""    # This is a comment
        1       # delete frame 1
        9       # delete frame 9
        11,15   # delete range 11 to 15
    """

    # del.txt = file containing eg "3"+chr(10)+"5"+chr(10)+"7"+chr(10)
    RejectRanges(scmd=SCMD,cmd="del.txt")           # Delete frames 1 & 9, 11 to 15, and frames in del.txt 3 and 5 and 7, trim audio 1 ms fade
    #RejectRanges(scmd="1;9;11,15",cmd="del.txt")   # Exactly the same as above


--------------------------------------
--------------------------------------
--------------------------------------

FrameSel_MakeReDupCmd(Clip c,String ofn, int F1, ... , int FN, String "SCmd"="", String "Cmd"="", \
      Bool "Reject"=False, Bool "Debug"=False, Bool "Range"=True, Bool "Comments"=False)

    FrameSel_MakeReDupCmd(), a function to take a duplicates frames command file and convert it to a FrameSel command file to
    replace duplicates in source clip with duplicates that are identical to the predecessor frame of the first duplicate.
    You could eg pull out non duplicates using FrameSel (with Reject=True), and do some kind of processing on those frames,
    and then re-create duplicates but with identical duplicates using the processed clip as source for the newly inserted
    identical duplicates. Motion Compensated processing would likely work better with duplicates removed first.
    Identical Duplicates may be of some use in creating VFR (Variable Frame Rate) encodes, or in better compression where
    many duplicates present.
        The Reject arg provides you with the option of using a non dupe frames list rather that a dupe frames list and achieve
    identical results, see later example.

    Args identical to FrameSel (up to Reject), with exception of the additional compulsory 2nd String arg which is
    an output filename, and missing Ordered (is always ordered), Ver and Show and Extract args.
    See FrameSel() description for other arguments.

      ofn,      String, Compulsory.
                Output file name. It is advised to use a different name to the Cmd file, although there is nothing to stop you
                overwriting an original Cmd file if you like a little gamble.(Output file only written after fully read in and
                all Ordering, Rejecting etc already processed. Only likely error would be during file writing eg eject floppy disk).

      Range,    bool, Default=True
                False = Write individual frame numbers only, to output file.
                True  = (Default) Write comma separated Frame Ranges to output file (only where adjacent frames).

      Comments, Bool, default False.
                If true, then write additional descriptive comments to output file, else no comments written.

    FrameSel_MakeReDupCmd, takes either Frame numbers as direct arguments, or in the SCmd string, or in the Cmd file (at least one must
    be specified). If more than one command method is used, will process Cmd file first, then SCmd string second and lastly
    directly supplied frame numbers. The command frames will be acted upon via the Reject arg (as in FrameSel, and here Ordered is ALWAYS
    implied) and then re-written to the output command file. Any comments in SCmd string or Cmd file will not be written to the output
    command file, where arg Comments=True, comments are auto generated to help decipher the output.

    The FrameSel_MakeReDupCmd() function returns the total number of duplicate frames written to the output file.

    Example:
        # Script to test identical results if commands specified as either duplicates or non duplicates.
        # Duplicates are synthesized as Blank Frames and will be replaced with duplicate of frame prior to first blank/dupe.
        # Req ClipClop, RT_Stats, FrameSel plugins.
        #######
        CB=ColorBars.KillAudio.Trim(0,-20).ShowFrameNumber   # 20 frames
        BK=Last.BlankClip
        #
        CCDupeFrames=""" # ClipClop Duplicate Frame Numbers for creating test clip
            1 3,5
            1 9,11
            1 15,17
        """
        FSDupeFrames=""" # FrameSel Duplicate Frame Numbers (MUST NOT INLCUDE 0)
            3,5
            9,11
            15,17
        """
        #
        CCNonDupeFrames=""" # ClipClop Non Duplicates  Frame Numbers for creating test clip
            1 0,2
            1 6,8
            1 12,14
            1 18,19
        """
        FSNonDupeFrames=""" #  FrameSel Non Duplicates (MUST INCLUDE FRAME 0)
            0,2
            6,8
            12,14
            18,19
        """
        ####### CONFIG #####
        AreDupes=True        # If True then SCmd=list of duplicates, else list of non duplicates (SHOULD GET SAME RESULT)
        ####################
        CCSCmd = (AreDupes) ? CCDupeFrames : CCNonDupeFrames
        SCmd   = (AreDupes) ? FSDupeFrames : FSNonDupeFrames
        ORG    = (AreDupes) ? ClipClop(CB,BK,scmd=CCSCmd) : ClipClop(BK,CB,scmd=CCSCmd)
        #Return ORG
        #######
        ReDupFrames = "ReDupFrames.txt"       # FrameSel command to re-assemble clip after processing. (created by FrameSel_MakeReDupCmd).
        ReDupFrames = RT_GetFullPathName(ReDupFrames)
        # Select Non Dupes Only for processing (Ordered always implied if Reject)
        PreProc     = Org.FrameSel(SCmd=SCmd,Reject=AreDupes,Ordered=True) # MUST be Ordered, Ordered=True, for when Reject=False
        Processed   = PreProc.McDegrainSharp(Frames=3)    # Whatever Processing of non dupes
        # Make Cmd file to recreate dups from processed predecessor (Reject=False if SCmd file specifies duplicates. else true if is non dupes)
        FrameSel_MakeReDupCmd(ORG,ReDupFrames,Scmd=SCmd,Reject=!AreDupes,Debug=True,Range=True,Comments=True)
        ReDupped=Processed.FrameSel(Cmd=ReDupFrames,Ordered=False)      # Recreate Dups. (duplicates so cannot be Ordered)
        #######
        #return ReDupped
        StackVertical(ORG,ReDupped)
        #AudioDubEx(Last,ORG)    # Restore audio
        Return Last

        Result for above script in ReDupFrames.txt command file.
        Numbers in comments are output frame numbers, those prefixed by a 'D' are duplicates.
        Below shows why you need in line ReDupped=Processed.FrameSel(Cmd=ReDupFrames,Ordered=False), Ordered=False, as we have
        at beginning of file frames 0,2 ;2;2;2, so must not be ordered.
        >>>>>>>>>>>>
            0     ,2      #   0,2 [Len=3]
            2             # D 3    # These are duplicates
            2             # D 4
            2             # D 5
            3     ,5      #   6,8 [Len=3]
            5             # D 9
            5             # D 10
            5             # D 11
            6     ,8      #   12,14 [Len=3]
            8             # D 15
            8             # D 16
            8             # D 17
            9     ,10     #   18,19 [Len=2]
        <<<<<<<<<<<<<
--------------------------------------


[edit] Examples

TODO

[edit] Changelog

v1.00 - 23 Mar 2012 : 1st release.
v1.01 - 24 Dec 2012 : Added frame ranges to CMD and SCMD.
v1.02 - 27 Apr 2013 : Added FrameRep
v1.03 - 14 May 2013 : Added FrameSel Reject mode.

	Renamed to FrameSel/FrameRep, reversioned to v2.0

v2.00 - 30 May 2013 : Implemented ordered, and SPACE separator in command file.
v2.10 - 23 Feb 2014 :
	Fixed All Frames Rejected bug (zero length return clip), best throw an error.
	Implemented Unique_Sort(), much faster in unlikely event that frames are in random order (when Ordered or Reject) .
	Added function FrameSel_CmdReWrite();
v2.11 - 27 Feb 2014 : 
	Fixed, v2.5 dll only worked with YV12 or Y8, (FrameRep when Show or Ver, throw error) oops.
	Added Extract arg to FrameSel().
v2.12 - 02 Mar 2014 :
	Increased FrameSel maximum Extract to 11. Added FrameSel Extract offset indicator when show = true. 
v2.13 - 30 Mar 2015. Recompile v2.6 dll with Avisynth Version 6 Header.
v2.20 - 20 Apr 2018. Add FrameSel_MakeReDupCmd, and x64. Recompile VS2008.


[edit] Archived Downloads

Version Download Mirror
v2.20 FrameSel_x86_x64_dll_v2-20_20180420.zip FrameSel_x86_x64_dll_v2-20_20180420.zip


[edit] External Links




Back to External Filters


Personal tools