Skip to content

Commit aeea7d0

Browse files
committed
feat: Add test fixtures and enhance test suite for subtitle processing
- Added `already_clean.srt` fixture to test idempotency of the clean operation. - Introduced `cue_settings.vtt` fixture to validate conversion from VTT with cue settings to SRT. - Created `large.srt` fixture for testing chunking functionality with large subtitle files. - Added `latin1.srt` fixture to test handling of Latin-1 encoded subtitles. - Enhanced `run_tests.sh` to include new tests for: - Checking the output of the `check` command. - Config set/get functionality. - Idempotent clean operation on already clean files. - Conversion of VTT with cue settings to SRT. - Fixing Latin-1 encoded files to UTF-8. - Chunking functionality for large and small subtitle files. - Validation of SRT files for correct formatting. - Auto-detection of source language in translation. - Quiet and verbose flag functionality in commands.
1 parent f1367c2 commit aeea7d0

9 files changed

Lines changed: 747 additions & 78 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,4 @@ jobs:
5555
steps:
5656
- uses: actions/checkout@v4
5757
- name: Run shellcheck
58-
run: shellcheck -x -S warning subtool.sh || true
58+
run: shellcheck -x -S warning subtool.sh

CLAUDE.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# subtool - All-in-one Subtitle CLI
2+
3+
## Project Overview
4+
Single bash script (`subtool.sh`, ~2100 lines) for subtitle management: download, translate, convert, sync, clean, merge, fix, extract, embed.
5+
6+
## Architecture
7+
- **One file**: `subtool.sh` — everything is in this script
8+
- **Config**: `~/.config/subtool/config` (API keys, defaults)
9+
- **Cache**: `~/.cache/subtool/` (temp files, chunks)
10+
- **Tests**: `tests/run_tests.sh` + `tests/fixtures/`
11+
12+
## Key Subsystems
13+
14+
### Subtitle Sources (search + download)
15+
- **OpenSubtitles** API v1 (`/subtitles`, `/features`, `/download`) — requires `OPENSUBTITLES_API_KEY`
16+
- **Podnapisi** — scrapes podnapisi.net
17+
- **SubDL** — uses subdl.com API — requires `SUBDL_API_KEY`
18+
19+
Search flow: `search_all_sources()` → iterates `SOURCES` (comma-separated) → calls `search_<source>()` for each.
20+
OpenSubtitles search resolves title to IMDB ID via `/features` endpoint first, then searches by `imdb_id`.
21+
22+
### AI Translation Providers
23+
- `claude-code` (default) — calls `claude -p` CLI, no API key needed
24+
- `zai-codeplan` — Z.ai Coding Plan API
25+
- `openai`, `claude`, `mistral`, `gemini` — standard chat APIs
26+
27+
Translation uses chunking for large files (`chunk_srt()`, 250 lines per chunk).
28+
29+
### Smart Query Parsing
30+
`parse_smart_query()` extracts title, season, episode, range, year, IMDB ID from free-text input like "Die Discounter S01E03-E08".
31+
32+
## Commands
33+
`get`, `search`, `batch`, `translate`, `info`, `clean`, `sync`, `autosync`, `convert`, `merge`, `fix`, `extract`, `embed`, `config`, `check`, `providers`, `sources`
34+
35+
## CLI Flags
36+
- `--auto` — auto-select first result (skip interactive prompt)
37+
- `--dry-run` — show results without downloading
38+
- `--json` — JSON output (implies `--quiet`)
39+
- `--verbose` — debug output via `debug()` to stderr
40+
- `--quiet` — suppress informational messages
41+
42+
## Utility Functions
43+
- `api_retry()` — retry with backoff for 429/rate-limit responses
44+
- `detect_lang()` — auto-detect language from subtitle text sample
45+
- `validate_srt()` — check SRT format validity (indices, timestamps, text)
46+
- `_translate_prompt()` / `_translate_dispatch()` — shared translation logic (deduplicated)
47+
48+
## CI/CD
49+
- `.github/workflows/release.yml` — semantic-release (bumps VERSION in subtool.sh)
50+
- `.github/workflows/ci.yml` — tests
51+
- `.releaserc` + `.version-hook.sh` — version management
52+
- Homebrew tap at `~/Downloads/homebrew-tap/Formula/subtool.rb`
53+
54+
## Conventions
55+
- All output/logs via stderr (`>&2`), only data on stdout
56+
- Colors: RED/GREEN/YELLOW/BLUE/CYAN/BOLD/NC
57+
- Helper functions: `log()`, `warn()`, `err()`, `info()`, `debug()`, `header()`, `die()`
58+
- URL encoding: `urlencode()` via jq
59+
- Dependencies: `jq` (required), `ffmpeg`/`ffprobe`/`ffsubsync` (optional)
60+
61+
## GitHub
62+
- Repo: `maxgfr/subtool`
63+
- Homebrew: `maxgfr/tap/subtool`

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,23 +115,52 @@ subtool convert -f subs.ass --to srt
115115
# Merge bilingual subtitles
116116
subtool merge -f primary.srt --merge-with secondary.srt
117117

118-
# Fix broken subtitles (renumber, fix overlaps, UTF-8)
118+
# Fix broken subtitles (renumber, fix overlaps, sort by timestamp, UTF-8)
119119
subtool fix -f broken.srt
120120

121121
# Extract subtitles from video
122122
subtool extract -f video.mkv --track 0
123123

124124
# Embed subtitles into video
125125
subtool embed -f video.mkv --sub subs.srt -l fr
126+
127+
# Check environment (deps, API keys, config)
128+
subtool check
129+
```
130+
131+
## Flags
132+
133+
| Flag | Description |
134+
|---|---|
135+
| `--auto` | Auto-select first result (no interactive prompt) |
136+
| `--dry-run` | Show results without downloading |
137+
| `--json` | Output results as JSON (implies `--quiet`) |
138+
| `--verbose` | Show debug output |
139+
| `--quiet` | Suppress informational messages |
140+
141+
```bash
142+
# Auto-select first subtitle match
143+
subtool get -q "Inception" -l fr --auto
144+
145+
# Dry-run: see what would be downloaded
146+
subtool get -q "Inception" -l fr --dry-run
147+
148+
# JSON output for scripting
149+
subtool search -q "Inception" -l fr --json
150+
151+
# Verbose debug output
152+
subtool get -q "Inception" -l fr --verbose
126153
```
127154

128155
## Configuration
129156

130157
```bash
131158
subtool config # Show current config
132159
subtool config set key value # Set a config value
160+
subtool config get key # Get a config value
133161
subtool providers # List AI providers and models
134162
subtool sources # List subtitle sources
163+
subtool check # Diagnostic: deps, API keys, paths
135164
```
136165

137166
API keys are stored in `~/.config/subtool/config`:

0 commit comments

Comments
 (0)