Skip to content
tribixbitePublic

About

Swiss-army knife for embeddable media on Android — animated WebP converter, image compressor (WebP/JPEG/PNG/AVIF), OG metadata inspector, anonymous file uploader

Resources

Stars

8 stars

Watchers

0 watching

Forks

Repository files navigation

Android API 26+ Kotlin Compose License

Release Build Downloads Size

Embeddy

The Swiss-army knife for embeddable media on Android.

Convert videos and GIFs to platform-ready animated WebP, compress images to WebP/JPEG/PNG/AVIF, inspect Open Graph and social embed metadata, and upload files to anonymous hosts — all from one app with a clean Material 3 dark-mode UI.

Download

Download

Every push to main triggers a CI build that produces split-ABI APKs:

ABI Best for
arm64-v8a Modern phones (Pixel, Samsung Galaxy S/A series, OnePlus)
armeabi-v7a Older 32-bit ARM devices
x86_64 Emulators, Chromebooks
universal Any device (larger download)

Features

Convert — Animated WebP from video, GIF or animated WebP

  • Adaptive quality algorithm — starts at target quality, steps down until file fits the size limit
  • Platform presets with tuned parameters:
    • Discord — 10 MB / 720p / 12 fps
    • Telegram — 256 KB / 512px / 30 fps (sticker-ready)
    • Slack — 5 MB / 640px / 12 fps
    • Custom — full manual control
  • Animated WebP input — frames are decoded in-app by splitting the RIFF container, because the bundled FFmpeg cannot demux the format
  • Trim to a range, or stitch several segments together
  • Lanczos downscaling, optional text sharpening (unsharp filter), denoise, dithering
  • Exact output dimensions with centre-crop, or scale to a maximum
  • 3-second preview clip before committing to a full encode
  • Real-time progress with quality-step feedback
  • Share/Save output directly from the result card
  • Accepts shared media via Android intent filters (video, GIF, animated WebP)

Inspect — Social embed metadata viewer

  • Fetches and parses Open Graph, Twitter Card, and general <meta> tags
  • Discord/Slack-style live embed preview card
  • Expandable tag sections with one-tap copy
  • Extracts favicon, canonical URL, charset, theme-color, robots, generator
  • Powered by Jsoup for robust HTML parsing

Upload — Anonymous file hosting

  • Upload to 0x0.st (512 MB) or catbox.moe (200 MB)
  • EXIF stripping — removes GPS, camera info, artist, serial numbers before upload
  • Determinate progress bar with chunked streaming (no full-file memory buffering)
  • Copy URL or share result instantly

Squoosh — Still image compression

  • Output formats: WebP, JPEG, PNG, AVIF
  • AVIF encoding via avif-coder (libaom, speed 6 — Squoosh.app equivalent)
  • Quality slider (1–100) for lossy formats
  • Lossless mode for WebP and AVIF
  • Max dimension scaling with efficient inSampleSize subsampling
  • Before/after size comparison with savings percentage
  • Image preview of compressed output

Architecture

app.embeddy
├── conversion/          # FFmpeg-kit animated WebP pipeline
│   ├── ConversionEngine # Adaptive quality loop with callbackFlow
│   ├── ConversionConfig # Mutable settings from presets
│   └── Preset           # Discord, Telegram, Slack, Custom
├── inspect/
│   └── MetadataEngine   # Jsoup-based OG/Twitter/meta parser
├── squoosh/
│   └── SquooshEngine    # Bitmap.compress + HeifCoder AVIF
├── upload/
│   └── UploadEngine     # Multipart POST with ProgressOutputStream
├── viewmodel/           # AndroidViewModel per tab
├── navigation/
│   ├── EmbeddyTab       # Tab enum with Material icons
│   └── AppScaffold      # Scaffold + NavigationBar + AnimatedContent
└── ui/
    ├── screens/         # ConvertScreen, InspectScreen, UploadScreen, SquooshScreen
    ├── components/      # MediaPicker, SettingsPanel, ConversionProgress, OutputPreview
    └── theme/           # Material 3 dark theme

Tech Stack

Component Library
UI Jetpack Compose + Material 3
Video → WebP FFmpeg-kit (libwebp_anim)
AVIF encoding avif-coder (libaom via JNI)
Image loading Coil (compose, gif, video)
HTML parsing Jsoup
EXIF handling AndroidX ExifInterface
Navigation Tab-based with AnimatedContent
Async Kotlin Coroutines + StateFlow

Building

Prerequisites

  • JDK 17+
  • Android SDK with compileSdk 35

Standard build

./gradlew assembleDebug

On Termux (ARM64 Android)

A helper script handles the aapt2 override needed for on-device builds:

bash build-and-install.sh              # build debug
bash build-and-install.sh --install    # build + install via adb
bash build-and-install.sh --release    # build release

Split APKs

The build produces per-ABI APKs (arm64-v8a, armeabi-v7a, x86_64) plus a universal APK. Configured in app/build.gradle.kts:

splits {
    abi {
        isEnable = true
        include("arm64-v8a", "armeabi-v7a", "x86_64")
        isUniversalApk = true
    }
}

CI/CD

Three workflows run on push to main:

Tests (test.yml) — gates everything else. Runs the Android unit suite, the Worker's SSRF tests plus typecheck, and the site's unit tests plus astro check. Also runs on pull requests.

Deploy Site (pages.yml) — runs the site tests, then builds and deploys to GitHub Pages. A failing suite blocks the deploy.

Build & Release (release.yml):

  1. Run the Android unit tests — a failure blocks the release
  2. Pin the resolved version into version.properties and commit it, with a skip-CI marker so the push does not re-trigger the workflow
  3. Build release APKs for the three configured ABIs plus universal
  4. Tag the version-pinned commit and publish a GitHub Release with grouped release notes, a download table with sizes and SHA-256 prefixes, and SHA256SUMS.txt

Version is version.properties (major/minor) + github.run_number (patch). Step 2 matters for anyone rebuilding from a tag — without it the version exists only in the CI environment and a tag build produces a stale version number.

Testing

./gradlew :app:testDebugUnitTest     # Android
cd worker && bun test                # Worker (SSRF)
cd site   && bun test src            # Site (WebP parsing, upload retry)

F-Droid

Store metadata lives in fastlane/metadata/android/en-US/. A draft build recipe and a submission guide — including the dependency-provenance questions a reviewer will raise — are in fdroid/.

Build a single all-ABI APK the way F-Droid does:

./gradlew assembleRelease -PsingleApk

License

GPL-3.0-only — see LICENSE file for details.

About

Swiss-army knife for embeddable media on Android — animated WebP converter, image compressor (WebP/JPEG/PNG/AVIF), OG metadata inspector, anonymous file uploader

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages