VideoHelp Forum
+ Reply to Thread
Page 1 of 2
1 2 LastLast
Results 1 to 30 of 31
Thread
  1. Reading through the documentation of ffmpeg and some old code I thought that it should be relatively easy to write a small key-frame accurate file cutting tool based on ffmpeg.

    basically one would do the following steps:
    1. Collect the key frame positions using ffmpeg or ffprobe
    2. let the user decide which gops to keep and which to remove
    3. use ffmpegs segment-options to a. split the content into parts and at the same time create a .ffconcat list
    4. modify the .ffconcat list to not include the unwanted gops
    5. use ffmpegs concat-demuxer to concatenate the wanted gops into a new file (and remux to the target container you want)
    6. clean up
    instead of using the segment option one could also use something like ffmepg -i "path input" -ss 00:00:01 -t 00:00:03 "path output1" -ss 00:00:05 -t 00:00:04 "path output2"... to lower the amount of overhead. (command line length restrictions might cause a problem if a lot of cuts happen,..)

    since this is doesn't seem really complicated, I wonder:
    • 'Is there some software out there that already does this?`
    • 'Did I miss some caveat?'

    I know vfr content and subtitles can't probably be processed properly by ffmpeg, but for normal files this should work, shouldn't it?

    Only real downside is that the temporary space requirement is rather large.

    -> Any thoughts? Is there an easier way to do steps 3.- 6. ?


    Cu Selur

    Ps.: may be I'll add this some time in the future to Hybrid or write a small separate tool. Looks like a easy cross-platform compatible way for cutting at key frames,...
    Quote Quote  
  2. Sounds like it would be useful if it works . Like a working version of avidemux which is buggy as hell

    One potential problem is ffmpeg doesn't distinguish between IDR frames and non-IDR "i" frames (at least it didn't a while ago, I don't know if that has changed)
    Quote Quote  
  3. One potential problem is ffmpeg doesn't distinguish between IDR frames and non-IDR "i" frames (at least it didn't a while ago, I don't know if that has changed)
    you are right that might be a problem, during the key frame detection
    Quote Quote  
  4. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    i was playing around with this exact same idea, to add a crude but workable .ts cutter to snip out any last minute sections and i needed something freeware'ish. but i don't know how to set ffmpeg to automatically always cut at the "I" frame so that there are no artifact before and/or after the cut clips. each clip would have a different i frame placement. not sure how to work that out in avc clips. but i'm still working on the add this piece to the my gui in my hdpvr_io tool. this is the code i last tested. it works fine, except for some artifacts. not sure if ffmpeg is re-encoding and causing the artifacts or that the in/out cuts are not in the best place.

    Code:
    ffmpeg -i "h:\video.ts" -ss 00:00:00 -t 00:00:02.000 -vcodec copy -acodec copy -y "h:\video_cut.ts"
    Quote Quote  
  5. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    well, the other issue i see is with a working "preview" and ability to step backword/forward per frame.
    Quote Quote  
  6. how to set ffmpeg to automatically always cut at the "I" frame so that there are no artifact before and/or after the cut clips.
    'force_key_frames' and the 'segment'-options should allow that

    well, the other issue i see is with a working "preview" and ability to step backword/forward per frame.
    • on windows: easy doable through avisynth
    • cross platform: complicated (iirc. MLT-framework offered that) and probably only achievable by doing it similar to avidemux (and ffmpegsource): 1st index the whole stream 2nd navigate through the stream using a self written navigation based on the index and libav.
      (side note: key frame stepping should be enough and should be doable with mplayer in slave mode )
    Last edited by Selur; 13th Oct 2013 at 18:34.
    Quote Quote  
  7. Or does it distinguish between IDR/i frames now with pict_type ?

    Under "select" documentation

    http://ffmpeg.org/ffmpeg-filters.html#select_002c-aselect

    ‘pict_type (video only)’the type of the filtered frame, can assume one of the following values:
    ‘I’ ‘P’ ‘B’ ‘S’ ‘SI’ ‘SP’ ‘BI’
    In the avisynth ffms2 documentation it lists


    FFPICT_TYPE The picture type of the most recently requested frame as the ASCII number of the character listed below. Use Chr() to convert it to an actual letter in avisynth. Use after_frame=true in Avisynth's conditional scripting for proper results. Only set when rffmode=0. The FFmpeg source definition of the characters:
    I: Intra
    P: Predicted
    B: Bi-dir predicted
    S: S(GMC)-VOP MPEG4
    i: Switching Intra
    p: Switching Predicted
    b: FF_BI_TYPE (no good explanation available) ?: Unknown
    I'm assuming "i" switching intra are non IDR frames , which correspond to "SI" in the ffmpeg documentation ?
    Quote Quote  
  8. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    thanks for the force_key_frames tip.

    actually, i've been suing that (trick) technique myself with avisynth in other gui projects. however, with my .ts captures, they unpredictably crash just like they do in dgavc. i had a thread about this last year i think. unless there is a special ffmpegsource version i don't know about, well, stepping bw/fw will randomly crash on my through avisynth/ffmpegsource.
    Quote Quote  
  9. @vhelp:
    a. instead of ffmpegsource I would use LWLibavVideoSource
    b. if your source is buggy (or has broken headers, which ts captures often do), it's not really a surprise when the avisynth source filter crashes

    @poisondeathray: checked some code I got in Hybrid and the comments I added to it -> Type_I should be IDR frames; and yes switching intra frames are Type_SI.
    Quote Quote  
  10. Member vhelp's Avatar
    Join Date
    Mar 2001
    Location
    New York
    Search Comp PM
    wow. thank you for the LWLibavVideoSource tip. (it took this long, between finding the correct version to get it up and running, and adding the step below to get working properly in my setup) its (video only) is flawless so far. that is, no crashes stepping bw/fw, jumping around anywhere and it loads up pretty quickly. no more (buggy) dgavc and ffmpegsource/ffms2 method for me.

    Code:
      v = "h:\499.video.hdpvr.nbc.snl.MyLeyCyrus2013.full.9Mbpts.ts"
      LoadPlugin( "C:\PLUGINS\LSMASHSource.dll" )
      LWLibavVideoSource(v, cache=True, threads=2).selectevery(2,1)
      AudioDub(last, LWLibavAudioSource(v, stream_index=1, av_sync=true))
    edit: i figured out how to get the audio working as well, now have audio/video working, nice, thanks again.
    Last edited by vhelp; 13th Oct 2013 at 21:16.
    Quote Quote  
  11. @vhelp: Happy it did work. Small warning about LWLibavVideoSource: It does like FFVideosource create an index, but it can create this index inside the RAM, problem with that is, that the index of LWLibavVideoSource is rather large, so it can kill the 3GB memory boundary of Avisynth. (-> read the L-Smash Source thread over at doom9).

    Cu Selur
    Quote Quote  
  12. Member
    Join Date
    Mar 2011
    Location
    Paris, France
    Search PM
    I'll piggy-back on this thread to ask if there's a simpler way in Windows to split an MP4 video accurately, ie. each new segment will start at a keyframe?

    Is My MP4Box GUI the best free application for this?

    Thank you.
    Quote Quote  
  13. Member racer-x's Avatar
    Join Date
    Mar 2003
    Location
    3rd Rock from the Sun
    Search Comp PM
    MpegStreamClip works great for mp4.
    Got my retirement plans all set. Looks like I only have to work another 5 years after I die........
    Quote Quote  
  14. Member
    Join Date
    Mar 2011
    Location
    Paris, France
    Search PM
    Thanks for the info.
    Quote Quote  
  15. Member
    Join Date
    Mar 2011
    Location
    Paris, France
    Search PM
    I'd still like to use ffmpeg instead, though, because it can be scripted.

    The following doesn't slice videos at keyframes, so the next slice starts looking funny (I guess it contains non-keyframes):

    Code:
    ffmpeg -ss 00:00:00 -i input.mp4 -to 01:00:00 -c copy -shortest -f mp4 Part1.mp4
    ffmpeg -ss 00:59:50 -i input.mp4  -c copy -shortest -f mp4 Part2.mp4
    Can ffmpeg be told to slice at keyframes, even if that means starting a few seconds before the time given?

    Thank you.
    Quote Quote  
  16. Have you tried, leaving out the '-shortest'? (from my point of view it seems wrong to add it in the first place, but you probably know why you used it,...)
    users currently on my ignore list: deadrats, Stears555
    Quote Quote  
  17. Member racer-x's Avatar
    Join Date
    Mar 2003
    Location
    3rd Rock from the Sun
    Search Comp PM
    Try:

    Code:
    ffmpeg -i input.mp4 -t 01:00:00 -c copy -f mp4 Part1.mp4
    ffmpeg -i input.mp4 -ss 00:59:50 -c copy -f mp4 Part2.mp4
    Got my retirement plans all set. Looks like I only have to work another 5 years after I die........
    Quote Quote  
  18. what with:
    https://www.ffmpeg.org/ffmpeg-all.html#trim
    https://www.ffmpeg.org/ffmpeg-all.html#atrim

    shortest is to stop operation when one of stream components is shorter than others (i.e. video end before audio or opposite)
    Quote Quote  
  19. shortest is to stop operation when one of stream components is shorter than others (i.e. video end before audio or opposite)
    Which you normally don't want! Since it will simply stop and thus you might end up with 'broken' streams.
    users currently on my ignore list: deadrats, Stears555
    Quote Quote  
  20. Member
    Join Date
    Mar 2011
    Location
    Paris, France
    Search PM
    Thanks much for the infos.

    Code:
    ffmpeg -i input.mp4 -ss 00:59:50 -c copy -f mp4 Part2.mp4
    Doesn't work well: The first three seconds of video is missing while audio is OK. Is it because the first keyframe starst there?

    If that's the case, how to tell ffmpeg to slice the first part at the last keyframe, and start the next part at the first keyframe?

    I think MyMP4GUIBox does just that: If you slice at, say 1hr but it's a non keyframe, it will starts earlier so as to start at a keyframe.

    As for "-shortest": I was using it by mistake thinking it meant that encoding would go faster (which doesn't make sense when just copying the video stream anyway).
    Quote Quote  
  21. Member racer-x's Avatar
    Join Date
    Mar 2003
    Location
    3rd Rock from the Sun
    Search Comp PM
    maybe it uses excessively long GOP, try instead:

    ffmpeg -i input.mp4 -ss 00:59:47 -c copy -f mp4 Part2.mp4

    see what that gets.....
    Got my retirement plans all set. Looks like I only have to work another 5 years after I die........
    Quote Quote  
  22. Member
    Join Date
    Mar 2011
    Location
    Paris, France
    Search PM
    Still NOK: The first few seconds of video are missing while audio is OK.

    I can't believe such a rich tool as ffmpeg is unable to slice at keyframes with no kung fu
    Quote Quote  
  23. Member
    Join Date
    Mar 2011
    Location
    Paris, France
    Search PM
    Thanks. Seems a lot more involved than just using a couple of options in ffmpeg.

    I guess there must be serious technical reasons for ffmpeg not having implemented this yet.
    Quote Quote  
  24. Member racer-x's Avatar
    Join Date
    Mar 2003
    Location
    3rd Rock from the Sun
    Search Comp PM
    ffmpeg works perfectly with every video I throw at it, yours is an exception, not the norm. Probably many things wrong with your source. Use MpegStreamClip to cut that mp4 on key frames then.
    Got my retirement plans all set. Looks like I only have to work another 5 years after I die........
    Quote Quote  
  25. Member
    Join Date
    Mar 2011
    Location
    Paris, France
    Search PM
    Nope, since I had the same problem with other files I tried before.

    MPEG StreamClip: "QuickTime is not installed!". No way I'm installing that POS on my computer.

    Besides, googling for "ffmpeg split keyframe" returns very complicated solutions to something that (IMHO) should be as simple as:
    Code:
    ffmpeg -i input.mp4 -onkeyframe -ss 00:59:50 -c copy -f mp4 Part2.mp4
    Looks like I'm stuck with GUI apps.

    Thank you.
    Quote Quote  
  26. Originally Posted by yetanotherlogin View Post
    Looks like I'm stuck with GUI apps.
    https://www.ffmpeg.org/ffmpeg-all.html#trim

    start_pts

    This is the same as start, except this option sets the start timestamp in timebase units instead of seconds.
    end_pts

    This is the same as end, except this option sets the end timestamp in timebase units instead of seconds.
    Quote Quote  
  27. Originally Posted by yetanotherlogin View Post
    Thanks. Seems a lot more involved than just using a couple of options in ffmpeg.

    I guess there must be serious technical reasons for ffmpeg not having implemented this yet.
    You are so right!

    I solved it: Start with:

    1
    FFPROBE
    ffprobe -skip_frame nokey -show_frames -select_streams v "Death in Paradise_BBC First HD_2017_03_01_07_20_00.ts">"Death in Paradise_BBC First HD_2017_03_01_07_20_00.txt"
    2
    ffmpeg -skip_frame nokey -i "Death in Paradise_BBC First HD_2017_03_01_07_20_00.wtv" -vf scale=640:360 -vsync 0 keyframes%01d.jpg

    3
    I wote a script in Yabasic to extract the best_effort_timestamp_time the aformentioned file and link het timestamp to the image-number write it in another file which I named edlfile.txt
    4
    to determine the cutpoints
    another script in yabasic invokes FFPlay to display the images and store the timestamps in EDL file:
    ffplay -exitonkeydown -hide_banner -loglevel quiet -loop 0 image.jpg
    5
    Final Yabasic sript to slice up the video at the cutpoints and concatenate them:
    ffmpeg1$= ffmpeg -hide_banner -stats -y -i " video in " -ss " start -t duration -map 0 -vcodec copy -acodec copy -scodec copy "vide out"
    you have to repeat this for every part.
    ffmpeg2$ = ffmpeg -loglevel quiet -hide_banner -stats -y -f concat -safe 0 -i concat.txt -vcodec copy -acodec copy -scodec copy "video out"
    Final note:
    I am not happy using ffplay to navigate the images in order to get the cutpoints since it has no slave-mode like mplayer which to my knowledge does not handle images, so I'm stuck with it so far.

    Hope this wil help and give someone the "eureka moment" and if you do please let me know.
    Quote Quote  
  28. Member Budman1's Avatar
    Join Date
    Jul 2012
    Location
    NORTHWEST ILLINOIS, USA
    Search Comp PM
    FWIW.. I am working on this feature but have not perfected it yet for some of the reasons listed here. I used the script shown to create a list for a variable bit rate MP4:

    Code:
    ffmpeg.exe" -i "C:\Users\Bud\Desktop\Various test Formats\[dp]Manjandani-1.mp4" -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>>"C:\Users\Bud\Desktop\[dp]Manjandani-1_KeyFrames.txt"
    Click image for larger version

Name:	ScreenHunter_212 Mar. 05 23.08.jpg
Views:	370
Size:	89.5 KB
ID:	40849


    This results in a list as shown below:

    Name:  ScreenHunter_213 Mar. 05 23.08.jpg
Views: 3706
Size:  41.5 KB

    The problem remaining is that the list is off by a certain amount while the actual displayed type is correct in the viewer (Potplayer) using an avisynth script and remains off about the same amount:

    Code:
    FFmpegSource2("C:\Users\Bud\Desktop\Various test Formats\[dp]Manjandani-1.mp4", atrack=-1).Crop(0,0,-0,-0)
    ScriptClip(Last, """Subtitle("[ "+Chr(FFPICT_TYPE)+" ]", size=(Height*56.0/720), align=2)""", after_frame=true)
    LanczosResize(864,368)
    Subtitle("C:\Users\Bud\Desktop\Various test Formats\[dp]Manjandani-1.mp4", x=864, y=204, font="Arial", size=24, text_color=$ff0000, align=3)
    Subtitle("This is Anamorphic video", font="Arial", size=24, text_color=$ff0000, align=5)
    ShowFrameNumber(scroll=true, x=10, y=27, font="Arial", size=24, text_color=$ff0000)
    ShowTime(x=72, y=44, font="Arial", size=24, text_color=$ff0000)
    ShowSMPTE(fps=23.976, x=68, y=61, font="Arial", size=24, text_color=$ff0000)
    )

    Click image for larger version

Name:	ScreenHunter_213 Mar. 05 23.09.jpg
Views:	266
Size:	72.3 KB
ID:	40851
    Click image for larger version

Name:	ScreenHunter_213 Mar. 05 23.19.jpg
Views:	197
Size:	64.4 KB
ID:	40852

    Seems to be a real need, at least for me, so still working on it.
    Quote Quote  
  29. 2 cents of thoughts from me:
    1. If you want to use avisynth on the whole clip, you should also use avisynth to extract the I-frame positions. (see: https://forum.doom9.org/showthread.php?p=1607578#post1607578)
    2. ShowTime will only show the correct time if your video has no a/v delay and is cfr.
    3. Instead of using ScriptClip it would be easier to use FFInfo.
    users currently on my ignore list: deadrats, Stears555
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!