From Avisynth wiki
Jump to: navigation, search


RemapFrames, RemapFramesSimple, and ReplaceFramesSimple provide general control over manipulation of frame indices in a clip. They can be used in cases where SelectEvery isn't suitable, such as when the desired frames don't follow a regular pattern.

RemapFrames/RemapFramesSimple/ReplaceFramesSimple also are efficient alternatives to long chains of FreezeFrame, DeleteFrame, or ApplyRange calls.

RemapFramesSimple and ReplaceFramesSimple are less powerful than RemapFrames but use a much simpler, more basic syntax.

remf, remfs and rfs are shortcuts for RemapFrames, RemapFramesSimple and ReplaceFramesSimple with slight differences. The mappings parameter comes before filename for a more compact "inline" call. These parameters are completely optional; when none of them is specified, an empty string is assumed. And when an empty string is detected, the filter is completely bypassed (no extra memory use). Also, these versions don't check aggressively the frame ranges. If a referenced frame doesn't exist, it's simply ignored or its index is replaced with the closest valid frame index. This allows working on partial ranges of a clip with a unique set of mappings.


RemapFrames(clip baseClip, string "filename", string "mappings", clip "sourceClip")
RemapFramesSimple(clip c, string "filename", string "mappings")
ReplaceFramesSimple(clip baseClip, clip sourceClip, string "filename", string "mappings")

remf(clip baseClip, string "mappings", string "filename", clip "sourceClip")
remfs(clip c, string "mappings", string "filename")
rfs(clip baseClip, clip sourceClip, string "mappings", string "filename")

rfs_transform (string mappings, string "op", bool "open", bool "discrete")
rfs_merge (string "s0", string "s1", …, string "s9")




Frames from sourceClip are mapped into baseClip.

"filename" The name of the text file that specifies the new frame mappings.

Mappings also may be given directly in a string. Overrides frame mappings given by filename.


The source clip used to supply the new, remapped frames.
(Default: Same as baseClip.)


Does not affect the audio track.

Each line in the text file or in the mappings string must have one of the following forms:

  • a z
    Replaces frame a in baseClip with frame z from sourceClip.
  • [a b] z
    Replaces all frames in the inclusive range a..b of baseClip with frame z from sourceClip.
  • [a b] [y z]
    Replaces all frames in the range a..b of baseClip with frames in the range y..z from the sourceClip. If the input and output ranges do not have equal sizes, frames will be duplicated or dropped evenly from y ..z to match the size of a..b. If y > z, the order of the output frames is reversed.
  • # comment
    A comment. Comments may appear anywhere on a line; all text from the start of the # character to the end of the line is ignored.

Sample data file:

[0 9] [0 4]     # the first ten frames will be 0, 0, 1, 1, 2, 2, 3, 3, 4, 4
10 5            # show frame 5 in frame 10's place
[15 20] 6       # replace frames 15..20 with frame 6
[25 30] [35 40] # replace frames 25..30 with frames 35..40
[50 60] [60 50] # reverse the order of frames 50..60

Within each line, all whitespace is ignored.

By default, all frames are mapped to themselves.

If multiple lines remap the same frame, the last remapping overrides any previous ones.

 # the frames in the generated clip will be
 # 4, 0, 0, 0, 0, 0, 6, 7, ...
 [0 5] 0
 0 3
 0 4

The output clip always will have the same number of frames as the input clip. To delete frames, remap the appropriate frames and then call Trim afterward.

 # Replace frames 50..89 with 60..99.  This effectively deletes frames
 # 50..59.
 RemapFrames(mappings="[50 89] [60 99]")
 # Trim off the excess.
 Trim(0, 89)

