0

Example : Content of the playlist file:

(0:00:00) Abcde efgh ijk
(0:04:28) bcdea gefgh idjk
(0:17:00) qbecde efgh ijk
(0:27:40) hebcde efgh ijk
(0:35:03) Abeds esdh dfk
(0:49:16) dfhks ierkld sls
(0:58:26) dhekd sdoemc ks
(1:09:40) whdjoc dlf fg
...

I am looking for a way to slice a video by taking the -ss, -t and output file name arguments from the playlist file.

ffmpeg -ss "$1" -i "$3" -to "$2" -c copy -r 30 -c:v libx264rgb -crf 0 -preset ultrafast -c:a aac  "$4".mp4

Where the timestamp at the beginning becomes the -ss argument, the text becomes the name of the output file and the timestamp in the next line becomes the -t argument.

2 Answers 2

1

With awk:

awk -v input="bla.mp4" -v to_last="1:23:45" -F'[()]' '
  BEGIN {
    str="ffmpeg -ss \"%s\" -i \"%s\" -to \"%s\" -c copy -r 30 -c:v libx264rgb -crf 0 -preset ultrafast -c:a aac \"%s_%s.mp4\"\n"
  }
  NR>1 { 
    printf str, ss, input, $2, ++cnt, output
  }
  { ss=$2; sub(/^ /,"",$3); output=$3 }
  END {
    printf str, ss, input, to_last, ++cnt, output # print the last line
  }
' playlist

The input file is split on ( and ) into fields and field2 is read as ss or t value and field3 as output filename (with the first space character removed). You need to specify the input file for -i and the duration for the last playlist entry tlast.

Output:

ffmpeg -ss "0:00:00" -i "bla.mp4" -to "0:04:28" -c copy -r 30 -c:v libx264rgb -crf 0 -preset ultrafast -c:a aac "Abcde efgh ijk.mp4"
ffmpeg -ss "0:04:28" -i "bla.mp4" -to "0:17:00" -c copy -r 30 -c:v libx264rgb -crf 0 -preset ultrafast -c:a aac "bcdea gefgh idjk.mp4"
ffmpeg -ss "0:17:00" -i "bla.mp4" -to "0:27:40" -c copy -r 30 -c:v libx264rgb -crf 0 -preset ultrafast -c:a aac "qbecde efgh ijk.mp4"
ffmpeg -ss "0:27:40" -i "bla.mp4" -to "0:35:03" -c copy -r 30 -c:v libx264rgb -crf 0 -preset ultrafast -c:a aac "hebcde efgh ijk.mp4"
ffmpeg -ss "0:35:03" -i "bla.mp4" -to "0:49:16" -c copy -r 30 -c:v libx264rgb -crf 0 -preset ultrafast -c:a aac "Abeds esdh dfk.mp4"
ffmpeg -ss "0:49:16" -i "bla.mp4" -to "0:58:26" -c copy -r 30 -c:v libx264rgb -crf 0 -preset ultrafast -c:a aac "dfhks ierkld sls.mp4"
ffmpeg -ss "0:58:26" -i "bla.mp4" -to "1:09:40" -c copy -r 30 -c:v libx264rgb -crf 0 -preset ultrafast -c:a aac "dhekd sdoemc ks.mp4"
ffmpeg -ss "1:09:40" -i "bla.mp4" -to "1:23:45" -c copy -r 30 -c:v libx264rgb -crf 0 -preset ultrafast -c:a aac "whdjoc dlf fg.mp4"

I'm only familiar with Handbrake, let me know if something needs to be changed.

3
  • It's working. But after a test run I realised, it would be difficult to sort the files, so I would have liked it to attach a number serially to the file names so it can be easily sorted. Something like 1_<Filename>.mp4, 2_<Filename>.mp4 ... and so on. Feb 29, 2020 at 22:40
  • 1
    Number prefix added.
    – Freddy
    Feb 29, 2020 at 22:49
  • Unfortunately there was a bug I didn't see, because the last line in playlist was ... and if you remove it the last line in the output is missing. See my edit.
    – Freddy
    Mar 2, 2020 at 16:57
0

There are a number of ways to approach this, but here is one. I'll assume that the playlist is contained in playlist.txt and that the format is exactly as given (including the assumption that the filename text always consists of three whitespace separated words). If those assumptions don't quite hold, you can probably modify what is show below to suite.

$ cat -b playlist.txt | sort -nr | tail -n +2 | sort -n > playlist_starts.txt
$ cat -b playlist.txt | tail -n +2 > playlist_ends.txt
$ paste playlist_starts.txt playlist_ends.txt > playlist_intervals.txt
$ cat playlist_intervals.txt | awk '{print "ss =", $2, "t =", $7, "filename =", $3, $4, $5}'

The output is:

ss = (0:00:00) t = (0:04:28) filename = Abcde efgh ijk
ss = (0:04:28) t = (0:17:00) filename = bcdea gefgh idjk
ss = (0:17:00) t = (0:27:40) filename = qbecde efgh ijk
ss = (0:27:40) t = (0:35:03) filename = hebcde efgh ijk
ss = (0:35:03) t = (0:49:16) filename = Abeds esdh dfk
ss = (0:49:16) t = (0:58:26) filename = dfhks ierkld sls
ss = (0:58:26) t = (1:09:40) filename = dhekd sdoemc ks

You can instead construct a ffmpeg command to run using these parameters instead of just printing them out like I've done.

You can examine the intermediate files to see what each command does. Basically, the first two extract the lines corresponding to starts and ends of each clip interval. The paste command concatenates corresponding lines in each file so the result playlist_intervals.txt has one line per interval. Then the last line just extracts the parameters you want.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .