my attempt at a subtitle utility after all the existing ones I tried failed me
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
srtune/src/main.rs

133 lines
3.7 KiB

#[macro_use]
extern crate failure;
#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
use regex::Regex;
use std::path::Path;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::io;
use std::str::FromStr;
fn main() {
let argv =
clap::App::new("srtune")
.version(env!("CARGO_PKG_VERSION"))
.arg(clap::Arg::with_name("input")
.value_name("INFILE")
.required(true)
.index(1)
.help("Input file"),
)
.arg(clap::Arg::with_name("output")
.value_name("OUTFILE")
.required(true)
.index(2)
.help("Output file"),
)
.get_matches();
let inf = argv.value_of("input").unwrap();
let outf = argv.value_of("output").unwrap();
let source = read_file(inf);
let mut lines = source.lines();
let mut subs = vec![];
while let Some(x) = lines.next() {
if x.is_empty() {
continue;
}
// 236
// 00:18:01,755 --> 00:18:03,774
// (掃除機の音)
// う~ん…。
if let Ok(num) = u32::from_str(x) {
// println!("Entry {}", num);
let datesrow = lines.next().expect("expected date row");
if datesrow.contains(" --> ") {
let mut halves = datesrow.split(" --> ");
let start = parse_time(halves.next().expect("expected two halves")).expect("invalid time");
let end = parse_time(halves.next().expect("expected two halves")).expect("invalid time");
//println!("{} -> {} secs", start, end);
let mut text = vec![];
while let Some(x) = lines.next() {
if x.is_empty() {
break;
}
text.push(x);
}
let text = text.join("\n");
//println!("Lines: {}", text);
subs.push(Subtitle {
num, start, end, text
})
}
}
}
println!("Parsed {} entries.", subs.len());
//println!("{:?}", parsed);
}
struct Subtitle {
num : u32,
start: f32,
end: f32,
text: String
}
lazy_static! {
static ref DATE_RE: Regex = Regex::new(r"(\d+):(\d+):(\d+),(\d+)").unwrap();
}
fn parse_time(time : &str) -> Result<f32, ()> {
// 00:18:01,755
match DATE_RE.captures(time) {
Some(caps) => {
Ok(f32::from_str(caps.get(1).unwrap().as_str()).unwrap()*3600f32 +
f32::from_str(caps.get(2).unwrap().as_str()).unwrap()*60f32 +
f32::from_str(caps.get(3).unwrap().as_str()).unwrap()+
f32::from_str(caps.get(4).unwrap().as_str()).unwrap() * 0.001f32)
},
None => Err(())
}
}
/// Read a file to string; panics on error.
fn read_file<P: AsRef<Path>>(path: P) -> String {
let path = path.as_ref();
let mut file = File::open(path).expect(&format!("Could not open file: {:?}", path));
let mut buf = String::with_capacity(file_len(&mut file).expect("Er testing file len"));
file.read_to_string(&mut buf)
.expect(&format!("Error reading file {:?}", path));
buf
}
fn file_len(file : &mut File) -> io::Result<usize> {
let old_pos = file.seek(SeekFrom::Current(0))?;
let len = file.seek(SeekFrom::End(0))?;
// Avoid seeking a third time when we were already at the end of the
// stream. The branch is usually way cheaper than a seek operation.
if old_pos != len {
file.seek(SeekFrom::Start(old_pos))?;
}
Ok(len as usize)
}