Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 30th May 2013, 07:01   #1  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
FrameSel/FrameRep v2.21 - 27 Jul 2021

see post #16 for current docs https://forum.doom9.org/showthread.p...43#post1839843
Code:
	FrameSel/Rep by Stephen Jones, AKA StainlessS @ Doom9

	v2.58, v2.60 x86 and x64 dll's

	Old Version:- FrameSelect(), http://forum.doom9.org/showthread.php?t=164497

	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.
	v2.21 - 27 July 2021
		Added High Bit Depth metrics [using DDigit 2.0]
		Added PruneIx arg to FrameSel_CmdReWrite.
Short Excerpt from docs (hit D9 meagre 16KB limit AGAIN!!!)
Code:
FrameSel/Rep() Plugins for Avisynth v2.58/v2.6 by StainlessS.

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.


Video:- All Valid colorspaces

Audio:- Returns NO AUDIO (Does not really make sense for individual frames, although now supports ranges).


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:- All Valid colorspaces

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.

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

EXAMPLES REMOVED, HIT D9 16KB limit AGAIN !!!


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

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, int "PruneIx"=0)

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.  

      PruneIx,  Int, Default 0. [Added in v2.21]
                Only real use for this is if you want to convert a frames/ranges file to ClipClop format instead of Prune format.
                ClipClop and Prune both support 256 clips, and so both need a clip index to specify clip to use.
                With Prune, you might want to work with a single clip and so default PrunIx of 0, will be what you almost
                certainly want. However, with ClipClop, clip index 0 is the source clip, and to work with only 1 replacement
                clip you will almost certainly want to specifiy a clip index of 1 [replace clip index 0 range with same
                clip index 0 range, would do nothing at all].
                When result is intended for Clipclop, its probably a good idea to use ORDERED=True [the default], although ClipClop
                will order and remove duplicate frames/ranges itself.
                There is no validity check of any kind on the PruneIx, it will even output -ve index.

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.   

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

StainlessS.
For audio support with fade in/out see trim/splice plugin Prune().
http://forum.doom9.org/showthread.php?t=162446
For frame range replacement see ClipClop().
http://forum.doom9.org/showthread.php?t=162266

See here for two scripts that allow you to select and delete ranges of frames including audio with fadeout/in at splices.
http://forum.doom9.org/showthread.ph...59#post1683559
See MediaFire or SendSpace in sig
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 27th July 2021 at 21:07. Reason: Update
StainlessS is offline   Reply With Quote
Old 19th October 2013, 20:55   #2  |  Link
martin53
Registered User
 
Join Date: Mar 2007
Posts: 407
With respect to the johnmeyer thread - you really programmed a treasure of plugins over time!
martin53 is offline   Reply With Quote
Old 23rd February 2014, 21:30   #3  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
FrameSel/FrameRep v2.10 - New version, see 1st post.

Code:
	FrameSel/Rep v2.5 and v2.6 dll's by StainlessS

	Old Version:- FrameSelect(), http://forum.doom9.org/showthread.php?t=164497

	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();
Main difference, function added
Code:
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 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.

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.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 25th February 2014, 18:37   #4  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
There is one thing I should have mentioned about this filter, ie

Original intent for this filter, was to extract frames for manual repair in eg paint program, and then replace back into source clip.

EDIT: Last paragraph of this post:
http://forum.doom9.org/showthread.ph...57#post1520157
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 26th February 2014 at 19:04.
StainlessS is offline   Reply With Quote
Old 27th February 2014, 04:31   #5  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
New version, v2.11, see 1st post.

Code:
	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 (EDIT: FrameRep, when Show or Ver), (throw error) oops.
		Added Extract arg to FrameSel().
FrameSel Extract Arg
Code:
       Extract Int, Default 1, MUST be ODD, 1 or 3 or 5 or 7. 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.
