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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//! Parse a SAMI (.smi) subtitle file.
//!
//! SAMI (Synchronized Accessible Media Interchange) is a Microsoft-developed
//! subtitle format widely used in Asian markets, especially Korea and China.
//!
//! # Features
//! - HTML-like structure with `<Sync>` and `<P>` tags
//! - Multi-language support
//! - CSS styling
//!
//! # Run
//! ```sh
//! cargo run --example parse-sami-content
//! ```
use subtitler::model::SubtitleFile;
fn main() -> anyhow::Result<()> {
let content = r#"<SAMI>
<Head>
<Title>Example Subtitle</Title>
<Style Type="text/css">
<!--
.ENCC {Name: English; lang: en-US;}
-->
</Style>
</Head>
<Body>
<Sync Start=1000><P Class=ENCC>First subtitle line</P></Sync>
<Sync Start=4000><P Class=ENCC>Second subtitle line</P></Sync>
<Sync Start=7000><P Class=ENCC>Third subtitle line</P></Sync>
</Body>
</SAMI>"#;
// Parse SAMI content
let file = subtitler::sami::parse_content(content)?;
match file {
SubtitleFile::Sami(data) => {
println!("=== SAMI File Info ===");
println!("Subtitles: {}", data.subtitles.len());
if let Some(ref header) = data.header {
println!("\nHeader:\n{}", header);
}
if !data.styles.is_empty() {
println!("\nStyles:");
for (name, style) in &data.styles {
println!(" .{}: {}", name, style);
}
}
println!("\n=== Subtitles ===");
for (i, sub) in data.subtitles.iter().enumerate() {
println!(
"{}. [{:>5}ms - {:>5}ms] {}",
i + 1,
sub.start,
sub.end,
sub.text
);
}
}
_ => println!("Unexpected format"),
}
Ok(())
}