<p>To avoid transcoding, ffmpeg requires cutting the movie at i-frames,
since that's where it has a full image.
If you put the time with <code>-ss</code> into ffmpeg, it will start from the
latest i-frame before or equal to the requested time.</p>
<p>This suggests the strategy:</p>
<ul>
<li>Find i-frames</li>
<li>Cut out segment videos</li>
<li>Concat segment videos</li>
</ul>
<p>To find the i-frames, you can use the Python script</p>
<pre><code># ffprobe -read_intervals 1:00:00%1:00:05 -show_frames vid.mkv 2&gt;&amp;1 | ./iframe_pts.py

import datetime
import sys

pts = '0'
pts_prefix = 'pts_time='
for line in sys.stdin:
  line = line.strip()
  if line.startswith(pts_prefix):
    pts = line[len(pts_prefix):]
    continue
  if line == 'pict_type=I':
    print('%s %s' % (pts, datetime.timedelta(seconds=float(pts))))
</code></pre>
<p>Running this with short intervals will tell you where the i-frames are
and you can pick whichever one is appropriate for what you're working on.
Note that you should start on an i-frame and then stop right before an
i-frame since ffmpeg might try to pad the video otherwise.</p>
<p>To cut out the selected segments,</p>
<pre><code>ffmpeg -i vid.mkv -ss 00:15:00 -t 01:38:00 -c:a copy -c:v copy s0.mkv
</code></pre>
<p>where <code>-ss</code> is the start time and <code>-t</code> is the duration.</p>
<p>Then, you can join the segments together with the concat filter.
First, make <code>input.txt</code>.</p>
<pre><code>file 's0.mkv'
file 's1.mkv'
</code></pre>
<p>Then run ffmpeg to join the segments together.</p>
<pre><code>ffmpeg -f concat -i input.txt -c:a copy -c:v copy condensed.mkv
</code></pre>

CC BY-SA 4.0
2024-11-17T07:19:46.330Z
2024-11-17T07:19:46.330Z
scubed
<p>I have a long video with idle sections that I want to remove.
Because it is long, I don't want to have
to reecode the video, but to use stream copy.
For example if I have vid.mkv I might want to take
00:15:00 to 01:37:00 and 01:53:00 to 02:07:00
and keep only those in the resulting movie.</p>
<p>(I've found the parts of this in separate places
but thought it would be useful to have a record
of the entire process here, so answering my own question.)</p>

CC BY-SA 4.0
2024-11-17T14:40:12.953Z
Avidemux nicely displays IPB frames. I have used it to losslessly cut and trim movies to the I frames and save with its MP4v2 Muxer (occasionally I have had to revert to its MP4 Muxer if the former for some reason did not work).
wywh
<ffmpeg>
How to condense a video without reencoding with ffmpeg
scubed
# How to condense a video without reencoding with ffmpeg

(Asked by: username_0 on 2024-11-17)

I have a long video with idle sections that I want to remove.
Because it is long, I don't want to have
to reecode the video, but to use stream copy.
For example if I have vid.mkv I might want to take
00:15:00 to 01:37:00 and 01:53:00 to 02:07:00
and keep only those in the resulting movie.

(I've found the parts of this in separate places
but thought it would be useful to have a record
of the entire process here, so answering my own question.)

**Tags:** ffmpeg

> **Comments:**
> **username_1**: Avidemux nicely displays IPB frames. I have used it to losslessly cut and trim movies to the I frames and save with its MP4v2 Muxer (occasionally I have had to revert to its MP4 Muxer if the former for some reason did not work).  

---

## 1 answers

### Answer by username_0 on 2024-11-17. Score: 0

To avoid transcoding, ffmpeg requires cutting the movie at i-frames,
since that's where it has a full image.
If you put the time with -ss into ffmpeg, it will start from the
latest i-frame before or equal to the requested time.
This suggests the strategy:

Find i-frames
Cut out segment videos
Concat segment videos

To find the i-frames, you can use the Python script
# ffprobe -read_intervals 1:00:00%1:00:05 -show_frames vid.mkv 2>&1 | ./iframe_pts.py

import datetime
import sys

pts = '0'
pts_prefix = 'pts_time='
for line in sys.stdin:
  line = line.strip()
  if line.startswith(pts_prefix):
    pts = line[len(pts_prefix):]
    continue
  if line == 'pict_type=I':
    print('%s %s' % (pts, datetime.timedelta(seconds=float(pts))))

Running this with short intervals will tell you where the i-frames are
and you can pick whichever one is appropriate for what you're working on.
Note that you should start on an i-frame and then stop right before an
i-frame since ffmpeg might try to pad the video otherwise.
To cut out the selected segments,
ffmpeg -i vid.mkv -ss 00:15:00 -t 01:38:00 -c:a copy -c:v copy s0.mkv

where -ss is the start time and -t is the duration.
Then, you can join the segments together with the concat filter.
First, make input.txt.
file 's0.mkv'
file 's1.mkv'

Then run ffmpeg to join the segments together.
ffmpeg -f concat -i input.txt -c:a copy -c:v copy condensed.mkv


---