Here, Examples removed from 1st post due to draconian D9 16KB limit in Usage forum
Code:
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.
EDIT:
Extract now fully implements support for original intent, as in previous post link.

What we need now is a Windows progger to write a RotoScope type frame editor that supports import of previous,
Target, and next frames, as either a clip or a bunch of frame triplets (for Copy/Rub-Through From Adjacent Frame, or Interpolated
From Adjacent Frames, or maybe even quintuplets or septets for motion predicted frames/pixels).
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 12th June 2014 at 22:36.
StainlessS is offline   Reply With Quote
Old 2nd March 2014, 22:38   #6  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
New Version FrameSel() v2.12, see 1st post.

Code:
	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.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 30th March 2015, 21:55   #7  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
FrameSel/FrameRep v2.13 - 30 Mar 2015. Re-compiled v2.6 dll with Avisynth Version 6 Header, see 1st post.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 4th February 2018, 04:34   #8  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Script Function, removes duplicates using existing single frames (not ranges) command file,
do processing on non dupes only,
recreate dupes in original positions but recreated by duplicating the unique frame prior to all duplicates (copes with multiple dupes in a row).

Here, the command file creator to re-create dupes in original position.
Code:
Function MakeReDupCmd(clip c,String "Frames",String "ReDupFrames") {
/*
    Req, RT_Stats v2.0, and FrameSel, & GSCript(c) Gavino.
    [Does NOT need GScript on Avs+]

    Create ReDupFrames frames command file, to recreate dupe frames from processed clip predecessor.
        Allows to process only non dupes, and re-create dupes from processed clip predecessor.

    Frames      = "Frames.txt"                                      # Input Frames file of dups (single frames only, no ranges)
    ReDupFrames = "ReDupFrames.txt"                                 # Re-dup creator
    ORG=AviSource("Dup.avi")
    PreProc   = Org.FrameSel(Cmd=Frames,Ordered=True,Reject=True)   # Select Non Dupes Only for processing
    Processed = PreProc.Sharpen(1.0).Sharpen(1.0).Sharpen(1.0)      # Whatever Processing of non dupes
    MakeReDupCmd(ORG,Frames,ReDupFrames)                            # Make ReDupFrames Cmd file to recreate dups from processed predecessor.
    ReDupped=Processed.FrameSel(Cmd=ReDupFrames,Ordered=False)      # Recreate Dups [EDIT: Identical dupes].
    Return AudioDubEx(ReDupped,ORG)                                 # Restore audio

*/
    c   FC=FrameCount   myName="MakeReDupCmd: "
    IsAvsPlus=(FindStr(UCase(versionString),"AVISYNTH+")!=0) HasGScript=RT_FunctionExist("GScript")
    Frames=Default(Frames,"Frames.txt")     ReDupFrames=Default(ReDupFrames,"ReDupFrames.txt")
    Assert(Frames!="",RT_String("%sFrames cannot be ''",myName))
    Assert(ReDupFrames!="",RT_String("%sReDupFrames cannot be ''",myName))
    Frames=RT_GetFullPathName(Frames)       ReDupFrames=RT_GetFullPathName(ReDupFrames)
    RT_FileDelete(ReDupFrames)
    TypeString="i"                          DB=RT_GetFullPathName("~"+"ReDupProcess_"+RT_LocalTimeString(file=True)+".DB")
    RT_DBaseAlloc(DB,0,TypeString)
    GS="""
        Records=RT_DBaseReadCSV(DB, Frames,StartField=0,EndField=0)                 # Records added. (read single frames file)
        RT_DBaseQuickSort(DB,Field=0)                                               # Ensure Ordered
        in_e   =-1
        uniq_e =-1
        For(Rec=0,Records-1) {
            ds=RT_DBaseGetField(DB,Rec,0)   de=ds                                   # Dupe frame
            While(Rec<Records-1 && RT_DBaseGetField(DB,Rec+1,0)-de<=1 ) {           # Coalesce multiple dupes.(Swallow multiples of same frame)
                Rec=Rec+1
                de=RT_DBaseGetField(DB,Rec,0)  # If was same as original de then swallow it, else is de+1
            }
            Assert(de <  FC, RT_String("%sEnd frame out of clip Error (de=%d)",myName,de))
            in_s=in_e+1     uniq_s=uniq_e+1     uniq_n=ds-in_s  ndups  = de-ds+1    uniq_e = uniq_s+uniq_n-1    in_e=de
            if(uniq_n==1)    { RT_WriteFile(ReDupFrames,"%-13d #   %d",   uniq_s,in_s,     Append=True) }
            else             { RT_WriteFile(ReDupFrames,"%-6d,%-6d #   %d,%d [Len=%d]",uniq_s,uniq_e,in_s,ds-1,ds-in_s,Append=True) }
            For(i=0,ndups-1) { RT_WriteFile(ReDupFrames,"%-13d # D %d",uniq_e,ds+i,Append=True) }
            if(Rec==Records-1 && in_e < FC-1) {
                in_s=in_e+1  uniq_s=uniq_e+1  uniq_n=FC-in_s  uniq_e=uniq_s+uniq_n-1
                if(uniq_n==1)    { RT_WriteFile(ReDupFrames,"%-13d #   %d",   uniq_s,in_s,     Append=True) }
                else             { RT_WriteFile(ReDupFrames,"%-6d,%-6d #   %d,%d [Len=%d]",uniq_s,uniq_e,in_s,FC-1,FC-in_s,Append=True) }
            }
        }
        RT_FileDelete(DB)
    """
    IsAvsPlus?Eval(GS):HasGScript?GScript(GS):Assert(False,RT_String("%sNeed either GScript or AVS+",myName))
    Return True
}
Demo clip maker, dupes simulated every 100 frames (actually blank frames for easy identifcation, they will be replaced).
Also creates a suitable frames file for the demo.
Code:
Function MakeDupClip(Int Len,int "dups",String "Frames") {
    # Req, RT_Stats, Gscript(only if not avs+).
    IsAvsPlus=(FindStr(UCase(versionString),"AVISYNTH+")!=0) HasGScript=RT_FunctionExist("GScript")
     dups=Default(dups,1)     Frames=Default(Frames,"Frames.txt")
    Assert(1 <= dups <= 9,"MakeDupClip: 1 <= dups <= 9")
    Colorbars.Killaudio.Trim(0,-Len).ShowFrameNumber.ConvertToYV12
    Frames=RT_GetFullPathName(Frames)
    RT_FileDelete(Frames)
    GS="""
        c=Last.BlankClip(length=0)
        n = 100-(1+dups)
        for(i=0,Len-1,100) {
            D = trim(i,-1) + c.BlankClip(Length=1).Loop(dups,0,0)
            M = trim(i+dups+1,-n)
            c = c + D + M
            for(j=1,dups) {
                RT_WriteFile(Frames,"%d",i+j,Append=True)
            }
        }
    """
    IsAvsPlus?Eval(GS):HasGScript?GScript(GS):Assert(False,RT_String("%sNeed either GScript or AVS+",myName))
    return c
}

