commit 55f1811ff46f61256a25c01531c5c94feb907de1 truex <truex@equwal.com> 2026-09-26 17:53:42 -0700 Turn on R8, build the speech library the same on each machine, add the F-Droid listing, and set the version to 0.2.1 F-Droid asks for R8 and for a reproducible build. The ggml sources put their file paths in the library (__FILE__), and ggml records the git state of the checkout. CMakeLists.txt now maps the paths of the checkout and of the NDK to fixed names, writes / on Windows too, and turns off the git lookup. The fastlane folder gets the title, the descriptions, the icon and the changelog. The recipe names the signed APK on GitHub (Binaries) and its key, and it marks the share link and the cloud captions as NonFreeNet.
app/build.gradle.kts | 10 +++-- app/src/main/cpp/CMakeLists.txt | 18 +++++++++ fastlane/metadata/android/en-US/changelogs/4.txt | 1 + .../metadata/android/en-US/full_description.txt | 21 ++++++++++ fastlane/metadata/android/en-US/images/icon.png | Bin 0 -> 4994 bytes .../metadata/android/en-US/short_description.txt | 1 + fastlane/metadata/android/en-US/title.txt | 1 + fdroid/com.honjimaku.subrep.yml | 44 +++++++++++++++++++++ 8 files changed, 93 insertions(+), 3 deletions(-)
diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9427c2b..1244b74 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -25,8 +25,8 @@ android { // The sound of other apps can be captured from Android 10 (API 29). Older devices get the microphone. minSdk = 26 targetSdk = 36 - versionCode = 3 - versionName = "0.2.0" + versionCode = 4 + versionName = "0.2.1" // Each phone worth running Whisper on is 64-bit ARM; the speech library is built for // ARMv8.2 (see src/main/cpp/CMakeLists.txt). @@ -50,7 +50,11 @@ android { buildTypes { debug { applicationIdSuffix = ".debug" } release { - isMinifyEnabled = false + // R8 removes unused code and resources. F-Droid asks for it. The JNI + // methods of Whisper keep their names through the default rules. + isMinifyEnabled = true + isShrinkResources = true + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) if (signingReady) signingConfig = signingConfigs.getByName("release") } } diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index 4158f6a..9a2c6c9 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -12,6 +12,20 @@ endif () set(WHISPER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../third_party/whisper.cpp) +# Reproducible build: F-Droid builds this library again, on Linux and at another +# path, and compares it with the signed APK. The maps remove the paths of the +# build machine from the __FILE__ strings of ggml. -ffile-reproducible writes "/" +# in them on Windows too. An empty GIT_EXE stops ggml from recording the git state +# of the checkout, which the F-Droid scanner changes. +get_filename_component(SUBREP_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../.." ABSOLUTE) +get_filename_component(SUBREP_TOOLCHAIN_BIN "${CMAKE_C_COMPILER}" DIRECTORY) +get_filename_component(SUBREP_TOOLCHAIN_ROOT "${SUBREP_TOOLCHAIN_BIN}" DIRECTORY) +add_compile_options( + -ffile-reproducible + "-ffile-prefix-map=${SUBREP_ROOT}=." + "-ffile-prefix-map=${SUBREP_TOOLCHAIN_ROOT}=toolchain") +set(GIT_EXE "" CACHE FILEPATH "Not used: the build records no git state" FORCE) + set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) set(WHISPER_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(WHISPER_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) @@ -32,3 +46,7 @@ add_subdirectory(${WHISPER_DIR} whisper EXCLUDE_FROM_ALL) add_library(subrep_whisper SHARED whisper_jni.c) target_link_libraries(subrep_whisper PRIVATE whisper log) target_link_options(subrep_whisper PRIVATE -Wl,--gc-sections -Wl,--exclude-libs,ALL) +# No GNU build ID. The linker makes it from the debug information, and that holds the +# build folder of Gradle (.cxx/<hash>), whose name is different on each machine. +# Without it, the stripped library is the same on the F-Droid build server. +target_link_options(subrep_whisper PRIVATE -Wl,--build-id=none) diff --git a/fastlane/metadata/android/en-US/changelogs/4.txt b/fastlane/metadata/android/en-US/changelogs/4.txt new file mode 100644 index 0000000..10d4e4b --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/4.txt @@ -0,0 +1 @@ +The settings end with links to the other apps of the author. The app is smaller: R8 removes code that it does not use. F-Droid can now check that its build is the same as the signed APK on GitHub. diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt new file mode 100644 index 0000000..a5e58c8 --- /dev/null +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -0,0 +1,21 @@ +Subrep makes live captions of the sound of your device. Whisper makes them on the phone, and a share link gives them to other people. + +<b>How it works</b> +<ul> +<li>The app captures the sound of the apps on the phone (a video, a game, a browser; Android 10 or later) or the microphone.</li> +<li>Whisper, on the phone, turns the sound into captions. No sound leaves the phone.</li> +<li>The captions go to your share link on honjimaku.com, where viewers read along, and to SubRead Overlay over the player, where a tap on a word opens the dictionary.</li> +</ul> + +<b>Speech models</b> +The app downloads the model that you choose from Hugging Face (ggerganov/whisper.cpp): tiny, base (82 MB) or small (264 MB). Base keeps up on most phones. + +<b>Cloud captions (optional)</b> +Cloud captions use Whisper large-v3 turbo on DeepInfra, through subread.space. They cost hours that you buy on subread.space. The app sends only speech, and only when you choose the cloud. + +<b>Permissions</b> +<ul> +<li>Screen capture and the microphone permission: for the sound of other apps. Android asks each time the captions start.</li> +<li>Internet: for the model download, the share link and the cloud captions.</li> +<li>Notifications: for the notification with the "Stop" button.</li> +</ul> diff --git a/fastlane/metadata/android/en-US/images/icon.png b/fastlane/metadata/android/en-US/images/icon.png new file mode 100644 index 0000000..63d3527 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/icon.png differ diff --git a/fastlane/metadata/android/en-US/short_description.txt b/fastlane/metadata/android/en-US/short_description.txt new file mode 100644 index 0000000..f28393d --- /dev/null +++ b/fastlane/metadata/android/en-US/short_description.txt @@ -0,0 +1 @@ +Live captions of the sound of your phone, made on the phone by Whisper diff --git a/fastlane/metadata/android/en-US/title.txt b/fastlane/metadata/android/en-US/title.txt new file mode 100644 index 0000000..07e7258 --- /dev/null +++ b/fastlane/metadata/android/en-US/title.txt @@ -0,0 +1 @@ +Subrep diff --git a/fdroid/com.honjimaku.subrep.yml b/fdroid/com.honjimaku.subrep.yml new file mode 100644 index 0000000..1f66d3d --- /dev/null +++ b/fdroid/com.honjimaku.subrep.yml @@ -0,0 +1,44 @@ +AntiFeatures: + NonFreeNet: + en-US: The share link sends the captions to a relay on honjimaku.com, whose server + is not free software. Cloud captions, optional, send speech to subread.space + and DeepInfra. +Categories: + - Speech Recognizer +License: AGPL-3.0-only +AuthorName: equwal +WebSite: https://honjimaku.com/subrep/ +SourceCode: https://github.com/equwal/subrep-android +IssueTracker: https://github.com/equwal/subrep-android/issues +Changelog: https://github.com/equwal/subrep-android/releases +Donate: https://ko-fi.com/truex + +AutoName: Subrep + +RepoType: git +Repo: https://github.com/equwal/subrep-android.git +Binaries: https://github.com/equwal/subrep-android/releases/download/v%v/Subrep-%v.apk + +Builds: + - versionName: 0.2.1 + versionCode: 4 + commit: v0.2.1 + subdir: app + submodules: true + sudo: + - apt-get update + - apt-get install -y cmake ninja-build + gradle: + - yes + scandelete: + - third_party/whisper.cpp/bindings + - third_party/whisper.cpp/examples + - third_party/whisper.cpp/models + ndk: 29.0.14206865 + +AllowedAPKSigningKeys: 1850490335e34b5a8edc9054125f2fb276afa2905755f4cf390b02973e775e14 + +AutoUpdateMode: Version +UpdateCheckMode: Tags +CurrentVersion: 0.2.1 +CurrentVersionCode: 4 \ No newline at end of file