Skip to main content
2 of 2
Typo: ffmpeg's "end" parameter is not -tt, it's -to.
zero0
  • 161
  • 1
  • 5

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.
zero0
  • 161
  • 1
  • 5