4

I have a recording (a simple, unprocessed TS from my satellite receiver, not encrypted) that has uneccessary stuff at the beginning and the ending. I want to cut out the main feature now with ffmpeg.

So I started with ffplay to get the timestamps for the beginning and the ending and crop detection:

ffplay -i "recording_xyz.ts" -vf "cropdetect=24:16:0"

This was the output for the first and the last frame I need:

[Parsed_cropdetect_0 @ 000000000625baa0] x1:0 x2:1279 y1:1 y2:718 w:1280 h:704 x:0 y:8 pts:7888683985 t:81953.624278 crop=1280:704:0:8
...
[Parsed_cropdetect_0 @ 000000000625baa0] x1:0 x2:1279 y1:1 y2:718 w:1280 h:704 x:0 y:8 pts:7888683985 t:87259.194348 crop=1280:704:0:8

The stream itself starts at timestamp 81825.820733:

Duration: 01:38:00.24, start: 81825.820733, bitrate: 12748 kb/s

With all that information, I tried to cut the desired part out (and also removing streams I don't need) and convert everything into an MKV. It turned out I don't need to crop, so I can simply copy everything:

ffmpeg -i "recording_xyz.ts" -ss 81953.0 -to 87259.0 -c:v copy -c:a copy -c:s copy -map 0:0 -map 0:3 -avoid_negative_ts 1 -reset_timestamps 1 "archive_file.mkv"

The result is an empty MKV file.

What would be the correct way to use ffmpeg to cut a specific scene identified by the timestamps out?

For reference:

ffmpeg version I'm using:

ffmpeg version N-64477-g5864069 Copyright (c) 2000-2014 the FFmpeg developers
  built on Jul  6 2014 22:10:36 with gcc 4.8.3 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx--enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-decklink --enable-zlib
    libavutil      52. 90.101 / 52. 90.101
    libavcodec     55. 68.101 / 55. 68.101
    libavformat    55. 45.100 / 55. 45.100
    libavdevice    55. 13.101 / 55. 13.101
    libavfilter     4. 10.100 /  4. 10.100
    libswscale      2.  6.100 /  2.  6.100
    libswresample   0. 19.100 /  0. 19.100
    libpostproc    52.  3.100 / 52.  3.100

ffmpeg's identification data for the original input stream:

Input #0, mpegts, from 'recording_xyz.ts':
  Duration: 01:38:00.24, start: 81825.820733, bitrate: 12748 kb/s
  Program 11110
  Program 11130
  Program 11140
    Stream #0:0[0x190a]: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p(tv, t709), 1280x720 [SAR 1:1 DAR 16:9], 50 fps, 50 tbr, 90k tbn, 100 tbc
    Stream #0:1[0x1914](deu): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 253 kb/s
    Stream #0:2[0x1915](mis): Audio: mp2 ([4][0][0][0] / 0x0004), 48000 Hz, stereo, s16p, 190 kb/s
    Stream #0:3[0x1916](deu): Audio: ac3 ([6][0][0][0] / 0x0006), 48000 Hz, stereo, fltp, 448 kb/s
    Stream #0:4[0x1917](mul): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 190 kb/s
    Stream #0:5[0x191e](deu): Subtitle: dvb_teletext ([6][0][0][0] / 0x0006)
    Stream #0:6[0x181a]: Unknown: none ([5][0][0][0] / 0x0005)

The things that appear on the console while trying to encode:

[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] non-existing PPS 0 referenced
    Last message repeated 1 times
[h264 @ 0000000002cb9c80] decode_slice_header error
[h264 @ 0000000002cb9c80] no frame!
[h264 @ 0000000002cb9c80] mmco: unref short failure
[mpegts @ 0000000002c784c0] PES packet size mismatch
    Last message repeated 3 times
[mpegts @ 0000000002c784c0] Could not find codec parameters for stream 6 (Unknown: none ([5][0][0][0] / 0x0005)): unknown codec
Consider increasing the value for the 'analyzeduration' and 'probesize' options

... stream identification data goes here (see above) ...

[matroska @ 00000000047c0980] Using AVStream.codec.time_base as a timebase hint to the muxer is deprecated. Set AVStream.time_base instead.
    Last message repeated 1 times
Output #0, matroska, to 'archive_file.mkv':
  Metadata:
    encoder         : Lavf55.45.100
    Stream #0:0: Video: h264 (H264 / 0x34363248), yuv420p, 1280x720 [SAR 1:1 DAR  16:9], q=2-31, 50 fps, 1k tbn, 90k tbc
    Stream #0:1(deu): Audio: ac3 ([0] [0][0] / 0x2000), 48000 Hz, stereo, 448 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:3 -> #0:1 (copy)
Press [q] to stop, [?] for help
frame=    0 fps=0.0 q=-1.0 size=       1kB time=00:00:00.00 bitrate=N/A

After some time, ffmpeg finishes:

video:0kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown

3 Answers 3

3

Could have several causes. Cutting without re-encoding is always error prone. Try to remux your ts first with mkvmerge with the desired streams and then try cutting that mkv with FFmpeg again using a simpler command like:

ffmpeg -i video.mkv -ss 81953 -to 87259 -c copy cut.mkv
1
  • Thanks a lot for your insight, I had multiple non-existing PPS 0 referenced when cutting without reencode, and some apps eg Adobe Premiere would not open it, until I did: ffmpeg -i media.ts -ss 0.04 -to 143.08 -c copy -f matroska - | ffmpeg -y -i - -c copy out.ts and suddenly Premiere likes it again. VLC had not a problem on any scenario though, as it probably assumed the next PPS it could encounter as PPS 0
    – Jose Alban
    Commented Sep 28, 2017 at 14:24
2

It turned out that it is quite easy to cut by the original timestamp. Let's stick with the example I've given in the question. ffplay -i recording_xyz.ts -vf "cropdetect=24:16:0" gives you the following information about the stream:

Input #0, mpegts, from 'recording_xyz.ts':
  Duration: 01:38:00.24, start: 81825.820733, bitrate: 12748 kb/s
  Program 11110
  Program 11130
  Program 11140
    Stream #0:0[0x190a]: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p(tv, t709), 1280x720 [SAR 1:1 DAR 16:9], 50 fps, 50 tbr, 90k tbn, 100 tbc
    Stream #0:1[0x1914](deu): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 253 kb/s
    Stream #0:2[0x1915](mis): Audio: mp2 ([4][0][0][0] / 0x0004), 48000 Hz, stereo, s16p, 190 kb/s
    Stream #0:3[0x1916](deu): Audio: ac3 ([6][0][0][0] / 0x0006), 48000 Hz, stereo, fltp, 448 kb/s
    Stream #0:4[0x1917](mul): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 190 kb/s
    Stream #0:5[0x191e](deu): Subtitle: dvb_teletext ([6][0][0][0] / 0x0006)
    Stream #0:6[0x181a]: Unknown: none ([5][0][0][0] / 0x0005)

Most important here is the start: 81824.820733 information from the second line. Keep this number in mind.

Now we need our desired start and stop timestamps. ffplay can be paused by the space key. Pause at the desired start and the desired end. You can "navigate" the stream by clicking with the mouse in the ffplay video window. The beginning of the stream is left, the end is at the right border of the window.

When paused, you can read the following on the console:

[Parsed_cropdetect_0 @ 000000000625baa0] x1:0 x2:1279 y1:1 y2:718 w:1280 h:704 x:0 y:8 pts:7888683985 t:81953.624278 crop=1280:704:0:8

You see again a timestamp here, marked with t:. In this example, the value is 81953.624278. Same goes for the desired end of the stream. In our example, this is 87259.194348.

With this information, you can easily calculate the values for ffmpeg's -ss and -to parameters:

  • Let b be the stream start timestamp (here 81824.820733)
  • Let s be the desired start timestamp (here 81953.624278)
  • Let e be the desired end timestamp (here 87259.194348)

The relative starting point (in seconds) is s - b = 81953.624278 - 81824.820733 = 128.803545. For the relative ending point (in seconds): e - b = 87259.194348 - 81824.820733 = 5434.373615. Convert the seconds now to the format hh:mm:ss.msec. For convenience, you might want to use this little Python script:

#!/bin/env python3

def ts_format(d: float) -> str:
    hrs = int(d)
    rest = float(d - hrs) * float(60)
    mins = int(rest)
    rest = float(rest - mins) * float(60)
    secs = int(rest)
    rest = float(rest - secs) * float(1000)
    msec = int(rest)
    return '{:02d}:{:02d}:{:02d}.{:03d}'.format(hrs, mins, secs, msec)


def main() -> bool:
    base = input('Base timestamp: ')
    starting = input('Desired start timestamp: ')
    ending = input('Desired end timestamp: ')
    start_hr = (float(starting) - float(base)) / float(3600)
    end_hr = (float(ending) - float(base)) / float(3600)
    print('Start: {:s} | End: {:s}'.format(ts_format(start_hr), ts_format(end_hr)))


if __name__ == '__main__':
    main()

With the example above, you'll receive the following output:

Start: 00:02:08.803 | End: 01:30:34.373

With this information, you can use ffmpeg:

ffmpeg -i recording_xyz.ts -ss 00:02:08.803 -to 01:30:34.373 -c:v copy -c:a copy -c:s copy -map 0:0 -map 0:3 -avoid_negative_ts 1 -reset_timestamps 1 "archive.mkv"

I tried this with several recordings, and it always worked well. It is also very easy to incorporate cropping if necessary:

ffmpeg -i recording_xyz.ts -ss 00:02:08.803 -to 01:30:34.373 -c:v libx264 -crf 18 -preset fast -tune film -vf "crop=1280:704:0:8" -c:a copy -c:s copy -map 0:0 -map 0:3 -avoid_negative_ts 1 -reset_timestamps 1 "archive.mkv"

Potential pitfalls

  • If the recording goes over midnight, you might experience a lower timestamp at the end of the stream compared to the beginning timestamp. You need to find the timestamp values around the break: The highest one before the break, and the lowest after the break. For calculating the desired end, you need to add the value at the end, the distance between the stream start and the highest value before the break and the distance between the lowest value after the break and the desired ending timestamp.
  • The method for finding your desired start and end point is very unprecise. In my humble opinion, this is OK for TV recordings.
  • The method is not suitable for removing commercials.
1

The total duration of the input is 5880 seconds long, but you are attempting to create an output starting at duration 81953 seconds.

ffmpeg should provide a warning indicating this, but perhaps it did not, or maybe you trimmed it from your output. This is one reason to provide the complete console output and not just selected segments (multiple repeating lines may be trimmed).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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