To add duplicate frames, call LengthenClip first and then remap the appropriate frames.

 # Duplicate frame 50 ten times, and delay all the subsequent frames by
 # ten frames.
 RemapFrames(mappings="[50 59] 50
                       [60 109] [50 99]")



"filename" The name of the text file that specifies the new frame mappings.
"mappings" Mappings alternatively may be given directly in a string. Unlike RemapFrames, mappings and filename cannot be used together.


Does not affect the audio track.

RemapFramesSimple takes a text file or a mappings string consisting of a sequence of frame numbers. The number of frame mappings determines the number of frames in the output clip. For example:

 # Generate a clip containing only the first five frames.
 RemapFramesSimple(mappings="0 1 2 3 4")
 # Duplicate frame 20 five times.
 RemapFramesSimple(mappings="20 20 20 20 20")




Frames from baseClip are replaced by frames from sourceClip.

"filename" The name of the text file that specifies the frames to replace.
"mappings" Replacement frames alternatively may be given directly in a string.


Does not affect the audio track.

ReplaceFramesSimple takes a text file or a mappings string consisting of sequences or ranges of frame numbers to replace. For example:

 # Replaces frames 10..20, 25, and 30 from baseClip with the
 # corresponding frames from sourceClip.
ReplaceFramesSimple(baseClip, sourceClip, mappings="[10 20] 25 30")
 # Inverse-telecine a clip and fix individual frames that still show
 # combing.
 c = src.Telecide(...).Decimate(...)
 deinterlaced = c.KernelDeint(...)
 # Replace frames 30, 40, 50 with their deinterlaced versions.
 ReplaceFramesSimple(c, deinterlaced, mappings="30 40 50")



"mappings" A frame mapping string that can be used in ReplaceFramesSimple or rfs.
"op" String containing the operation to perform on the original mappings. Default: "x".

Indicates if ranges and single frames should be converted to half-open intervals before being tranformed then converted back to closed intervals. This flag is ignored when discrete is set to true. Default: true.

"discrete" Indicates if ranges should be split into individual frames before being transformed, and possibly grouped in ranges afterwards. Default: false.


rfs_transform is a helper function transforming a set of mappings for ReplaceFramesSimple using an arithmetic operation. This is useful when one needs to substitute frames after a framerate change or any kind of timeline manipulation.

The operation is noted in Reverse Polish Notation (or Postfix). All calculation are done in double-precision floating point data. The resulting frame is rounded to the nearest (even) integer. The logical operations return 0 or 1 and assume the input is false if exactly equal to 0, true otherwise. Here is a list of the available operators:

  • neg ! round floor ceil
  • - * / mod min max == != > >= < <= && || ^^
  • clip ?

There are three input variables:

  • x: the current frame index being processed,
  • r: indicates if it's the frame is the beginning of a range (0) or the end (1),
  • y: the other range boudary.

Excepted in discrete mode, single frames are considered as a ranges containing one frame. In half-open interval mode, the end of the range is augmented of 1 before the calculation. This ensures that the ranges and their implicit complementary intervals are treated equaly, with more consistency. This is an easy solution to avoid gaps at the range boundaries when the timeline is dilated.

When a range is reverted (time inversion), the function automatically swaps the resulting range boundaries and keep everything consistent.

Frames indexes are truncated if they go below 0, but there is no upper bound check. In half-open mode, the end of the clip is indexed by the frame after the last frame (whose number equals the total number of frames), whereas in closed mode, the end is the last frame (total number of frames minus 1).


 # Shifts the mappings 10 frames forward
 rfs_transform ("[100 199] 300 [400 999]", op="x 10  ")
 # result: "[110 209] 310 [410 1009]"
 # Dilates the mappings 5 times
 rfs_transform ("[100 199] 300 [400 999]", op="x 5 *")
 # result: "[500 999] [1500 1504] [2000 4999]"



"s0", …, "s9" Strings that can be used in ReplaceFramesSimple or rfs. Default: undefined.


rfs_merge is a helper function merging several mappings for ReplaceFramesSimple together. It just concatenates these strings and inserts spaces in between, but it is probably more convenient than a simple concatenation because it handles properly the undefined strings. If all strings are undefined, the result is also an undefined string.


 # Shifts the mappings 10 frames forward
 rfs_transform ("[100 199]", "300", "[400 999]")
 # result: "[100 199] 300 [400 999]"

Adapting Existing Scripts

Using FreezeFrame Using RemapFrames
FreezeFrame(10, 11, 10)
FreezeFrame(15, 16, 16)
FreezeFrame(20, 24, 21)
FreezeFrame(30, 32, 31)
FreezeFrame(35, 36, 36)
RemapFrames(mappings="[10 11] 10
                      [15 16] 16
                      [20 24] 21
                      [30 32] 31
                      [35 36] 36")
Using ApplyRange Using ReplaceFramesSimple
ApplyRange(10, 11, "SomeFilter")
ApplyRange(15, 16, "SomeFilter")
ApplyRange(20, 24, "SomeFilter")
ApplyRange(30, 32, "SomeFilter")
ApplyRange(35, 36, "SomeFilter")
src = BlankClip(length=100).ShowFrameNumber()
filtered = src.SomeFilter()
ReplaceFramesSimple(src, filtered,
\                   mappings="[10 11]
                              [15 16]
                              [20 24]
                              [30 32]
                              [35 36]")

Revision History

  • 0.4.1
    • It is now allowed for a downstream filter to request a frame out of range.
    • rfs_transform now accepts an undefined mapping string as input.
  • 0.4.0
    • Added remf, remfs, rfs, rfs_merge and rfs_transform.
  • 0.3.1
    • Fixed RemapFrames which was seriously broken because I forgot that initial clip parameters can't be optional. As a consequence, I had to rearrange RemapFrames's parameter order.
  • 0.3.0
    • Added ReplaceFramesSimple.
  • 0.2.0
    • Added RemapFramesSimple.
  • 0.1.1
    • Now retains field parity information of the remapped frames.
  • 0.1.0
    • Initial release.
Personal tools