# Make 1000 frame demo test clip with dupes every 100 frames (DUPS=number of duplicates, 1->9)
# For the demo, dups are actually blank frames so you can easily see effect (they will be replaced in 2nd part of demo).
# Save Clip to "Dup_"+String(DUPS)+".AVI" for part two of demo, eg "Dup_3.AVI" when DUPS==3.

DUPS=3
Frames="Frames_"+String(DUPS)+".txt"

MakeDupClip(1000,DUPS,Frames)
Part2 of demo,
Code:
#######
DUPS=3                                        # Names based on DUPS for demo test clip.
Frames="Frames_"+String(DUPS)+".txt"          #  Frames file of dups. (single frames only, not ranges)
AVI="Dup_"+String(DUPS)+".avi"                #
ReDupFrames = "ReDupFrames.txt"               # FrameSel command to re-assemble clip after processing. (created by MakeReDupCmd).
#######
Frames      = RT_GetFullPathName(Frames)
ReDupFrames = RT_GetFullPathName(ReDupFrames)
AVI         = RT_GetFullPathName(AVI)
#######
AviSource(AVI)
ORG=Last                                      # Original Video + Audio
#######
PreProc   = Org.FrameSel(Cmd=Frames,Ordered=True,Reject=True)   # Select Non Dupes Only for processing
Processed = PreProc.Sharpen(1.0).Sharpen(1.0).Sharpen(1.0)      # Whatever Processing of non dupes
#
MakeReDupCmd(ORG,Frames,ReDupFrames)                            # Make frames Cmd file to recreate dups from processed predecessor.
ReDupped=Processed.FrameSel(Cmd=ReDupFrames,Ordered=False)      # Recreate Dups.
#######
StackVertical(ORG,ReDupped)
AudioDubEx(Last,ORG)    # Restore audio
Return Last
Created ReDupFrames.txt where DUPS=3 (1000 input frames)
where input dupes @ 1->3, 101->103, 201->203, etc.
Code:
0             #   0
0             # D 1
0             # D 2
0             # D 3
1     ,97     #   4,100 [Len=97]
97            # D 101
97            # D 102
97            # D 103
98    ,194    #   104,200 [Len=97]
194           # D 201
194           # D 202
194           # D 203
195   ,291    #   204,300 [Len=97]
291           # D 301
291           # D 302
291           # D 303
292   ,388    #   304,400 [Len=97]
388           # D 401
388           # D 402
388           # D 403
389   ,485    #   404,500 [Len=97]
485           # D 501
485           # D 502
485           # D 503
486   ,582    #   504,600 [Len=97]
582           # D 601
582           # D 602
582           # D 603
583   ,679    #   604,700 [Len=97]
679           # D 701
679           # D 702
679           # D 703
680   ,776    #   704,800 [Len=97]
776           # D 801
776           # D 802
776           # D 803
777   ,873    #   804,900 [Len=97]
873           # D 901
873           # D 902
873           # D 903
874   ,969    #   904,999 [Len=96]
RT_Stats v2.0beta here:- https://forum.doom9.org/showthread.p...26#post1818026
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 3rd April 2018 at 08:16.
StainlessS is offline   Reply With Quote
Old 4th February 2018, 12:44   #9  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Bug fix to above first script.

