View Full Version : make a txt file with I frames?
smok3
21st December 2011, 09:46
looking for a cli utility (maybe even ffmpeg can do that somehow?) that would take long gop mkv or mp4 AVC file and do a text file with I frame positions, like:
0
322
600
1211
..
This would be then passed as multiple loops into ffmpeg as start and length parameters (using −ss position and −t duration parameters probably) to transcode each gop into new file for editing purposes.
thanks.
ronnylov
21st December 2011, 14:52
Maybe you can get some information by using mkvinfo (obiously it will work with mkv files only).
http://forum.doom9.org/showthread.php?t=111294
It should be possible to get only I-frames out of ffmpeg but I am not sure how to get the frame numbers from this:
http://37rtm.host22.com/content/extracting-key-frames-ffmpeg
Selur
22nd December 2011, 16:22
try: http://www.multiupload.com/5ES48FJ5AJ and call it with:
FrameCounter.exe "Path to RAW H.264 file" list 2> listing.txt
should create something like:
argc 3
listing elements enabled
analysing h.264 frame count of: g:\Hybrid\test - clips\rawAVCvideo.264
Frame count analyse at 1 of 0.524775
0 : IDR (0x65)
1 : P (0x41)
2 : P (0x41)
3 : B (0x01)
4 : B (0x01)
5 : P (0x41)
6 : P (0x41)
7 : B (0x01)
8 : B (0x01)
9 : P (0x41)
10 : P (0x41)
11 : B (0x01)
12 : P (0x41)
13 : B (0x01)
14 : P (0x41)
15 : P (0x41)
16 : B (0x01)
17 : P (0x41)
18 : B (0x01)
19 : P (0x41)
20 : B (0x01)
21 : P (0x41)
22 : B (0x01)
23 : P (0x41)
24 : B (0x01)
25 : P (0x41)
26 : B (0x01)
27 : P (0x41)
28 : B (0x01)
29 : P (0x41)
30 : P (0x41)
31 : P (0x41)
32 : B (0x01)
33 : P (0x41)
34 : P (0x41)
35 : B (0x01)
36 : P (0x41)
37 : P (0x41)
38 : B (0x01)
39 : P (0x41)
40 : P (0x41)
41 : B (0x01)
42 : P (0x41)
43 : P (0x41)
44 : B (0x01)
45 : IDR (0x65)
46 : P (0x41)
47 : B (0x01)
....
418 : B (0x01)
419 : P (0x41)
420 : P (0x41)
421 : B (0x01)
422 : B (0x01)
423 : P (0x41)
424 : P (0x41)
425 : B (0x01)
426 : B (0x01)
427 : P (0x41)
428 : B (0x01)
counted:
0x01 175 times.
0x41 251 times.
0x65 3 times.
sps/pps:
0x68 3 times.
framecount: 428
Cu Selur
Ps.: basically it's a slightly modified version of my FrameCounter (http://forum.selur.de/topic12-framecounter-counting-frames-in-raw-streams-source.html) (added some output routines)
sneaker_ger
22nd December 2011, 16:55
If you don't mind the remuxing, just use mkvmerge's splitting function and set the duration as low as possible. Since it can only cut on keyframes it will create a new file for each GOP which you can in turn easily batch encode with e.g. ffmpeg.
MatLz
22nd December 2011, 17:48
You also can use avisynth with ffvideosource.
ffvideosource("yourfile")
I="I"
scriptclip("""
writefileif("yourlogfile","chr(FFPICT_TYPE)==I","current_frame")
""")
Run the script in avsinfo or vdub
smok3
22nd December 2011, 21:16
Thanks all, MatLz - that sounds promising, only this is on OSX, so avisynth doesnt make much sense there and my ffmpeg analysis brings some really weird results as well..., actually not really sure if the cli is correct; http://pastebin.com/QBePYSBQ
in the case that this would actually starting to make some sense, there is still a problem after that, since i would have to call ffmpeg for each "scene" and i assume that would be really really slow (to seek)? So i guess my best bet is just to cut the thingy based on some length, maybe 5 minutes or something like that...
MatLz
22nd December 2011, 22:38
Thanks all, MatLz - that sounds promising, only this is on OSX, so avisynth doesnt make much senseYou haven't mentioned you were on this "thing" :D
I just realized that this method can be useful for feeding x264 with a qpfile with I, P and B frames from a reference encode to test settings without affecting frametype decisions.
Gavino
23rd December 2011, 00:47
scriptclip("""
writefileif("yourlogfile","chr(FFPICT_TYPE)==I","current_frame")
""")
Note that you don't need to put WriteFileIf (or WriteFile) inside a call to ScriptClip. WriteFile[If] is itself a run-time filter (http://avisynth.org/mediawiki/Runtime_environment), like ScriptClip.
06_taro
23rd December 2011, 01:23
If you do not need to stick to cli tools, there are two good options:
Aegisub can output keyframes list of most formats/codecs as long as they can be decoded using ffms2. Just use "Video"->"Save keyframes" from the menu toolbar. ( For now official 2.1.8 build is too old to handle matroska files with header stripping, you can use this custom 2.1.9 build (http://nmm.me/5j) which uses latest ffms2 and works well with most formats and codecs. )
Aegisub generated keyframes list example:
# keyframe format v1
fps 23.976024
0
1208
1312
1355
1392
……
Also you can try VFRHelper (http://nmm.me/3z) which can not only output keyframes list but also timestamps of those keyframes. It is quite convenient when generating chapter files. It uses ffms2 too, and can also handle many codecs. Just open a video file and click "Load plugin"->"Other"->"Output timecodes of all keyframes".
VFRHelper generated keyframes list example:
0|00:00:00.000
60|00:00:02.503
178|00:00:07.424
276|00:00:11.512
396|00:00:16.517
423|00:00:17.643
……
MatLz
23rd December 2011, 02:14
@Gavino
Yeah you're right. But for my defense, iirc, it's the first time I use writefile :D
So now I can even put the I string directly :
ffvideosource("yourfile")
writefileif("yourlogfile","""chr(FFPICT_TYPE)=="I" ""","current_frame")
Selur
23rd December 2011, 06:04
Just wondering if it's about splitting an mp4 into gop sized chunks, can't this be easily done by mp4box or mkvmerge by simply activating the split option and choosing a split size of i.e. 1 MB?
smok3
23rd December 2011, 09:21
Selur, if mp4box and/or mkvmerge can split at I-frame positons that would be great. Last time i tryed something like that with mp4box did not really work well btw.
Selur
23rd December 2011, 09:24
iirc they both only split on Iframes so using a file size that is small than any gop should cause them to split every gop,.. -> it's at least worth a try :)
smok3
23rd December 2011, 10:23
sounds good, worth a try (now to find some mp4box compile for osx...)
Selur
23rd December 2011, 10:25
now to find some mp4box compile for osx...
MP4Box/GPac home is probably a good place to look: http://gpac.wp.institut-telecom.fr/downloads/gpac-nightly-builds/
Atak_Snajpera
13th January 2012, 20:45
does anybody know how to extract positions of keyframes from .ffindex file?
Iznogood
7th February 2012, 12:37
Thanks MatLz for the idea using avs. Only problem is I don't have avsinfo (at least winxp-search didn't show any results) nor vdub. Since I don't really want to install vdub again just to get a keyframelist I'd like to give avsinfo a try, but google just shows me tons of maliciouswareremoval-sites, so is there any official site for it to download?
Also thanks for the hint to VFRHelper. Would have been awesome to get the timecodes too, but since this is not working as CLI and I want to batch more than one file I can't use this, but I'll use it for single files in future.
ati_doom
2nd March 2012, 12:31
Using ffmpeg you can extract all key frames and their corresponding timecodes with the following code:
ffmpeg -vf select="eq(pict_type\,PICT_TYPE_I)" -i yourvideo.mp4 -vsync 2 -s 73x41 -f image2 thumbnails-%02d.jpeg -loglevel debug 2>&1 | grep "pict_type:I -> select:1" | cut -d " " -f 6 - > keyframe-timecodes.txt
What follows -vf in a ffmpeg command line is a Filtergraph description. The select filter selects frames to pass in output. The constant of the filter is “pict_type” and the value “PICT_TYPE_I”. In short, we are only passing key frames to the output.
-vsync 2 prevents ffmpeg to generate more than one copy for each key frame.
-f image2 writes video frames to image files. The output filenames are specified by a pattern, which can be used to produce sequentially numbered series of files. The pattern may contain the string "%d" or "%0Nd".
-loglevel debug 2 > keyframe-timecodes.txt outputs:
[select @ 0000000001A88BE0] n:0 pts:0 t:0.000000 pos:1953 interlace_type:P key:0 pict_type:I -> select:1.000000
[select @ 0000000001A88BE0] n:1 pts:40000 t:0.040000 pos:4202 interlace_type:P key:0 pict_type:P -> select:0.000000
I use “>&1 | grep "pict_type:I -> select:1" | cut -d " " -f 6 -” to output something more readable:
t:0.000000
t:1.360000
Finally, I can convert “keyframe-timecodes.txt” into a chapter navigation list and use the thumbnails to navigate the video:
<a onclick="jwplayer().seek(0); return false" href="#"><img src="thumbnails-01.jpeg"></a>
<a onclick="jwplayer().seek(1.36); return false" href="#"><img src="thumbnails-02.jpg</a>
You can see the full explanation and a demo here:
http://www.videoproductionslondon.com/blog/scene-change-detection-during-encoding-key-frame-extraction-code
Selur
2nd March 2012, 12:37
Nice didn't know that ffmpeg call. Thanks for sharing,...
btw. if the input is mkv one can also use mkvinfo to get the I frame positions:
mkvinfo --ui-language en_US -s input.mkv | grep "I Frame, Track 1"
and
ffprobe -show_frames -pretty "path to input" | grep 'pict_type\|coded_picture_number'
or similar should also work,..
Atak_Snajpera
2nd March 2012, 14:14
Instead of mkvinfo I recommend ffindex.exe (from r644 (http://code.google.com/p/ffmpegsource/issues/detail?id=73&can=1)). Now it has -k switch which gives keyframe positions in easy to read format :). Before that update I was also using mkvinfo and it is not reliable in 100%. For example mkvinfo was reporting key frame at position 1 or 2 instead of 0 in some mkvs.
Selur
2nd March 2012, 14:20
good to know, thanks for the info :)
londonmoon
7th March 2012, 01:17
Oh wow, you saved me a lot of time. It's pretty easy now that you've explained it.
smok3
6th April 2012, 09:28
similar (mediainfo, ffmpeg, x264) for OSX http://forum.doom9.org/showthread.php?p=1558710#post1558710 (experimental, unstable, ect)
(it should work with every format, output is cuted input video and bunch of logs - should be easy to adapt for certain use, like: thumbs, transcode pieces, ect. Should be easy to "port" to other *nix enviroments)
Since VFRHelper (https://github.com/SAPikachu/VFRHelper) doesn't work for me I used a Windows command line version of ati_doom (http://forum.doom9.org/showthread.php?p=1562537#post1562537)'s method:
ffmpeg.exe -i "yourvideo.mkv" -vf select="eq(pict_type\,PICT_TYPE_I)" -vsync 2 -f null NUL -loglevel debug 2>&1| for /f "tokens=4,8,9 delims=. " %d in ('findstr "pict_type:I"') do echo %d %e.%f>>"keyframe_list.txt"
(if in a .bat file: write %%d %%e %%f instead of %d %e %f)
I'm not sure if it's the best way, but it works. It's MUCH slower than ffmsindex.exe (https://github.com/FFMS/ffms2/releases), so use the latter if you don't need timestamps.
n:0 t:0.000000
n:240 t:4.004000
n:421 t:7.024000
n:671 t:11.195000
n:921 t:15.365000
n:1171 t:19.536000
n:1421 t:23.707000
n:1670 t:27.861000
n:1920 t:32.032000
n:2169 t:36.186000
n:2419 t:40.357000
n:2668 t:44.511000
n:2918 t:48.682000
n:3168 t:52.853000
n:3418 t:57.024000
n:3668 t:61.194000
n:3918 t:65.365000
n:4168 t:69.536000
n:4418 t:73.707000
n:4668 t:77.878000
nevcairiel
5th May 2015, 19:55
A better use of ffmpeg would be this, it should be much faster:
ffprobe -show_packets -print_format compact input.mkv | grep -n flags=K
You can process the output further to get the format you want.
ndjamena
6th May 2015, 00:01
In almost four years no one seems to have mentioned Open GOPs and non IDR I-Frames. Depending on what you're trying to do that distinction could be VERY important.
(Non-IDR I frames are seekable, but damage the stream if used for cutting. It wasn't long ago that MKVMerge was quite happy to cut on non-IDR frames (in MPEG2 at least), I haven't checked if that's still true.)
Overdrive80
8th May 2015, 17:02
ffvideosource("E:\Compresion.mkv")
ffinfo(framenum=true,frametype=true,cfrtime=false,vfrtime=false,varprefix = "")
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.