video_compress_kit_android 0.0.2 copy "video_compress_kit_android: ^0.0.2" to clipboard
video_compress_kit_android: ^0.0.2 copied to clipboard

PlatformAndroid

Android implementation of the video_compress_kit plugin using MediaCodec.

video_compress_kit_android #

pub package License: MIT

The Android implementation of video_compress_kit.

Usage #

You should not depend on this package directly. Add the app-facing package instead:

dependencies:
  video_compress_kit: ^0.0.1

The Android implementation is automatically endorsed and registered.


How It Works #

Video Compression Pipeline #

Uses Android's built-in MediaCodec hardware video encoder with MediaExtractor for demuxing and MediaMuxer for muxing. No bundled native libraries — the entire implementation rides on top of OS APIs, adding ~0 MB to your APK size.

Input MP4
  → MediaExtractor (demux video + audio tracks)
  → MediaCodec decoder (hardware H.264 decode)
  → Surface transfer
  → MediaCodec encoder (hardware H.264 encode)
      ├─ H.264 Profile: Baseline / Main / High (API 23+)
      ├─ Bitrate mode: VBR / CBR / CQ (API 21+)
      ├─ CQ quality: KEY_QUALITY (0–100)
      └─ Color standard: BT.601 / BT.709 (API 24+)
  → MediaMuxer + audio passthrough
  → Output MP4

Image Compression Pipeline #

Uses Android's built-in BitmapFactory for decoding and Bitmap.compress() for re-encoding. No third-party image libraries.

Input image (JPEG / PNG / WebP / etc.)
  → BitmapFactory.decodeFile (with inSampleSize for memory efficiency)
  → Scale to maxWidth / maxHeight (proportional)
  → Bitmap.compress(format, quality, outputStream)
      ├─ JPEG: CompressFormat.JPEG
      ├─ PNG:  CompressFormat.PNG
      └─ WebP: CompressFormat.WEBP / WEBP_LOSSY (API 30+)
  → ExifInterface: copy EXIF tags (if keepExif = true)
  → Output file

Per-Session Architecture #

Each compressVideo() call creates a VideoCompressor instance stored in a ConcurrentHashMap<String, VideoCompressor> keyed by sessionId. This enables:

  • Concurrent compressions — multiple videos processed in parallel
  • Per-session progress — each compressor reports progress tagged with its session ID
  • Per-session cancellation — cancel a specific session without affecting others
  • Cancel all — iterate the map and cancel every active session
┌──────────────────────────────────┐
│  VideoCompressKitAndroidPlugin   │
│                                  │
│  compressors: ConcurrentHashMap  │
│  ┌────────────┬────────────┐     │
│  │ "job-1"    │ "job-2"    │     │
│  │ Compressor │ Compressor │     │
│  └────────────┴────────────┘     │
│                                  │
│  cancelCompression("job-1")      │
│   → compressors["job-1"].cancel()│
│                                  │
│  cancelCompression(null)         │
│   → cancel ALL                   │
└──────────────────────────────────┘

Video Feature Support Matrix #

Feature Support Notes
H.264 encoding Hardware-accelerated via MediaCodec
Resolution scaling Aspect-ratio preserved
Custom bitrate Overrides preset default
Custom frame rate
Audio passthrough Copies audio track without re-encoding
H.264 Baseline profile KEY_PROFILE, API 23+
H.264 Main profile KEY_PROFILE, API 23+
H.264 High profile KEY_PROFILE, API 23+
VBR bitrate mode BITRATE_MODE_VBR (default)
CBR bitrate mode BITRATE_MODE_CBR
CQ bitrate mode ✅* BITRATE_MODE_CQ + KEY_QUALITY (API 21+). Falls back to VBR if hardware doesn't support CQ
BT.601 color standard KEY_COLOR_STANDARD (API 24+)
BT.709 color standard KEY_COLOR_STANDARD (API 24+)
Faststart (moov atom) Not supported by MediaMuxer
Per-session progress Event channel with {sessionId, progress}
Per-session cancel ConcurrentHashMap keyed by sessionId
Delete original file

CQ fallback: Not all Android hardware encoders support BITRATE_MODE_CQ. The implementation wraps CQ configuration in a try/catch — if the encoder rejects CQ mode, it automatically falls back to VBR with the preset bitrate.

Image Feature Support Matrix #

Feature Support Notes
JPEG output Bitmap.CompressFormat.JPEG
PNG output Bitmap.CompressFormat.PNG (lossless, quality ignored)
WebP output WEBP_LOSSY on API 30+, WEBP on older
Quality control 1–100 for JPEG/WebP
Resize (maxWidth / maxHeight) Proportional scaling with inSampleSize for memory efficiency
EXIF metadata copy ExifInterface — copies orientation, GPS, camera, and date tags

Requirements #

Requirement Value
Min SDK 24 (Android 7.0)
Compile SDK 36
Kotlin 2.x
Java 17
Dependencies kotlinx-coroutines-android:1.7.3

Native APIs Used #

API Purpose Min API
MediaExtractor Demux input video/audio tracks 16
MediaCodec Hardware H.264 decode/encode 16
MediaMuxer Mux encoded video + audio into MP4 18
MediaFormat Configure encoder (profile, bitrate mode, CQ, color) 16+
BitmapFactory Decode images with inSampleSize 1
Bitmap.compress Re-encode images to JPEG/PNG/WebP 1
ExifInterface Read/write EXIF metadata 24
MediaMetadataRetriever Get video metadata, extract frames 10

License #

MIT — see LICENSE.