Yoda, is above working for you ?
Will probably do an additional FrameSel function doing same as above, but coping with ranges as well as single frames.
(If I forget, remind me )

EDIT: Above script function is Yoda's idea to reduce processing duration [probably better MC denoising too].
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 4th February 2018 at 14:57.
StainlessS is offline   Reply With Quote
Old 9th February 2018, 03:12   #10  |  Link
Motenai Yoda
Registered User
 
Motenai Yoda's Avatar
 
Join Date: Jan 2010
Posts: 709
Sorry I have negative time unto march
__________________
powered by Google Translator
Motenai Yoda is offline   Reply With Quote
Old 5th March 2018, 19:36   #11  |  Link
Motenai Yoda
Registered User
 
Motenai Yoda's Avatar
 
Join Date: Jan 2010
Posts: 709
mmm... how I have to create Frames.txt from an existent video?
__________________
powered by Google Translator
Motenai Yoda is offline   Reply With Quote
Old 6th March 2018, 06:53   #12  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
How bout this, modified from another function (there are plenty of dupe frames detectors out there).

EDIT: SCript removed, see here for better alternative:- https://forum.doom9.org/showthread.php?t=175357

Client
Code:
Avisource(".\N.AVI")
WriteDupeFrames(0.5,Ranges=False)
I'll do a FrameSel mod (MakeReDupCmd with ranges) within a couple of days.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 2nd April 2018 at 00:28.
StainlessS is offline   Reply With Quote
Old 6th March 2018, 22:21   #13  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
I'll try do a mod for low motion detect, ie compared with initial start unique frame rather than previous frame.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 2nd April 2018, 00:50   #14  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Yoda, MakeReDupCmd and MakeDupClip in post #8 updated to work with GScript or Avs+ version of GScript interpreter.

