Variable Frame Rate MP4
From SDA Knowledge Base
Contents
Introduction
This guide assumes you're comfortable with AviSynth, MeGUI and batch files or working through the command line.
What is variable frame rate? You can probably guess that a constant frame rate is where the frame rate of a video stays the same throughout its whole length. In VFR you'll have sections that have a different framerate. VFR is useful when the game you've recorded has multiple in-game framerates. For example, God of War for the PS2 outputs gameplay at full framerate while its cinematics are half framerate. MvBob is best suited for F1 while Telecide is best suited for F2.
Creating the actual VFR MP4 isn't so hard, the tedious part is setting up the AviSynth script and frame ranges. You have to look through your segment for changes in framerate and get the exact frame that this happens.
Files you'll need
Download tc2mp4 and extract the contents to your working directory. Place mp4box.exe in the same directory. Mp4box can be found in "..\MeGUI\tools\mp4box\".
Encoding the AviSynth script
To create a VFR video, you must first create the CFR version by matching the framerates. It's when you've encoded it to mp4 format that you'll use tc2mp4 to slow down or speed up specific sections in your video.
Example 1.
a=avisource("my30fpsvid.avi") b=avisource("my60fpsvid.avi") ### Match a's framerate to that of b. Avoid using numbers, if the ### framerates are even 0.000001 different, this will not work. a=a.assumefps(b) AlignedSplice(a,b) ConvertToYV12()
Since this script didn't use any Trim commands, we have to find how many frames each video has. Load each into VirtualDub(Mod), go to File -> File Information. Look at the length and take note of how many frames there are. Remember, 0 counts as a frame. So if vdub reports 100 frames in total, the frames would be 0-99.
Example 2.
This example is more complex thanks to mvbob doubling the amount of frames.
Loadplugin("C:\Program Files\DGMPGDec\DGDecode.dll") Ac3Source(MPEG2source("SEG7_5155.d2v"),"SEG7_5155_DELAY-73ms.ac3").DelayAudio(-0.073) assumetff() a=last.Trim(0,1720).mvbob() b=last.Trim(1721,4080).telecide().assumefps(a) c=last.Trim(4081,11480).mvbob() d=last.Trim(11481,12455).telecide().assumefps(a) e=last.Trim(12456,13485).mvbob() f=last.Trim(13486,16680).telecide().assumefps(a) g=last.Trim(16681,17200).mvbob() AlignedSplice(a,b,c,d,e,f,g) Lanczos4Resize(640,480) ConvertToYV12()
Encode it!
Finding the frame ranges
To calculate the frame ranges from the AviSynth script above, first find out how many there are in each set.
From Example 1, if the 30 fps video had 23490 frames, and the 60 fps video had 25211 frames, then your timecode file would be:
# timecode format v1 Assume 30 0,23489,30 23490,48700
Tip: Write down the left hand side first by incrementing from the set above, then the end frame is just the one before.
From Example 2, since MvBob is a bobbing deinterlacer, it doubles the amount of frames. Don't forget that the first number in the trim command is inclusive. So the sets are 3442,2360,14800,975,2060,3195,1040, that's 27872 frames in total.
So, timecode.txt would be:
# timecode format v1 Assume 29.970030 0,3441,59.940060 3442,5801,29.970030 5802,20601,59.940060 20602,21576,29.970030 21577,23636,59.940060 23637,26831,29.970030 26832,27871,59.940060
Setting the VFR
Your CFR encoding should be done now. Open a command line and use the following:
tc2mp4 -i myCFRvid.mp4 -t timecode.txt -o myVFRvid.mp4
tc2mp4 gets rid of any audio in your files, so keep reading..
Muxing the Audio
If you were to encode the audio based off the AviSynth scripts above, you'd get parts in the audio stream playing at an abnormal speed. Let's modify the above scripts solely to get the correct audio stream.
Example 1.
a=avisource("my30fpsvid.avi") b=avisource("my60fpsvid.avi") ### Match a's framerate to that of b. Avoid using numbers, if the ### framerates are even 0.000001 different, this will not work. #a=a.assumefps(b) a=a.changefps(b) AlignedSplice(a,b) ConvertToYV12()
To splice the videos together, they need to have the same framerate. But how do we do that without speeding up the 30 fps vid? Use the changefps command this time to match the framerate by duplicating the frames but not actually changing the pace.
Example 2.
Loadplugin("C:\Program Files\DGMPGDec\DGDecode.dll") Ac3Source(MPEG2source("SEG7_5155.d2v"),"SEG7_5155_DELAY-73ms.ac3").DelayAudio(-0.073) assumetff() a=last.Trim(0,1720).mvbob() b=last.Trim(1721,4080).telecide().assumefps(a) c=last.Trim(4081,11480).mvbob() d=last.Trim(11481,12455).telecide().assumefps(a) e=last.Trim(12456,13485).mvbob() f=last.Trim(13486,16680).telecide().assumefps(a) g=last.Trim(16681,17200).mvbob() #AlignedSplice(a,b,c,d,e,f,g) Lanczos4Resize(640,480) ConvertToYV12()
Simply comment out the AlignedSplice. What gets through is the original ac3source line.
Encode the audio in MeGUI, and mux it with the vfr video. Et voilà, you're done.