Closed GOP and Keyframes for Editable Masters
Specify closed GOP, a one-second I-frame interval, and a transcode-on-ingest so a human editor can recut generated MP4s without a render farm.
Generated MP4s look fine in a player and then refuse to cut. Drag the razor to 3.4 seconds and the NLE either reconstructs neighbouring frames or queues a render. The file is not broken. It is an open, long GOP, which is what most video pipelines emit because that is how you keep a short clip small. An editor recutting forty of those files does not have a farm. They have a timeline that should stream-copy on every trim.
The fix is three decisions made once, on ingest, not at delivery: closed GOP, an I-frame interval short enough to land near a cut, and a transcode that produces that shape before the bin is populated. Handing generated clips to a human editor already treats codec shape as one of four handoff items. This is the GOP half of that job, written so you can specify it rather than hope the model did.
Why a generated MP4 will not cut cleanly
A GOP (group of pictures) is the stretch of frames between one independently coded frame and the next. In H.264 that independent frame is an I-frame, and in a closed GOP it is an IDR: it clears the decoder's reference buffer. Every P-frame and B-frame after it is a delta against frames inside that group. Cut on the IDR and the decoder can start. Cut between I-frames and the decoder must walk forward from the previous I-frame, which is why a four-second trim on an eight-second clip can take longer than generating the clip did.
Open GOP makes that worse. B-frames at the start of a new group are allowed to look back into the previous group. Even a cut that lands on a GOP boundary still needs the previous GOP in memory. Players hide this. NLEs that try to smart-render (copy the bitstream instead of re-encoding) cannot. Premiere, Resolve, and Final Cut will either re-encode the whole clip around the cut or insert a render marker. Do that forty times and you have built a farm out of one editor's afternoon.
Two properties of generated video make this the default rather than a corner case.
The model does not know you will recut. Inference pipelines optimise for a watchable file, not a mezzanine. Long GOPs (two, four, even eight seconds between I-frames) are normal. Scene-cut detection, if it is on, places I-frames where the picture changes, not where an editor will later want a line to start.
The frame rate is not yours until you conform it. Versely timelines default to 25 fps. Most models that expose a rate offer 24, 30, or 60, not 25. A 24 fps open-GOP file dropped onto a 25 fps sequence is two problems stacked: a conform and a GOP that will not cut. Conforming 24 fps clips onto a 25 fps timeline is a separate article. Do the GOP transcode after the rate is settled, or you will encode twice.
ffprobe will tell you what you actually received. This is the check to run on one file from a batch before you spend an evening discovering the rest are the same:
ffprobe -select_streams v:0 -show_frames \
-show_entries frame=pict_type,key_frame,pts_time \
-of csv=p=0 input.mp4 | awk -F, '$2==1'
You want key_frame=1 rows at a regular interval, and pict_type=I at those times. If the first I-frame after time zero is at 2.4 seconds, and the next is at 6.1, that file is not an edit master. It is a playback file.
Closed GOP, and the I-interval that actually helps
Three numbers specify the bitstream an editor can recut. Write them on the ingest ticket so nobody has to reverse-engineer a preset later.
| Parameter | Edit master | Why |
|---|---|---|
| GOP structure | Closed (open-gop=0; IDR at the start of each group) | A cut on an I-frame does not need the previous GOP |
| I-frame interval | 1 second, or GOP size = frame rate | A cut is never more than one second from a seek point |
| Scene-cut | Off for the ingest transcode (scenecut=0) |
Interval is predictable; smart-render can trust it |
One second is the working interval for recuts, not a law of physics. YouTube's recommended upload encoding asks for a closed GOP of half the frame rate: at 25 fps that is a GOP of 12 or 13 frames, two I-frames per second. That is a delivery shape, not a bin shape. Keep two encodes in your head:
- Ingest / edit master: closed GOP, I-frame every 1.0 s (GOP size = fps). Or intra-only (ProRes 422, DNxHR, or
all-intraH.264) if the recut is heavy and disk is cheap. - Delivery: whatever the platform published. YouTube's half-rate closed GOP and Instagram's closed-GOP H.264 or HEVC are delivery recipes. They are not bin recipes.
Do not ship the ingest file to the platform and do not drop the delivery file on the timeline. The failure mode is one encode trying to be both.
For a 25 fps timeline, the ffmpeg that produces the ingest shape is:
ffmpeg -i generated.mp4 \
-c:v libx264 -profile:v high -pix_fmt yuv420p \
-x264-params "open-gop=0:scenecut=0:keyint=25:min-keyint=25" \
-movflags +faststart \
-c:a aac -ar 48000 -ac 2 \
master.mp4
keyint=25 at 25 fps is one I-frame per second. Do not add -r 25 unless the source is already 25 fps; a 24 fps generate needs the duplication conform, not a silent retime. open-gop=0 closes the group. scenecut=0 stops extra I-frames at detected cuts, so the interval stays on a grid an NLE can snap to. moov at the front is the fast-start atom that lets an editor scrub before the file has finished copying.
If the recut is surgical (dozens of trims inside an eight-second take), skip long-GOP H.264 and ingest to an intra codec. ProRes 422 or DNxHR HQ makes every frame an I-frame. The cost is disk, not a farm.
Transcode on ingest, not at the farm
The whole point of this recipe is that the expensive decode happens once, on the way into the project, instead of once per cut on the way out. "Transcode on ingest" is a folder rule, not a plugin:
- Land the generates in a
_rawfolder. Do not import them. Names should already sort by scene and shot; this step does not rename. - Pick the sequence rate first. If the timeline is 25 fps, conform 24 fps generates here, in the same ffmpeg as the GOP rewrite, so you do not bake a second generation of motion artefacts later. If the clip has a speaking mouth, do not retime picture against audio; use the duplication path from the 24-to-25 article.
- Run the closed-GOP (or intra) transcode into
_masters. One command, one preset, the whole batch. Batch rendering from a shell script is the same loop with a different-c:vblock. - Import
_mastersonly. The NLE never sees the open-GOP originals. Trims, including a section cut out of a clip and a straight trim, now smart-render or stream-copy. - Keep
_raw. If a generate is the wrong take, you still have the original to inspect. You do not re-ingest from a compressed master.
Inside Versely, a trim is an EDL instruction, not a bitstream copy. Ask the agent to trim or cut when the recut lives in the cloud editor. The 480p preview pass is free, with a short per-user cooldown, and the final export is charged once. That preview will tell you whether the edit is right. It will not rewrite the GOP of a file you are about to hand to Premiere.
After ingest, drop a cut at 1.3 s on three random masters (off the one-second grid on purpose). If the NLE throws a render bar, the GOP is still open or the interval is still too long. Fix the preset, re-run _raw → _masters, and only then let the editor in.
What this does not fix
Closed GOP will not salvage a variable-frame-rate file, a 24 fps clip on a 25 fps sequence, or an AAC track that clicks because it was 44.1 kHz against a 48 kHz picture. GOP only answers whether you can cut the bitstream without a decode. Drift against the voice is a frame-rate ticket. A pop on the last frame is a sample-rate ticket. You still assemble the scene. You just assemble from files that behave like footage.
FAQ
Does a shorter GOP cost me quality?
At a fixed CRF, more I-frames mean a larger file, not a softer picture. I-frames are bigger than P- and B-frames, so a 1-second GOP is fatter than a 4-second GOP at the same CRF. That is the ingest trade: disk for seekability. If the file size bothers you, ingest to DNxHR LB or ProRes LT, which are designed for this, rather than cranking H.264 CRF until the I-frames look like delivery.
Can I skip this if I only cut on the Versely timeline?
If the finished piece never leaves the EDL editor, you do not need an ingest GOP. The moment a human opens the same clip in Premiere, Resolve, or Final Cut, you do. A Versely reusable draft is not an XML or AAF an NLE will import.
What GOP should I use for the YouTube or Reels upload?
Not the ingest GOP. YouTube asks for a closed GOP of half the frame rate. Instagram's Graph API Reel spec wants progressive H.264 or HEVC, closed GOP, 4:2:0. Encode that from the finished timeline, once. Do not recode every source clip to the delivery GOP before the edit; you will pay twice and the editor still will not thank you.
How do I tell open GOP from closed without reading every frame?
ffprobe -show_frames as above, plus x264's log line on re-encode (open-gop=0). If you cannot re-encode, cut on a listed I-frame in the NLE. A file that still renders goes back through ingest, not through a queue at 2 a.m.