Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 23 additions & 16 deletions .github/workflows/release-apk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ concurrency:
jobs:
publish:
if: github.ref_type == 'tag'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 360
steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -48,24 +49,33 @@ jobs:

- uses: android-actions/setup-android@v4
with:
packages: 'platform-tools platforms;android-35 build-tools;35.0.0'
packages: 'platform-tools platforms;android-35 build-tools;35.0.0 ndk;26.2.11394342'

- uses: gradle/actions/setup-gradle@v4

- name: Download and verify pinned FFmpegKit AAR
- name: Install FFmpeg source build tools
run: |
mkdir -p app/libs
curl --fail --silent --show-error --location --proto '=https' --proto-redir '=https' \
'https://repo.maven.apache.org/maven2/dev/ffmpegkit-maintained/ffmpeg-kit-https/7.1.6/ffmpeg-kit-https-7.1.6.aar' \
-o app/libs/ffmpeg-kit-https-7.1.6.aar
echo 'e80e5ee52248a3dcb1dda0524dd784fe4bbb212dcd4d575e82e15d21a002d860 app/libs/ffmpeg-kit-https-7.1.6.aar' | sha256sum --check
sudo apt-get update
sudo apt-get install --yes gettext

- name: Run unit tests and lint
run: bash gradlew --no-daemon :app:testDebugUnitTest :app:lintDebug --console=plain
- name: Build FFmpegKit from pinned sources
run: |
bash scripts/build_ffmpeg_source.sh
aar="$GITHUB_WORKSPACE/build/compliance/ffmpeg-7.1.6/ffmpeg-kit-https-7.1.6.aar"
test -s "$aar"
digest="$(sha256sum "$aar" | cut -d' ' -f1)"
printf 'CASTTRACE_FFMPEG_AAR_PATH=%s\n' "$aar" >> "$GITHUB_ENV"
printf 'CASTTRACE_FFMPEG_AAR_SHA256=%s\n' "$digest" >> "$GITHUB_ENV"

- name: Collect FFmpeg corresponding-source materials
run: python scripts/prepare_ffmpeg_compliance.py --aar "$CASTTRACE_FFMPEG_AAR_PATH"

- name: Enforce FFmpeg corresponding-source release gate
run: python scripts/verify_release_readiness.py

- name: Run unit tests and lint with the release FFmpeg AAR
run: bash gradlew --no-daemon :app:testDebugUnitTest :app:lintDebug --console=plain

- name: Prepare signing key
env:
CASTTRACE_KEYSTORE_BASE64: ${{ secrets.CASTTRACE_KEYSTORE_BASE64 }}
Expand Down Expand Up @@ -127,11 +137,6 @@ jobs:
raise SystemExit('APK version changed after tag validation.')
PY

- name: Collect FFmpeg corresponding-source materials
env:
GH_TOKEN: ${{ github.token }}
run: python scripts/prepare_ffmpeg_compliance.py

- name: Check source materials and assemble release assets
env:
TAG_NAME: ${{ github.ref_name }}
Expand All @@ -141,10 +146,11 @@ jobs:
mkdir -p build/release
version="${TAG_NAME#v}"
cp app/build/outputs/apk/release/app-release.apk "build/release/casttrace-${version}-release.apk"
cp app/build/ffmpeg/ffmpeg-kit-https-7.1.6-compatible.aar "build/release/casttrace-ffmpeg-7.1.6-compatible.aar"
git archive --format=zip --prefix=casttrace-android/ HEAD -o "build/release/casttrace-${version}-source.zip"
cp build/compliance/ffmpeg-7.1.6/casttrace-ffmpeg-7.1.6-source-materials.zip build/release/
cd build/release
sha256sum casttrace-*-release.apk casttrace-*-source.zip casttrace-ffmpeg-7.1.6-source-materials.zip > SHA256SUMS
sha256sum casttrace-*-release.apk casttrace-*-compatible.aar casttrace-*-source.zip casttrace-ffmpeg-7.1.6-source-materials.zip > SHA256SUMS

- name: Publish GitHub Release
uses: softprops/action-gh-release@v2
Expand All @@ -154,6 +160,7 @@ jobs:
fail_on_unmatched_files: true
files: |
build/release/casttrace-*-release.apk
build/release/casttrace-*-compatible.aar
build/release/casttrace-*-source.zip
build/release/casttrace-ffmpeg-7.1.6-source-materials.zip
build/release/SHA256SUMS
Expand Down
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

此记录描述源码版本,不代表已发布可下载的 APK。设备验证范围见 README。