Original dupe frames creator script removed from post #12, and replaced with link to new script function.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 2nd April 2018 at 00:53.
StainlessS is offline   Reply With Quote
Old 18th April 2018, 14:24   #15  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
FrameSel/Rep v2.20, new Beta Version, not well documented yet so Beta.
Here (v2.58, avs+ v2.6 x86/x64 + source ~100KB):- http://www.mediafire.com/file/dk7jy9...9_20180418.zip
Req VS cpp 2008 runtimes.

Code:
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)

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.

Similar to demo script in post #8, part 2
Code:
# Matching post #8, Part 2 of Demo

/*
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)
*/

#######
DUPS=3                                        # Names based on DUPS for demo test clip.
Frames="Frames_"+String(DUPS)+".txt"          # Frames file specifies duplicates
AVI="Dup_"+String(DUPS)+".avi"                #
ReDupFrames = "ReDupFrames.txt"               # FrameSel command to re-assemble clip after processing. (created by FrameSel_MakeReDupCmd).
#######
Frames      = RT_GetFullPathName(Frames)
ReDupFrames = RT_GetFullPathName(ReDupFrames)
AVI         = RT_GetFullPathName(AVI)
#######
AviSource(AVI)
ORG=Last                                      # Original Video + Audio
#######
PreProc   = Org.FrameSel(Cmd=Frames,Reject=True)                # Select Non Dupes Only for processing (Ordered always implied if Reject)
Processed = PreProc.Sharpen(1.0).Sharpen(1.0).Sharpen(1.0)      # Whatever Processing of non dupes
# Make Cmd file to recreate dups from processed predecessor (Reject=False, ie Cmd file specifies duplicates)
FrameSel_MakeReDupCmd(ORG,ReDupFrames,Cmd=Frames,Reject=False,Debug=True,Range=True,Comments=True)
ReDupped=Processed.FrameSel(Cmd=ReDupFrames,Ordered=False)      # Recreate Dups. (Multiple consecutive duplicates cannot be Ordered)
#######
#return ReDupped
StackVertical(ORG,ReDupped)
AudioDubEx(Last,ORG)    # Restore audio
Return Last
Another Test script
Code:
# 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 duplicates of processed frame prior to first blank/dupe.


/*
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)
*/

#######
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)  # Test clip (same result both cases) using frames in 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) # EDIT: Added Ordered=True, for when Reject=False
Processed   = PreProc.Sharpen(1.0).Sharpen(1.0).Sharpen(1.0)    # 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. (Multiple consecutive duplicates cannot be Ordered)
#######
#return ReDupped
StackVertical(ORG,ReDupped)
#AudioDubEx(Last,ORG)    # Restore audio
Return Last
EDIT: Above, adding of Ordered=True, not really necessary here as our SCmd lists are numerically ordered anyway.

Result for above script in ReDupFrames.txt command file.
Code:
0     ,2      #   0,2 [Len=3]
2             # D 3    # These are DUPES
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]
Numbers in above comments are output frame numbers.
Above shows why line ReDupped=Processed.FrameSel(Cmd=ReDupFrames,Ordered=False) requires Ordered=False.

EDIT: Also upped on SendSpace below in my sig.
Sorry about delay Yoda
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 20th April 2018 at 10:07.
StainlessS is offline   Reply With Quote
Old 20th April 2018, 11:18   #16  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Post #1 of 4.

FrameSel v2.21, new version

