[Home]Filter Plugins/Filter Modfps

Capabilities

Video Audio RGB YUV YUV422 multiple instances processing type frames needed
yes no yes yes no no PRE 1

Introduction

modfps is a filter written for transcode which allows one to alter the frame rate by either dropping or cloning frames. While one can reduce the fps to any amount one can only increase the fps to at most twice the original fps.

There are two modes of operation, buffered and unbuffered, unbuffered is quick, but buffered, especially when dropping frames should look better.

For most users, modfps will need either no options, or just mode=1.

Parameters

infps, infrc are depreciated, and I can't immediately think why they might be used.

Default values are shown in [green] in square brackets.

verbose Run in verbose mode
For each frame, some information about the time, the frames sit in the stream, and whether a frame is skipped/cloned will be printed. This info is probably not useful except for debugging.

mode Mode of operation (0=fast, 1=buffered) [1]
There are two modes of operation, buffered (1) and fast (0). Buffered mode is the default and recommended mode of operation. While fast mode will get you the correct frame rate, depending on the video stream you're working with it may look very poor.

For example, if you have a 29.97fps stream recorded from your tv card, you might frequently found that it's really 23.976fps or 25.0fps, and there are just duplicate frames. If you use fast mode to convert the steam, your odds are one in 5 if you're going from 29.97 to 23.976 of randomly hitting the pattern such that the skipped frames are the duplicate frames. If you miss, you'll skip a frame with action, which gives you a big jump, and soon after that they'll be the duplicate frame. This gives one a bad headache if you try to watch to much of it on a monitor.

Unless you really need the speed, it's suggested sticking with mode 1.

buffer The number of frames to buffer (2-25) [5]
The default is perfect when going from 29.97fps to 23.976. As a note, while it might initially seem like a good idea to run with 100 buffers if you've got the RAM, note that modfps does not consider local effects when deciding which frame to skip/clone. Thus, if one were going from 29.97fps to 15fps and there were 60 frames buffered, it could decide that all of the frames that it wants to skip are the last ones, which would mean that AV could be off by 1.5 seconds.

A good formulae to decide on the number of buffers to use is: buffers = absolute value of ( input_fps/(input_fps-output_fps) )

subsample How many pixels to subsample (1-256) [32]
When calculating the difference of frames, how many pixels do we look at? If we looked at all of them, buffered mode would run slower, while not behaving too differently. The current default is to run with subsample=32 , or to say in English, to compare every 32nd pixel

clonetype How to clone frames (0-16) [0]
When cloning a frame, modfps will let one do more than a simple copy of the data. Suppose that the first cloned frame is frame 5. Frame 5 and 6 of the import steam will correspond to frame 5 and 7 of the export steam. Frame 6 of the export steam will varry based on clonetype.

Miscellaneous

Because transcode by default will buffer some (5) frames, whenever one isn't encoding an entire file (I.E. using -c -J cut or -J skip).

As of transcode 0.6.9 filters do not see frames which are not in the range of -c ... thus if one is cutting frames 1000-1500 the first frame modfps sees is 1000. As modfps buffers the frame it sets the TC_FRAME_IS_SKIPPED flag, so it won't be encoded. After it's read in the buffers it wants, it will start outputting the frames it's buffered. I.e. the first frame modfps doesn't set as skipped will be 1005 from the encoder's point of view while corresponding to frame 1000 from the import stream.

When using -c, one should add the number of buffers to the last segment, because all of the frames are offset by a bit.

I.e. if: -c 3916-13090,17493-24185,28304-42212,46777-54710 gives you the segments you want without modifying the frame rates, when you use modfps=buffers=5 (the default) you should modify the option to -c 3916-13090,17493-24185,28304-42212,46777-54715

Also of interest is that ivtc works as well with modfps as it does with decimate. While there's no real benefit to use it when transcoding from 29.97 to 23.976 fps I've seen 29.97 video which has telecine effects, except it's at 25.0 fps ... -J ivtc,modfps=buffers=7 works well in this case.

When using -J cut, cut will alter the number of audio frames skipped so that -J cut=1000-1500,modfps -f 29.97 --export_fps 23,1 will keep the AV in sync while -c wouldn't. However, again all the frames in the export are off by the number of buffers. But the effects are different from -c, so if you wanted to use -J cut="3916-13090,17493-24185,28304-42212 you would then use -J cut="3921-13095,17498-24190,28309-42217

Usage Examples