## 0.2.14 - 未发布
## 0.2.14 - 2026-10-31

- 增加直播提醒和超火、礼物、订阅等直播事件采集能力。
- 以 Hilt 统一应用、服务、Receiver、Worker 和 ViewModel 的依赖注入。
- 拆分平台 Resolver、仓储、录制存储和录制恢复职责,保留既有调用与 Intent 契约。
- 增加录制并发、重试优先级、恢复和 Resolver 工厂的 JVM 回归测试。
- 完善开发者上手文档和带源码许可门槛的 APK 发布流程。
- 补齐 FFmpegKit 固定源码构建和对应源码材料;本地发布门槛检查通过。

## 0.2.13 - 2026-10-01

Expand All @@ -26,4 +27,3 @@
- 手机厂商后台策略、网络状态和平台接口仍可能影响自动录制。
- Mate 20 收尾期间曾观察到短会话重新开录,触发原因待进一步确认。
- 本轮长会话手机端拖动、HarmonyOS 4.2 和未充电深度待机尚未完成验收。
- FFmpeg 完整对应源码材料尚未补齐,暂不正式分发 APK/AAB。
38 changes: 38 additions & 0 deletions FFMPEG-LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# FFmpegKit License and Source Materials

## Binary used by the app

Local development uses `dev.ffmpegkit-maintained:ffmpeg-kit-https:7.1.6` from Maven Central. The AAR is excluded from Git and its SHA-256 is pinned in `app/build.gradle.kts`. Official Release builds instead compile FFmpegKit from the source commits, patches and toolchain pinned in [`third_party/ffmpeg/source-build.json`](third_party/ffmpeg/source-build.json). The Maven and source-built AARs are not claimed to be byte-for-byte identical. Both builds are LGPLv3 HTTPS variants with FFmpeg n7.1.5 and without GPL or nonfree FFmpeg components; the app packages `arm64-v8a` and `x86_64`.

The build task `prepareCompatibleFfmpeg` adjusts only ELF64 `PT_GNU_RELRO.p_memsz` when 16 KiB alignment padding extends beyond the mapped `PT_LOAD` segments at 4 KiB page granularity. This avoids Android 10 `mprotect` failures on unmapped padding. The source AAR remains unchanged; the transformation is in `app/build.gradle.kts` and is part of the application build configuration.

## License scope

The root [Apache License 2.0](LICENSE) covers CastTrace application source. It does not relicense FFmpegKit or its linked libraries. Full notices shipped with the app are under `app/src/main/assets/licenses/` and can be read offline from Settings → Open-source licenses.

The FFmpegKit build and its dependencies retain their own terms. The current native configuration identifies FFmpeg, GMP, GnuTLS, Nettle/Hogweed and libiconv on LGPL-compatible build paths. `cpu_features` and `ndk_compat` retain their upstream notices. Android zlib and MediaCodec are system libraries. The exact component versions, source commits, build options and hashes are recorded in [`third_party/ffmpeg/manifest.json`](third_party/ffmpeg/manifest.json).

## Corresponding source and release gate

An APK release includes the corresponding FFmpegKit/native-library source archives, pinned dependency source, build recipe and patches, application source/build configuration, license notices and SHA-256 checksums. The tag workflow builds the AAR from the pinned inputs, verifies its version, ABIs and native configuration, packages the source materials, and passes that same AAR to Gradle for tests and APK packaging. The policy records the exact verification scope and does not claim byte-for-byte equivalence with the separate Maven development artifact.

## Rebuilding

The pinned build uses Ubuntu 24.04, JDK 17, Android SDK Platform 35, NDK r26c and `gettext` for GnuTLS bootstrap. Reproduce it with [`scripts/build_ffmpeg_source.sh`](scripts/build_ffmpeg_source.sh), which fetches pinned commits, applies the tracked patches and writes the AAR under `build/compliance/`. Then run [`scripts/prepare_ffmpeg_compliance.py`](scripts/prepare_ffmpeg_compliance.py) and [`scripts/verify_release_readiness.py`](scripts/verify_release_readiness.py) to package and check corresponding-source materials.

```sh
./android.sh --enable-gnutls --enable-gmp \
--enable-android-media-codec --enable-android-zlib \
--disable-arm-v7a --disable-arm-v7a-neon --disable-x86
```

