Files

134 lines
4.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# cuenorm
Any subtitle format in, one normalised cue stream out.
Part of [catena](../../README.md).
## What it does
Reads a subtitle file — SubRip, WebVTT or SubStation Alpha — and writes one
[`cue` record](../../docs/records.md#cue--one-line-of-a-transcript) per line: a start, an
end, and what was said.
The format is worked out from the content, not from the name, because a
subtitle file is named for the format somebody expected it to be in.
## When you would use it
- **At the front of anything that reads recordings.** Everything downstream
works on cues and never has to know which of the three formats a recording
arrived with.
- **Cleaning up automatic captioning.** It repeats each line across
overlapping windows, so the same sentence arrives three or four times over;
indexed as they come, every one is a separate hit for the same words at
almost the same timestamp, which buries everything else in a result list.
- **Getting markup and sound cues out of the way.** `<v Speaker>` tags,
styling, `[Music]`, `[Applause]` — none of it is speech, and a search that
matches `[Music]` matches every recording with a theme tune.
## Install
```sh
cargo install --git https://git.pumpin.online/funkpower/catena cuenorm
```
## Example
A WebVTT file with a speaker tag, a sound cue, and a repeated line:
```
$ cat episode.vtt
WEBVTT
00:00:01.000 --> 00:00:04.500
<v Host>The mill stood at the northern end of the valley,
00:00:04.500 --> 00:00:08.000
where the fall of the river was steepest and the ice came latest.
00:00:08.000 --> 00:00:11.000
[Music]
00:00:11.000 --> 00:00:15.500
Its wheel was undershot, which was wasteful,
00:00:15.000 --> 00:00:19.000
Its wheel was undershot, which was wasteful,
00:00:19.000 --> 00:00:24.000
and nobody replaced it for two hundred years.
```
```
$ cuenorm episode.vtt
{"v":1,"start":1.0,"end":4.5,"text":"The mill stood at the northern end of the valley,"}
{"v":1,"start":4.5,"end":8.0,"text":"where the fall of the river was steepest and the ice came latest."}
{"v":1,"start":11.0,"end":19.0,"text":"Its wheel was undershot, which was wasteful,"}
{"v":1,"start":19.0,"end":24.0,"text":"and nobody replaced it for two hundred years."}
```
The speaker tag is gone, `[Music]` left no cue at all, and the repeated line
became one cue spanning both — `11.0` to `19.0`, the earliest start and the
latest end.
In a pipeline:
```sh
cuenorm episode.vtt | cuepack --seconds 75 > passages.ndjson
cuenorm episode.srt | cueseg --duration 7245 > chapters.ndjson
```
## Options
| Option | Effect |
|---|---|
| `--keep-repeats` | Keep consecutive repeats instead of merging them |
| `--man` | Write this page as a manual page, in roff |
## Exit codes
| Code | Meaning |
|---|---|
| `0` | Done |
| `64` | The command line was wrong |
| `74` | The file could not be read |
Bytes that are not UTF-8 are replaced rather than refused. A subtitle file
downloaded from anywhere is as likely to be Latin-1, and a cue with one wrong
character still has its timing and most of its words.
## The formats
| Format | Recognised by |
|---|---|
| WebVTT | The `WEBVTT` line at the front |
| SubStation Alpha | A `[Script Info]` or `[Events]` section |
| SubRip | Neither of the above |
SubStation Alpha events are rows under a `Format:` line that names the
columns, so the column order is read rather than assumed. Override blocks
(`{\an8}`), line breaks (`\N`) and drawing commands are handled: a drawing
command is a shape, not speech, and reads as a string of coordinates if it is
kept.
A WebVTT cue line carries positioning settings after the end time, which are
ignored — that is also what lets an old SubRip file with screen coordinates
after its timestamps read at all.
## As a library
```rust
let cues = cuekit::merge_repeats(&cuekit::parse(&content));
for cue in &cues {
println!("{:.1}–{:.1} {}", cue.start, cue.end, cue.text);
}
```
See [`cuekit`](../cuekit/README.md) for the parsers one at a time.
## See also
- [`cuepack`](../cuepack/README.md) — cues into passages worth embedding.
- [`cueseg`](../cueseg/README.md) — cues into topic chapters.
- [`cuekit`](../cuekit/README.md) — the library this is a command over.