-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathffmpg_gen_chapter_data
38 lines (33 loc) · 1.32 KB
/
ffmpg_gen_chapter_data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/usr/bin/perl
# Perl translation of https://ikyle.me/blog/2020/add-mp4-chapters-ffmpeg
#
# # create e.g. chapters.txt file having format
# # h:mm:ss track name # h:mm:ss is the start time within INPUT.mp4 of the track
# # # append final line:
# # h:mm:ss END # whose h:mm:ss is the duration of INPUT.mp4)
# ffmpg_gen_chapter_data chapters.txt > chapters.ffm # run this program
# ffmpeg -i INPUT.mp4 -f ffmetadata FFMETADATAFILE
# cat FFMETADATAFILE chapters.ffm > newffm
# ffmpeg -i INPUT.mp4 -i newffm -map_metadata 1 -codec copy OUTPUT.mp4
use strict;
use warnings;
my $ffmpeg_timebase_scale = 1000;
my @chapters;
while( <> ) {
if( my($hr,$min,$sec,$title) = m"^\s*(\d+):(\d{2}):(\d{2}(?:\.\d{1,3})?)\s+(\S.*\S)\s*$" ) {
$sec += (($hr * 60) + $min) * 60;
push @chapters, { title => $title, start => int($sec * $ffmpeg_timebase_scale) };
}
}
uc($chapters[@chapters-1]->{title}) eq 'END' or die "last chapter must be named 'END', w/start time == video duration\n";
for( my $ix=0; $ix < @chapters - 1; ++$ix ) {
my $hr = $chapters[$ix];
my $end = $chapters[$ix+1]->{start} - 1;
print <<"ENDX"; # NB! _ORDER_ of the following k=v entries IS SIGNIFICANT (it's ffmpeg after all...)
[CHAPTER]
TIMEBASE=1/$ffmpeg_timebase_scale
START=$hr->{start}
END=$end
title=$hr->{title}
ENDX
}