The source-built AAR is supplied to Gradle using `CASTTRACE_FFMPEG_AAR_PATH` and `CASTTRACE_FFMPEG_AAR_SHA256`. Gradle then creates a compatible AAR by trimming only unmapped ELF `PT_GNU_RELRO` padding that can cause `mprotect` failures on Android 10. This transformation is in the application build configuration and is included in the CastTrace source archive; the Release also publishes the resulting compatible AAR. Any native-library or transformation change requires renewed native loading, remuxing, playback and device compatibility tests.

To rebuild CastTrace for development, download and verify the pinned Maven AAR, use JDK 17 and Android SDK 35, then run the Gradle commands in [README.md](README.md). To reproduce a Release, use the source-build sequence in [RELEASING.md](RELEASING.md). A modified LGPL library can be rebuilt and relinked using the application source and build configuration included with a release. Do not use CastTrace's private signing key for modified builds.

## References

- [FFmpegKit maintained source](https://github.com/ffmpegkit-maintained/ffmpeg)
- [FFmpeg](https://github.com/FFmpeg/FFmpeg)
- [GNU LGPL v3](https://www.gnu.org/licenses/lgpl-3.0.html)
- [Release process](RELEASING.md)
135 changes: 135 additions & 0 deletions README.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# CastTrace Android

[简体中文](README.md) | English

<p align="center">
<a href="https://github.com/SRiftX/casttrace-android/actions/workflows/android-checks.yml"><img alt="Android checks" src="https://github.com/SRiftX/casttrace-android/actions/workflows/android-checks.yml/badge.svg"></a>
<a href="https://github.com/SRiftX/casttrace-android/releases"><img alt="GitHub Releases" src="https://img.shields.io/github/v/release/SRiftX/casttrace-android?display_name=tag&label=APK"></a>
<img alt="Android 8.0+" src="https://img.shields.io/badge/Android-8.0%2B-3DDC84?logo=android&logoColor=white">
<a href="LICENSE"><img alt="Apache 2.0" src="https://img.shields.io/badge/License-Apache--2.0-green"></a>
</p>

CastTrace is an Android application for monitoring live rooms and recording supported streams. It is built with Kotlin, Jetpack Compose, Room, WorkManager, Media3 and FFmpegKit. It manages room lists locally, monitors live status in the background, resumes interrupted recordings, collects supported chat messages, and plays saved videos.

This is an independently maintained Android project that takes inspiration from the platform recording approach in [StreamCap](https://github.com/ihmily/StreamCap). It is not an official StreamCap mobile client. A platform being supported upstream does not mean that CastTrace supports it.

<p align="center">
<a href="#screenshots">Screenshots</a> ·
<a href="#download">Download APK</a> ·
<a href="#features">Features</a> ·
<a href="#build-from-source">Build from source</a> ·
<a href="#developer-guide">Developer guide</a> ·
<a href="#contributing">Contributing</a>
</p>

## Screenshots

<p align="center">
<a href="screenshots/live-rooms-large-screen.png"><img src="screenshots/live-rooms-large-screen.png" height="300" alt="Live room monitoring and recording console"></a>
<a href="screenshots/live-reminders.png"><img src="screenshots/live-reminders.png" height="300" alt="Live reminder list"></a>
<a href="screenshots/settings.png"><img src="screenshots/settings.png" height="300" alt="Recording and background operation settings"></a>
</p>

## Download

Download the APK and checksums from [GitHub Releases](https://github.com/SRiftX/casttrace-android/releases). CastTrace supports Android 8.0+ on `arm64-v8a` and `x86_64`. The APK uses the established CastTrace signing identity and can update an existing installation while retaining app data. Each release also includes CastTrace source, FFmpeg corresponding-source materials, the compatible AAR and SHA-256 checksums. See [RELEASING.md](RELEASING.md) for the release procedure.

## Features

- Manage multiple rooms and import room links, shared text or batches.
- Monitor live status in the background and schedule live reminders.
- Recover from short disconnects, expired stream URLs and process restarts.
- Save FLV, HLS/TS or MP4 recordings, including long-session segments.
- Browse, seek, rename, delete, export and share saved videos.
- Capture text chat on supported platforms and export videos with chat overlays.
- Back up room lists and app settings.

Background monitoring depends on notification permission, battery policy and vendor-specific startup controls. Some devices require CastTrace to be allowed to start and run in the background.

## Platform Support

The platform catalog tracks supported, needs-review, planned and stopped entries. Current supported entry points include Huya, Douyin, Bilibili, Douyu and direct HLS/FLV URLs. Some other platforms require device, account or regional verification. Recognizing a shared link does not guarantee that a room is live or recordable. See [`PlatformCatalog.kt`](app/src/main/java/com/streamcap/mobile/platform/PlatformCatalog.kt) for the current status.

## Build from Source

Requirements:

- JDK 17
- Android SDK Platform 35 and Build Tools 35.0.0
- Android 8.0 (API 26) or newer; APKs include `arm64-v8a` and `x86_64`
- The pinned FFmpegKit 7.1.6 AAR, verified by SHA-256

The AAR is excluded from Git. Download and verify it before building:

Linux and macOS:

```bash
mkdir -p app/libs
curl --fail --silent --show-error --location --proto '=https' --proto-redir '=https' \
'https://repo.maven.apache.org/maven2/dev/ffmpegkit-maintained/ffmpeg-kit-https/7.1.6/ffmpeg-kit-https-7.1.6.aar' \
-o app/libs/ffmpeg-kit-https-7.1.6.aar
echo 'e80e5ee52248a3dcb1dda0524dd784fe4bbb212dcd4d575e82e15d21a002d860 app/libs/ffmpeg-kit-https-7.1.6.aar' | sha256sum --check
```

Windows PowerShell:

```powershell
New-Item -ItemType Directory -Path app\libs -Force | Out-Null
Invoke-WebRequest `
'https://repo.maven.apache.org/maven2/dev/ffmpegkit-maintained/ffmpeg-kit-https/7.1.6/ffmpeg-kit-https-7.1.6.aar' `
-OutFile app\libs\ffmpeg-kit-https-7.1.6.aar
$expected = 'e80e5ee52248a3dcb1dda0524dd784fe4bbb212dcd4d575e82e15d21a002d860'
$actual = (Get-FileHash app\libs\ffmpeg-kit-https-7.1.6.aar -Algorithm SHA256).Hash.ToLowerInvariant()
if ($actual -ne $expected) { throw "Unexpected FFmpegKit AAR SHA-256: $actual" }
```

Set `ANDROID_HOME` to the local SDK. If Gradle reports `Unable to establish loopback connection` on Windows, use a short writable temporary path:

```powershell
$env:ANDROID_HOME = "$env:LOCALAPPDATA\Android\Sdk"
$env:TEMP = 'C:\tmp'
$env:TMP = 'C:\tmp'
New-Item -ItemType Directory -Path $env:TEMP -Force | Out-Null
./gradlew.bat --no-daemon :app:testDebugUnitTest :app:lintDebug :app:assembleDebug
```

Linux and macOS:

```bash
bash gradlew --no-daemon :app:testDebugUnitTest :app:lintDebug :app:assembleDebug
```

The Debug APK is written to `app/build/outputs/apk/debug/app-debug.apk`. The application ID remains `com.streamcap.mobile` for compatibility with existing installations and data.

## Developer Guide

Start with [CONTRIBUTING.md](CONTRIBUTING.md). Read [ARCHITECTURE.md](ARCHITECTURE.md) before changing dependency injection, recording lifecycle or data boundaries.

Production code is under `app/src/main/java/com/streamcap/mobile/`:

- `app/`: Hilt root graph and Android entry points.
- `data/`: Room, preferences, network policy and repositories.
- `platform/`: platform identities, aliases and resolver construction.
- `service/`: background monitoring, recording coordination, recovery and publication.
- `storage/`: recording files, MediaStore, export, deletion and segment discovery.
- `ui/`: Compose screens and Hilt ViewModels.

To add a platform, update `PlatformCatalog` and add JVM tests for URL recognition, aliases and resolver selection. Preserve recording Intent actions and Room schema compatibility; database changes require a migration.

## Tests

Run the checks relevant to the change. Cross-module changes should pass:

```bash
bash gradlew --no-daemon :app:testDebugUnitTest :app:lintDebug :app:assembleDebug :app:assembleRelease
```

Instrumentation tests require a connected device or emulator. Real recording tests require an explicit authorized room ID and may create media files. Do not test rooms without permission to record them. Device test setup is documented in [CONTRIBUTING.md](CONTRIBUTING.md).

## License

Application source is licensed under [Apache License 2.0](LICENSE); see [NOTICE](NOTICE) for attribution. Third-party components retain their own licenses. FFmpegKit is an LGPLv3 build and its redistribution status is tracked separately from the application license. See [THIRD_PARTY.md](THIRD_PARTY.md) and [FFMPEG-LICENSE.md](FFMPEG-LICENSE.md).

## Contributing

Report reproducible issues through [GitHub Issues](https://github.com/SRiftX/casttrace-android/issues) and read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. Remove cookies, account details, device identifiers and private recordings from reports.
Loading