Docs current as of 27 Jul 2021

1) FrameSel
Code:
FrameSel/Rep() Plugins for Avisynth v2.58, avs/+ v2.6 x86/x64 (c) Stephen Jones AKA StainlessS.
v2.21, Supports High Bit Depth in Avs+ plugin, only really relevant where SHOW or VER = True, where it shows text on HBD frame.

FrameSel() is a simple plugin to select individual frames from a clip.
http://forum.doom9.org/showthread.php?t=167971


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


Video:- All Valid colorspaces

Audio:- Returns NO AUDIO (Does not really make sense for individual frames, although now supports ranges).

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")
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 27th July 2021 at 21:13.
StainlessS is offline   Reply With Quote
Old 20th April 2018, 11:18   #17  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Post #2 of 4.

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

Video:- All Valid colorspaces

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.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 27th July 2021 at 20:53.
StainlessS is offline   Reply With Quote
Old 20th April 2018, 11:19   #18  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Post #3 of 4.

3) FrameSel_CmdReWrite
Code:
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, int "PruneIx"=0)

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.

      PruneIx,  Int, Default 0. [Added in v2.21]
                Only real use for this is if you want to convert a frames/ranges file to ClipClop format instead of Prune format.
                ClipClop and Prune both support 256 clips, and so both need a clip index to specify clip to use.
                With Prune, you might want to work with a single clip and so default PrunIx of 0, will be what you almost
                certainly want. However, with ClipClop, clip index 0 is the source clip, and to work with only 1 replacement
                clip you will almost certainly want to specifiy a clip index of 1 [replace clip index 0 range with same
                clip index 0 range, would do nothing at all].
                When result is intended for Clipclop, its probably a good idea to use ORDERED=True [the default], although ClipClop
                will order and remove duplicate frames/ranges itself.
                There is no validity check of any kind on the PruneIx, it will even output -ve index.

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
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 27th July 2021 at 21:14.
StainlessS is offline   Reply With Quote
Old 20th April 2018, 11:20   #19  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Post #4 of 4.

4) FrameSel_MakeReDupCmd
Code:
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]
        <<<<<<<<<<<<<
--------------------------------------

StainlessS.

EDIT: And here is my entry on WikiPedia (I've been around a long time, being dead dont arf put a crimp in my life )
https://en.wikipedia.org/wiki/Stainless_Stephen
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 27th July 2021 at 20:55.
StainlessS is offline   Reply With Quote
Old 27th July 2021, 21:19   #20  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
v2.21, see 1st post.
[Available only on MediaFire in sig below this post, having problems getting into my SendSpace account].

Current docs available at post #16:- https://forum.doom9.org/showthread.p...43#post1839843

Code:
	v2.21 - 27 July 2021
		Added High Bit Depth metrics [using DDigit 2.0]
		Added PruneIx arg to FrameSel_CmdReWrite.
Code:
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, int "PruneIx"=0)


# ...

      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.

      PruneIx,  Int, Default 0. [Added in v2.21]
                Only real use for this is if you want to convert a frames/ranges file to ClipClop format instead of Prune format.
                ClipClop and Prune both support 256 clips, and so both need a clip index to specify clip to use.
                With Prune, you might want to work with a single clip and so default PrunIx of 0, will be what you almost
                certainly want. However, with ClipClop, clip index 0 is the source clip, and to work with only 1 replacement
                clip you will almost certainly want to specifiy a clip index of 1 [replace clip index 0 range with same
                clip index 0 range, would do nothing at all].
                When result is intended for Clipclop, its probably a good idea to use ORDERED=True [the default], although ClipClop
                will order and remove duplicate frames/ranges itself.
                There is no validity check of any kind on the PruneIx, it will even output -ve index.
Would previously work just fine with HBD clips, except where Show = true, ie printing metrics text on frame.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 27th July 2021 at 21:48.
StainlessS is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 02:41.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.