Sync subtitles: Difference between revisions
Content added Content deleted
m (Link to Wikipedia SubRip page) |
(added Raku programming solutions) |
||
Line 1,108: | Line 1,108: | ||
{{out}} |
{{out}} |
||
<pre>Same as FreeBASIC entry.</pre> |
<pre>Same as FreeBASIC entry.</pre> |
||
=={{header|Raku}}== |
|||
===Brutal=== |
|||
<syntaxhighlight lang="raku" line># 20240621 Raku programming solution |
|||
sub MAIN() { |
|||
my @lines = $*IN.lines; |
|||
for 9, -9 -> $seconds { |
|||
say "Original subtitle adjusted by {$seconds.fmt('%+d')} seconds."; |
|||
for @lines -> $line { |
|||
if $line ~~ /(\d ** 2 ':' \d ** 2 ':' \d ** 2 ',' \d ** 3) ' --> ' (\d ** 2 ':' \d ** 2 ':' \d ** 2 ',' \d ** 3)/ { |
|||
my $start = adjust-time($0.Str, $seconds); |
|||
my $end = adjust-time($1.Str, $seconds); |
|||
my $adjusted = $line; |
|||
$adjusted ~~ s/\d ** 2 ':' \d ** 2 ':' \d ** 2 ',' \d ** 3 ' --> ' \d ** 2 ':' \d ** 2 ':' \d ** 2 ',' \d ** 3/$start ~ ' --> ' ~ $end/.Str; |
|||
say $adjusted |
|||
} else { |
|||
say $line; |
|||
} |
|||
} |
|||
say() |
|||
} |
|||
} |
|||
sub adjust-time($time, $seconds) { |
|||
my ($time_str, $milliseconds_str) = $time.split(','); |
|||
my (\hh, \mm, \ss) = $time_str.split(':')>>.Int; |
|||
my $milliseconds = $milliseconds_str.Int; |
|||
my $datetime = DateTime.new(:year, :month, :day, |
|||
:hour(hh), :minute(mm), :second(ss)); |
|||
given $datetime .= later(:seconds($seconds)) { |
|||
return sprintf('%02d:%02d:%02d,%03d',.hour,.minute,.second,$milliseconds) |
|||
} |
|||
}</syntaxhighlight> |
|||
You may [https://ato.pxeger.com/run?1=lVTdbuNEFJYQV-cpDquu7JSJ49_EdtUuCKjIBQtaKnFTCbnxJDa1Z1aecUq0aiWeg5tewEvtI_AUnIlj1ykroc6FfXzm-87PN8fz519Ndts-Pv7d6vU0_vj5H6q9wR--Xr61J_gBELHe4VdVKbjCczw5Xb519h9nZmstG0wYThOcXuCJ4ispctWxaKlsh69-bMpNKbIKKawudcUxy39rleY53uzwQ09y1rW2rddf5tbkHnvfq7NDJJPnUINJZKwhC61yffA9PODMvs7x9BR9tFILP2mz3g4maOGUIlr4ItZsnLxT6ETprNGkUNfdVJc1t09c52fdsEGZydl_aFzkZD2jef9LGzQ87zo_RjxtkyBq9oLWBj1ewJkden8YyA_7vmami-PCzEQMxT3t3COvFH8m6h77rLd7OH4Txp7A3nEPYAb3SEfzHMk4jHO386vai1yXVVUeIMY1MZqafUe9r0oaSmZ1B2CI10XB8Lqu6aHUgDS0Hp1ak4sLZyl0zzlKYBjPEx6B80xzE5KA35J5ZeoQ_M5Odzyjas1Kayl00dmY5tmO4ZFwn1hpIdvGLooJI3YpWs3tujYfXRk29dL1uCm3XIyqcM6xIruxD0hlD2pOhvNquG4bgep9Uwq9pr_Y9fN0eLDXbpBbzDElMKfLzpwuCjsSoz_J7iY6XEiPHz_7xwPXTV0vDTwWRe5-yA6OOQvCBVxSaLwxkaRAI5TCbCMZ6ILjumyUxjprzP1QlWtuLpNaOYDgwxAliqJR2NBnrpfA5Z66ykiHLpIqHMchk3qt5F21A0kfzSgq8q2stjx3AAIYYnlhOA4esGSRwBUxOZFoQE31mVhxpWWjKANACGPsmByxOImBQPuy1o2su7oAop4zZ37gjzkLNndj-G7Lm50UlG8liZrRxaO46awkMWAOA3gRBCN25LJg7sE3dMjZistW4dWuyYSQKmub1lAXMCAXwXxM9VkYx3DJG7kqifkFQNxjY-YGY8nJEc8TeMdzBpD0qIT57lMxfuq6zCXtfpJiQ8E8Fw5un0WhO8aRbkkCSyUsve8QM9zw1a18QyyvZ4Us9OZj1oIcCXwv77r7aJUJXBJPE9uLUNNwXU3f8d-xFGhOzwTzYeBGR6V6HnPDGH4pddEdcL41Z5yj5qtCyEpu6L9doipIzFssNebyTjjdzP8L Attempt This Online!] |
|||
===Less brutal=== |
|||
<syntaxhighlight lang="raku" line># 20240621 Raku programming solution |
|||
grammar SRT { # loc.gov/preservation/digital/formats/fdd/fdd000569.shtml |
|||
token TOP { ^ <subtitle>+ % \n $ } |
|||
token subtitle { <index> \n <timecode> \n <text> \n? } |
|||
token index { \d+ } |
|||
token timecode { <timestamp> ' --> ' <timestamp> } |
|||
token timestamp { \d ** 2 ':' \d ** 2 ':' \d ** 2 ',' \d ** 3 } |
|||
token text { <line>+ % \n } |
|||
token line { <-[\n]>+ } |
|||
} |
|||
sub parse-srt($srt-content) { |
|||
my $parsed = SRT.parse($srt-content); |
|||
return $parsed |
|||
?? $parsed<subtitle>.map(-> $sub { { |
|||
index => $sub<index>.Str, |
|||
start => $sub<timecode><timestamp>[0].Str, |
|||
end => $sub<timecode><timestamp>[1].Str, |
|||
text => $sub<text>.Str |
|||
}}) |
|||
!! Nil; |
|||
} |
|||
sub adjust-time($time, $seconds) { |
|||
my ($time_str, $milliseconds_str) = $time.split(','); |
|||
my (\hh, \mm, \ss) = $time_str.split(':')>>.Int; |
|||
my $milliseconds = $milliseconds_str.Int; |
|||
my $datetime = DateTime.new(:year, :month, :day, |
|||
:hour(hh), :minute(mm), :second(ss)); |
|||
given $datetime .= later(:seconds($seconds)) { |
|||
return sprintf('%02d:%02d:%02d,%03d',.hour,.minute,.second,$milliseconds) |
|||
} |
|||
} |
|||
sub adjust-subtitles(@subtitles, Int $seconds) { |
|||
@subtitles.map({ $_<start> = adjust-time($_<start>, $seconds); |
|||
$_<end> = adjust-time($_<end> , $seconds); |
|||
$_ }); |
|||
} |
|||
sub format-srt(@subtitles) { |
|||
@subtitles.map({ |
|||
$_<index> ~ "\n" ~ $_<start> ~ " --> " ~ $_<end> ~ "\n" ~ $_<text> ~ "\n" |
|||
}).join("\n"); |
|||
} |
|||
my @subtitles = parse-srt($*IN.slurp) or die; |
|||
for 9, -9 -> \N { |
|||
my @adjusted-subtitles = adjust-subtitles(@subtitles.deepmap(*.clone), N); |
|||
say "Original subtitle adjusted by {N.fmt('%+d')} seconds."; |
|||
say format-srt(@adjusted-subtitles); |
|||
}</syntaxhighlight> |
|||
You may [https://ato.pxeger.com/run?1=jVbdbts2FAZ2M4BPcZI5sJzSimRZtuUkToFtwXKTFmmAXdRdoVi0rUYiDZJ2agTei-wmF9tL9RH2FDvUv9Osm4Ao1NH3nZ_vHJH-408Z3q-fnv5a63l39OV7dyHDNA0lvLu5hUf4ARIxsxdic7KSTDG5CXUs-EkUL2IdJidzIdNQq5N5FJk_x3H8QWCrpU4TAgBa3DMOt2_eoqff4Eyt73SsEzZ5BUcw5dCCXY0qXyL0LOYR-zwxkDMdp2wmIlY8sc_arC6azAyNtGn0qmkumcahWSsdpqsJtKHbNfem7Rkrs2YO4fgYetAet19e03Lt7bnAJE3QJOZVqY3Xxmxed99P-YeJSXlHCFYPq1Aq1lVSWy28dWeCa8Z1Bx4NN91CKwNEcG56Y2cP-8hTA5RMryWvwMaE18VFaam7YKfhykItWib4Yx6munJR8TrPAUVP7Hda0j0giiV1E1h1rKHwe-fD10zGo3zxTab7AjNTeI9p5sLgathu1ykeDg7gOk5OyQ5yncPo01rprolhtcydohMMzCNVi52_-agwNLTSOEniAmJMHexB9t5WqyTWFg5CLr4hTpdLCtM0xZtSFdLQSvS43ZlM7CuuS85eAMN4HnAPHIWaGZcI_AmXtyYPzh6s8ZaFmK25ximOxDJfwzgKtxT2BHzhGi_FWlrLZYciO-Zrzaw0NQ95GhbWkte4iDc4xXUW9jkkuJZWgVRWpWanGqpiKtVKxlzPrfaR04vG1Y0eOV7UprZJgdp5dGrnXuieGFlPqy-m6GQ50cp6XS0poGTP-1q_zmb_EVofz7L5naCWe2NR2hujcfqigojEOZ6YWXzuIbf_Dw__0Zl6pNFDUXm-8WabRV3Uv1RZRsWUio31dzic8kP8V9ePpmxjLKxZ7k1YvvPmlqwHHfuTiLllnvO0cDTryKhGYzs7vrq2VbKWqw4ICVHMTgnBCiCg0A0Ao06vqw_vda4ii7pNZ9_otB0xtjKFHtuzRHCGM3udS63CLRy-kXhW8TCpD5gyANxt4fHanqf4SR69itqdHRSdsg8rflPorzMzlecnZ3GAPn357m-XOM7YcceeS33fyVQtDAPq9YfkEqcc7sxQCw7mm1UQLgQleslgHkulAc9fc0gk8ZxlCSibAOmRyovv-w23_R513IBcZtRZiJ9k7kktbdvGJX52iXhItkTgg2x4BbYRyYZFNiEeqXy5_X7TuUeDYUBukcmQhHulyT7kM9yfhVQYgZA-aWKbZJ-OghFBUJbWXIo0z4sQv-QMaM_rNTlDOnBG5OcNk1vsJoWZQGqIZ4ViprIYxSADUoGHntdg-w71Bi75EfebcMbEWsHtVoacCxWu5dpQh6RCDr1Bk9qj_dGIXDIpZjEyDwgZldgRdbym5GgYDQJywyJKSFCiAtpz6mR6Y8ehDmr3VvAFOnMdUph71O87TRzqFgTkSvG2ziqEEBZsdi8ukOWWrD7tu4Mma4iGgPwiHoAlimHnOVwhTyPb9fHHBv7y6t7gIR5zMN0zznqk4vp7qboudfoj8musl3mDo43pcYRH7WzJRSIWeIRcgVqimPcQa4jEA7fzmf8H Attempt This Online!] |
|||
=={{header|Rust}}== |
=={{header|Rust}}== |