commit a367ba62b43a69ae64dbcc1876cf01ad3dab1c50 equwal <truex@equwal.com> 2026-09-21 04:56:28 -0700 Describe how another app asks SubRead for subtitles
docs/intent-api.md | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+)
diff --git a/docs/intent-api.md b/docs/intent-api.md new file mode 100644 index 0000000..49ab55d --- /dev/null +++ b/docs/intent-api.md @@ -0,0 +1,65 @@ +# Make subtitles from another app + +A reader or an audiobook player can ask SubRead to make the `.srt` for a book, +and get the file back. The other app needs no code of SubRead and no speech +model of its own. SubRead shows its usual screen with the progress, so the user +sees that a long job runs and can stop it. + +## Ask + +```kotlin +val ask = Intent("space.subread.app.action.ALIGN").apply { + setPackage("space.subread.app") + putExtra("space.subread.extra.AUDIO", audioUri) // Uri: m4b, m4a, mp3, opus, ogg, flac, wav + putExtra("space.subread.extra.BOOK", bookUri) // Uri: epub, txt, Aozora zip + putExtra("space.subread.extra.LANGUAGE", "ja") // optional: a Whisper language code, or "auto" (the default) + // SubRead must be able to read both files: + clipData = ClipData.newRawUri("audio", audioUri).apply { addItem(ClipData.Item(bookUri)) } + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) +} +startActivityForResult(ask, REQUEST_SUBTITLES) // or an ActivityResultLauncher +``` + +Both Uris must be `content://` Uris that the calling app may grant (its own +`FileProvider`, or a document Uri for which it holds a persisted permission). +A `file://` Uri works only for a file that SubRead can read, so do not use one. + +One audio file for one book. A book in many audio files is not handled yet. + +Declare that the app looks for SubRead (Android 11 and later hide other apps +without this), in the manifest of the calling app: + +```xml +<queries> + <package android:name="space.subread.app" /> +</queries> +``` + +`ask.resolveActivity(packageManager) == null` means that SubRead is not +installed, or is older than 0.9.0. Offer the download then: +<https://github.com/equwal/subread-android/releases/latest> (also on F-Droid +and Google Play when those listings are up). + +## Answer + +`RESULT_OK`: + +| Where | What | +|---|---| +| `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 | +| `space.subread.extra.CUES` | `Int`: the number of subtitle lines | +| `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 | +| `space.subread.extra.LANGUAGE` | `String`: the language that was used | + +`RESULT_CANCELED`: the user went back, or the job failed. +`space.subread.extra.ERROR` (`String`) says why when it failed. + +The job takes about a third of the length of the audio on a mid-range device. +SubRead keeps what it has transcribed, so asking again for the same audio file +continues and does not start over. + +## The subtitles + +SubRip, UTF-8, one cue for each phrase the narrator says, times on the clock of +the audio file. The words are the book's own. A line that starts with `*` is +what the speech model heard where no text of the book could be matched.