I need to transcode a video to another one with the following properties:

  • GOP size is always fixed at a given value
  • Only IDR frames are used as key-frames (not I-slices)
  • SPS/PPS/VPS frames are repeated every time before the IDR frame.

Is there a way to do this with ffmpeg?

Also, it would be great if you can also tell me of a simple way of verifying all this (perhaps using ffprobe?).

  • Which output format? – Gyan Aug 26 '19 at 15:36
  • H.265 output format. – Elektito Aug 26 '19 at 15:39
  • As in, a raw bitstream? – Gyan Aug 26 '19 at 15:42
  • Frankly, doesn't really matter. I can fix the container if I need to, later. But the raw stream is what matters to me. – Elektito Aug 26 '19 at 15:43

Minimal command line, for a GOP size of 2 seconds:

ffmpeg -i input -force_key_frames expr:gte(t,n_forced*2) -c:v libx265 -x265-params open-gop=0:scenecut=0:repeat-headers=1 output.hevc


ffmpeg -i output.hevc -c copy -bsf:v trace_headers -f null -

After each line containing key frame e.g.,

Packet: 18115 bytes, key frame, no pts, dts 2319977, duration 40000.

You should see the VPS/SPS/PPS. The first Slice Segment Header that follows should have a NAL unit type of 20 which is IDR_N_LP.

ffprobe can't invoke bitstream filters.

| improve this answer | |
  • The seems to be working. Thanks. The verification command doesn't work for me though ("Unknown bitstream filter trace_headers"). Also, not that it's a problem, but there is a "supplemental enhancement information" NAL after VPS, SPS and PPS which wasn't there before. Could you tell me why this particular command causes that to appear? – Elektito Aug 27 '19 at 7:28
  • Oh, and also, the expr:gte(t,n_forced*2) part of the first ffmpeg command needs to be quoted. I'd suggested you edit that in the interest of the future copy-pasters! – Elektito Aug 27 '19 at 8:17
  • So maybe I was wrong. I tried this with another video and looks like it does not always work. Keyframes frequently happen before the 250 frames (10 seconds) that I set is up (I'm assuming the n_forced*2 determines GOP size and I changed it to n_forced*10). I tried adding min-keyint=250:keyint=250 to the x2675 params. No effect. I also tried the -g option of ffmpeg. Still the same thing happens. – Elektito Aug 27 '19 at 11:51
  • if your source is a container with VFR stream and/or fps < 25, then there may not be 250 frames in a 10 second interval. You can change t to n and the value to a frame distance – Gyan Aug 27 '19 at 14:40
  • The FPS I'm sure is 25 (or so ffprobe says). I'm not sure about VFR (that's variable frame rate, right?), but I think it's unlikely. I think the problem is that whatever we do libx265 seems to not honor min-keyint. Your force_key_frames option does work and it fixes my main issue, but x265 right at the beginning says that Keyframe min / max / scenecut : 126 / 250 / 0 even though I've set both min-keyint and keyint to 250. – Elektito Aug 27 '19 at 15:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.