improve help text, add duration clipping

automove
Ondřej Hruška 5 years ago
parent b904965e6a
commit 3f1b1c019b
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 53
      src/main.rs

@ -22,24 +22,30 @@ fn main() {
let argv = let argv =
clap::App::new("srtune") clap::App::new("srtune")
.version(env!("CARGO_PKG_VERSION")) .version(env!("CARGO_PKG_VERSION"))
.about("Modify a .srt file to match a video. Input and output can be a file or stream, \ .about("\
so you pipe multiple invocations to create more complex operations. However, a single \ 'srtune' helps you edit a .srt file to match a video. Input and output can be either a file, or a stream, \
so you can pipe multiple invocations to create more complex operations. However, a single \
invocation should suffice in most cases.\n\ invocation should suffice in most cases.\n\
\n\ \n\
Times are specified with colons and always include seconds (HH:MM:SS, MM:SS, 0:SS). \ Times are specified with colons (required) and always include seconds (HH:MM:SS, MM:SS, 0:SS, :SS). \
Decimal point can be either period or comma, so times can be copied directly from the \ Decimal point in the seconds part, if needed, can be either a period or a comma; times can be copied from the \
.srt file. Numbers without colons are assumed to be subtitle indices.\n\ .srt file. Numbers without colons are assumed to be subtitle indices.\n\
\n\ \n\
The tool can be used iteratively, adjusting the invocation until the generated \ The tool can be used iteratively, adjusting the invocation until the generated \
subtitle file matches the audio track. As such, times accepted by its parameters \ subtitle file matches the audio track. You can reload the file in VLC by dragging it \
are, by default, the ones seen in the output file (after shifts and moving), while \ onto the player window. To make this work, subtitle times specified in arguments are the \
indices are those from the input file.\n\ ones seen in the output file (after shifts and moving), while entry indices are those from the input file.\n\
\n\
Using indices makes it easier to specify a subtitle to alter, but it is tied to the one .srt file. \
Times are harder to write, but the one configuration will work for any locatization or variant of the file,\
so long as it is intended for the same version of the movie. Enable debug logging with '-v' to see times \
you can use in place of indices.
\n\ \n\
Indices are normally not renumbered, so the output file can be used as a reference \ Indices are normally not renumbered, so the output file can be used as a reference \
for both times and indices. The flag '--renumber' will give each output entry a new \ for both times and indices when you work out the right set of arguments. The flag '--renumber' \
sequential number. Please note that, once renumbered, the indices in the output file \ will give each output entry a new sequential number. Please note that, once renumbered, \
should no longer be used in the command invocation, as there can be a mismatch. They \ the indices in the output file should no longer be used in the command invocation, \
can be used when piped into a new process, of course. as there can be (and often will be) differences from the original file.\
") ")
.arg(clap::Arg::with_name("input") .arg(clap::Arg::with_name("input")
.value_name("INFILE") .value_name("INFILE")
@ -210,7 +216,6 @@ fn main() {
} }
None => (/* no automoves */) None => (/* no automoves */)
} }
debug!("Automove: {:?}", automove);
let inf = argv.value_of("input"); let inf = argv.value_of("input");
let outf = argv.value_of("output"); let outf = argv.value_of("output");
@ -359,11 +364,13 @@ enum AutoMoveTag {
ByIndex(u32, SubInstant) ByIndex(u32, SubInstant)
} }
#[derive(Debug,Default,Clone,Copy)] #[derive(Debug,Default,Clone)]
struct IterState { struct IterState {
start_time : Option<SubInstant>, start_time : Option<SubInstant>,
renumber_i : u32, renumber_i : u32,
timeline_head : SubInstant, timeline_head : SubInstant,
/// Queue last item for duration clipping
queued : Option<Subtitle>,
} }
fn transform_subtitles<'a>(mut lines : Box<dyn SubsInput + 'a>, mut outfile : Box<dyn SubsOutput + 'a>, mut opts : TransformOpts) { fn transform_subtitles<'a>(mut lines : Box<dyn SubsInput + 'a>, mut outfile : Box<dyn SubsOutput + 'a>, mut opts : TransformOpts) {
@ -443,11 +450,8 @@ fn transform_subtitles<'a>(mut lines : Box<dyn SubsInput + 'a>, mut outfile : Bo
subtitle.dur *= opts.durscale; subtitle.dur *= opts.durscale;
// TODO prevent durations overlap (will need to buffer one entry)
let would_be_shifted_start = subtitle.start + opts.shift; let would_be_shifted_start = subtitle.start + opts.shift;
// TODO use drain_filter when stable
let mut to_drop = vec![]; let mut to_drop = vec![];
for (i, amove) in opts.automove.iter().enumerate() { for (i, amove) in opts.automove.iter().enumerate() {
match amove { match amove {
@ -502,7 +506,17 @@ fn transform_subtitles<'a>(mut lines : Box<dyn SubsInput + 'a>, mut outfile : Bo
istate.renumber_i += 1; istate.renumber_i += 1;
subtitle.num = istate.renumber_i; subtitle.num = istate.renumber_i;
} }
outfile.emit(subtitle);
if let Some(mut q) = istate.queued.take() {
if q.start + q.dur > subtitle.start {
let clipped = subtitle.start - q.start;
debug!("Clipping duration of #{} ({}) to avoid overlap: {} -> {}", q.num, q.start, q.dur, clipped);
q.dur = clipped;
}
outfile.emit(q);
}
istate.queued = Some(subtitle);
} }
} }
Err(e) => { Err(e) => {
@ -514,6 +528,11 @@ fn transform_subtitles<'a>(mut lines : Box<dyn SubsInput + 'a>, mut outfile : Bo
} }
} }
} }
// emit the last entry
if let Some(q) = istate.queued.take() {
outfile.emit(q);
}
} }
//region Time types //region Time types

Loading…
Cancel
Save