The source video of the example was recorded from a tv card, with half the height of the source (to avoid interlacing effects, and because I can't encode 640x480 realtime). Because of this, the video I get is usually either 29.97fps (10%) 23.976 (65%) 25.0 (25%). The percentages correspond to roughly how often I come upon this source. As you can see, I rarely have something that will look good without modification, and even then, decimate wouldn't always save me.

First, I do a first pass of xvid, video only.

 /usr/bin/nice -n +19 /usr/local/test/bin/transcode --print_status 5 \
               --export_fps 25.0,3 -x mplayer -J modfps=buffer=7,hqdn3d -V -i tv.avi \
               -b 64 -c 3916-13090,17493-24185,28304-42212,46777-54715 -y xvid,null \
               -j 0,8 -Y 0,-4 -B 0,39,08 -w 600 -R 1

Next, I do the 2nd pass, again, video only.

 /usr/bin/nice -n +19 /usr/local/test/bin/transcode --print_status 5 \
               --export_fps 25.0,3 -x mplayer -J modfps=buffer=7,hqdn3d -V -i tv.avi \
               -b 64 -c 3916-13090,17493-24185,28304-42212,46777-54715 -y xvid,null \
               -j 0,8 -Y 0,-4 -B 0,39,08 -w 600 -R 2 -o tmp.tv.avi

Now that I have the video, I examine audio. I've found that since commercials are much louder than TV, before I give anything to filter astat, I'll rip the raw audio. Note, that the values of -c are different for audio than they were for video.

I wish to stress: Currently, one cannot use -c with transcode and process audio and video at the same time while changing the frame rate without losing AV sync.

 /usr/bin/nice -n +19 /usr/local/test/bin/transcode --print_status 500 \
               -f 29.970 --export_fps 25.000 -u 35 -x null,auto -y null,wav \
               -m sound.tv.avi -c 3267-10919,14593-20175,23611-35212,39020-45637 -i tv.avi

Then we do a quick pass thru with filter astat.

 /usr/bin/nice -n +19 /usr/local/test/bin/transcode --print_status 500 \
               -f 23.976,1 -p sound.tv.avi -J astat=alog -u 50

Finally, I encode the audio while using passthru mode to merge it with video.

 /usr/bin/nice -n +19 /usr/local/test/bin/transcode --print_status 50 \
               -i tmp.tv.avi -o out.tv.avi -p sound.tv.avi -s `cat alog` -P1 -b 64 \
               -y raw

Please note in the above example that modfps was only used to handle changing the rate of the video, and that one must give different values to -c (as of transcode 0.6.9)

Scripts

The following scripts are what I use to calculate my cut sections which are given to transcode. I use avidemux v2 on input avi's to cut out commercials from a video stream I had recorded on tv. I could use avidemux to save the avi, however some of the sections well be reencodded, and it's a semi-slow process (taking a few minutes, meaning that it's highly interruptive) so I prefer to just have transcode take a bit longer to skip over the commercials. Instead I save the edit list, and have my encoding scripts cat the edit list thru two commands. The first gives the -c values for video, and the 2nd handles it for audio.


 #!/usr/bin/perl
 
 $numbuffers = 5;
 $i = 0;
 $argc = @ARGV;
 
 # we take one argument: the number of buffers
 if ($argv > 0){
   $numbuffers = $ARGV[0];
 }
 
 while(<STDIN>){
   if(/^Start : (\d+)/){
     # even tho initially some frames will be skipped, with newest
     # transcode, we keep the beginning where it should be, but we must
     # add 5 frames to the very last segment.
     $c[$i]{start} = 1 + $1;
     $_ = <STDIN>;
     if(/^Size : (\d+)/){
       $c[$i]{end} = $c[$i]{start}+$1;
       $i++;
     } else {
       print;
       die "ergh, we were supposed to find the end\n";
     }
   }
 }
 
 if($i > 0){
   $c[$i-1]{end} += $numbuffers ;
 } else {
   print "-c 0";
   exit -1;
 }
 
 print "-c ";
 for($j=0;$j<$i;$j++){
   print "$c[$j]{start}-$c[$j]{end}";
   if($i-1 != $j){
     print ",";
   }
 }
 print "\n";


 #!/usr/bin/perl
 
 # read from stdin the workbench
 
 $infps = 5;
 $outfps = 4;
 $argc=@ARGV;
 if ($argc>0){
   $infps=$ARGV[0];
 }
 if ($argc>1){
   $outfps = $ARGV[1];
 }
 
 use POSIX;
 $i = 0;
 while(<STDIN>){
   if(/^Start : (\d+)/){
     $c[$i]{start} = ceil((1+$1)*($outfps/$infps));
     $_ = <STDIN>;
     if(/^Size : (\d+)/){
       $c[$i]{end} = floor($c[$i]{start}+($1*$outfps/$infps));
       $i++;
     } else {
       print;
       die "ergh, we were supposed to find the end\n";
     }
   }
 }
 print "-c ";
 for($j=0;$j<$i;$j++){
   print "$c[$j]{start}-$c[$j]{end}";
   if($i-1 != $j){
     print ",";
   }
 }
 print "\n";

The first script takes one argument, the number of buffers passed to modfps, and will default to 5, like modfps. The 2nd script takes two arguments, the import_fps and the export_fps. Note that the intent of my choice of audio sections was not to get audio outside of the cutzone (possibly large noise from the very last bit of a commercial), and thus the video and audio might end up encoding a different number of frames, and thus with many cut sections, AV sync might be lost. However, these work for me ;)


Transcode Wiki | Filter Plugins | Recent Changes | Preferences
Password required to edit | View other revisions
Last edited January 1, 2005 3:14 pm by Monroe (diff)
Search: