Recently Written · git

subread-android

SubRead for Android: times an audiobook against its ebook on the device

git clone https://github.com/equwal/subread-android

Log | Files | Refs


docs/intent-api.md (3507 bytes)

1 # Make subtitles from another app
2 
3 A reader or an audiobook player can ask SubRead to make the `.srt` for a book,
4 and get the file back. The other app needs no code of SubRead and no speech
5 model of its own. SubRead shows its usual screen with the progress, so the user
6 sees that a long job runs and can stop it.
7 
8 ## Ask
9 
10 ```kotlin
11 val ask = Intent("space.subread.app.action.ALIGN").apply {
12     setPackage("space.subread.app")
13     putExtra("space.subread.extra.AUDIO", audioUri)   // Uri: m4b, m4a, mp3, opus, ogg, flac, wav
14     putExtra("space.subread.extra.BOOK", bookUri)     // Uri: epub, txt, Aozora zip
15     putExtra("space.subread.extra.LANGUAGE", "ja")    // optional: a Whisper language code, or "auto" (the default)
16     // SubRead must be able to read both files:
17     clipData = ClipData.newRawUri("audio", audioUri).apply { addItem(ClipData.Item(bookUri)) }
18     addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
19 }
20 startActivityForResult(ask, REQUEST_SUBTITLES)        // or an ActivityResultLauncher
21 ```
22 
23 Both Uris must be `content://` Uris that the calling app may grant (its own
24 `FileProvider`, or a document Uri for which it holds a persisted permission).
25 SubRead refuses every other Uri, a `file://` Uri included: SubRead would read
26 its own private files for the caller.
27 
28 One audio file for one book. A book in many audio files is not handled yet.
29 
30 Declare that the app looks for SubRead (Android 11 and later hide other apps
31 without this), in the manifest of the calling app:
32 
33 ```xml
34 <queries>
35     <package android:name="space.subread.app" />
36 </queries>
37 ```
38 
39 `ask.resolveActivity(packageManager) == null` means that SubRead is not
40 installed, or is older than 0.9.0. Offer the download then:
41 <https://github.com/equwal/subread-android/releases/latest> (also on F-Droid
42 and Google Play when those listings are up).
43 
44 ## Answer
45 
46 `RESULT_OK`:
47 
48 | Where | What |
49 |---|---|
50 | `data` | a `content://` Uri of the `.srt` (UTF-8), with `FLAG_GRANT_READ_URI_PERMISSION`. Copy the file; the grant ends with the calling activity |
51 | `space.subread.extra.CUES` | `Int`: the number of subtitle lines |
52 | `space.subread.extra.MATCH_RATE` | `Double`, 0 to 1: the share of lines whose words were found in the book. Under 0.8 usually means another edition, a translation, or the wrong language |
53 | `space.subread.extra.LANGUAGE` | `String`: the language that was used |
54 
55 `RESULT_CANCELED`: the user went back, or the job failed.
56 `space.subread.extra.ERROR` (`String`) says why when it failed.
57 
58 SubRead makes one set of subtitles at a time. An ask that arrives while a job
59 runs is refused with `RESULT_CANCELED` and an `ERROR`; the job that runs is not
60 touched. An ask with a file that is missing or is not a `content://` Uri is
61 refused the same way, before any work starts.
62 
63 The job takes about a third of the length of the audio on a mid-range device.
64 SubRead keeps what it has transcribed, so asking again for the same audio file
65 continues and does not start over.
66 
67 When the subtitles are ready in less than 3 seconds (SubRead did this audiobook
68 before), SubRead does not close by itself. The screen says why the job was so
69 fast, and a button returns to the calling app with the same `RESULT_OK` answer.
70 A screen that opens and closes at once looks like a fault.
71 
72 ## The subtitles
73 
74 SubRip, UTF-8, one cue for each phrase the narrator says, times on the clock of
75 the audio file. The words are the book's own. A line that starts with `*` is
76 what the speech model heard where no text of the book could be matched.