video_compress_kit 0.0.3 copy "video_compress_kit: ^0.0.3" to clipboard
video_compress_kit: ^0.0.3 copied to clipboard

Hardware-accelerated video compression for Flutter using native platform APIs. Zero binary bloat — uses MediaCodec on Android and VideoToolbox on iOS.

video_compress_kit #

pub package License: MIT

Hardware-accelerated video & image compression for Flutter — zero binary bloat, no bundled FFmpeg.

Built by ikolvi.com.

Features #

Video #

  • Compress videos with five quality presets (or custom bitrate/resolution)
  • H.264 profile selection — Baseline, Main, or High
  • Bitrate modes — VBR, CBR, or Constant Quality (CRF-like)
  • BT.709 color standard for HD / 4K content
  • Faststart — moov atom at front for faster streaming (both platforms)
  • Per-session progress & cancellation — run multiple compressions concurrently
  • Audio passthrough — copies audio track without re-encoding
  • Estimate file size — predict output size before compressing

Image #

  • Compress images — JPEG, PNG, WebP output
  • Resize — constrain to max width / height with proportional scaling
  • EXIF metadata — strip or preserve orientation, GPS, camera info

General #

  • Get media info — resolution, duration, bitrate, file size
  • Extract thumbnails — single-frame JPEG at any timestamp
  • Zero binary bloat — uses only native OS APIs

Installation #

dependencies:
  video_compress_kit: ^0.0.1

No extra setup — platform implementations are auto-endorsed.


Video Compression #

Basic usage #

import 'package:video_compress_kit/video_compress_kit.dart';

final kit = VideoCompressKit();

final result = await kit.compressVideo(
  '/path/to/video.mp4',
  sessionId: 'upload-1',  // unique per concurrent operation
  config: const CompressionConfig(quality: VideoQuality.medium),
);

print('Output: ${result.outputPath}  (${result.fileSize} bytes)');

Per-session progress #

Each compression is identified by a sessionId. Progress events include both the session ID and progress value (0.0–1.0):

kit.compressionProgress.listen((event) {
  final id = event['sessionId'] as String;
  final pct = (event['progress'] as double) * 100;
  print('$id: ${pct.toStringAsFixed(1)}%');
});

Filter progress for a specific session:

kit.compressionProgress
  .where((e) => e['sessionId'] == 'upload-1')
  .listen((e) => print('${e['progress']}'));

Per-session cancellation #

// Cancel a specific session
await kit.cancelCompression(sessionId: 'upload-1');

// Cancel ALL active sessions
await kit.cancelCompression();

Concurrent compressions #

final job1 = kit.compressVideo('/path/a.mp4', sessionId: 'job-1');
final job2 = kit.compressVideo('/path/b.mp4', sessionId: 'job-2');

// Both run in parallel with independent progress and cancellation
final results = await Future.wait([job1, job2]);

Quality presets #

Preset Max Resolution Typical Bitrate (1080p@30fps) Approx. 60 s file
veryLow 360p ~0.6 Mbps ~4 MB
low 480p ~1.3 Mbps ~10 MB
medium 720p ~2.8 Mbps ~21 MB
high 1080p ~9.3 Mbps ~70 MB
veryHigh Original ~12.4 Mbps ~93 MB

Values are estimates from the built-in bits-per-pixel model. Actual sizes vary with content complexity and frame rate.

Estimate file size before compressing #

final info = await kit.getMediaInfo(path);
final estimate = kit.estimateFileSize(info: info, quality: VideoQuality.medium);
print('≈ ${(estimate / 1024 / 1024).toStringAsFixed(1)} MB');

Custom configuration #

const config = CompressionConfig(
  quality: VideoQuality.medium,   // base preset
  bitrate: 3000000,               // override: 3 Mbps
  width: 1280,                    // override: 1280 px
  height: 720,                    // override: 720 px
  frameRate: 30,
  includeAudio: true,
  deleteOrigin: false,
  outputPath: '/custom/output.mp4',
);

Advanced codec options #

Fine-tune the H.264 encoder beyond simple presets:

final result = await kit.compressVideo(
  '/path/to/video.mp4',
  sessionId: 'hq-job',
  config: CompressionConfig(
    quality: VideoQuality.high,
    h264Profile: H264Profile.high,       // best compression efficiency
    bitrateMode: BitrateMode.cq,         // constant quality (CRF-like)
    cqQuality: 70,                       // 0–100 (higher = better quality)
    colorStandard: ColorStandard.bt709,  // HD color space
    faststart: true,                     // moov atom at front (both platforms)
  ),
);

H.264 Profile

Profile Description Best for
H264Profile.baseline No B-frames, no CABAC Maximum compatibility, WebRTC, older devices
H264Profile.main B-frames, CABAC Broadcast, streaming
H264Profile.high 8×8 transforms, custom quant matrices Best compression (default on modern devices)

Android: Requires API 23+. If null, the platform default is used.
iOS: All profiles supported on modern devices.

Bitrate Mode

Mode Behaviour File size
BitrateMode.vbr Variable bitrate — adjusts per-frame Variable (platform default)
BitrateMode.cbr Constant bitrate — fixed rate Predictable
BitrateMode.cq Constant Quality — quality-based encoding Variable, quality-driven

CQ mode is the closest equivalent to CRF (x264). Use the cqQuality parameter (0–100) to control quality. On Android, uses BITRATE_MODE_CQ (falls back to VBR if hardware doesn't support it). On iOS, uses AVVideoQualityKey.

Color Standard

Standard Use case
ColorStandard.bt601 Standard-definition content
ColorStandard.bt709 HD / 4K content (recommended)

Android: Requires API 24+.
iOS: Applied via pixel buffer attributes.

Faststart

faststart: true moves the moov atom to the beginning of the MP4 file, enabling progressive download and faster streaming start — equivalent to ffmpeg -movflags +faststart.

Platform Support
iOS ✅ Native shouldOptimizeForNetworkUse
Android ✅ Custom Mp4FastStart post-processor — parses MP4 boxes, patches stco/co64 offsets, rewrites as ftyp + moov + mdat. Zero dependencies, ~1–2 s I/O overhead.

Image Compression #

Basic usage #

final result = await kit.compressImage(
  '/path/to/photo.jpg',
  config: ImageCompressionConfig(
    quality: 80,
    maxWidth: 1920,
    maxHeight: 1080,
    format: ImageFormat.jpeg,
  ),
);

print('${result.outputPath} — ${result.fileSize} bytes');
print('Dimensions: ${result.width}×${result.height}');

Output formats #

Format Quality range Notes
ImageFormat.jpeg 1–100 (default: 80) Lossy, smallest files, universal
ImageFormat.png Ignored (lossless) Lossless, transparency support
ImageFormat.webp 1–100 Best compression ratio. iOS 14+ only

All configuration options #

Parameter Type Default Description
quality int 80 Output quality (1–100). Ignored for PNG
maxWidth int? null Max output width. Scales proportionally
maxHeight int? null Max output height. Scales proportionally
format ImageFormat jpeg Output format: jpeg, png, webp
keepExif bool false Preserve EXIF metadata (orientation, GPS, camera)
outputPath String? null Custom output path (auto-generated if null)

WebP example #

final result = await kit.compressImage(
  '/path/to/photo.jpg',
  config: ImageCompressionConfig(
    quality: 75,
    format: ImageFormat.webp,
    keepExif: false,
  ),
);

EXIF preservation #

// Keep original EXIF data (orientation, GPS, camera info)
final result = await kit.compressImage(
  '/path/to/photo.jpg',
  config: ImageCompressionConfig(keepExif: true),
);

Android: Uses ExifInterface to copy EXIF tags.
iOS: Uses ImageIO (CGImageSource / CGImageDestination) to copy metadata.


Other APIs #

Get media info #

final info = await kit.getMediaInfo('/path/to/video.mp4');
print('Resolution: ${info.width}×${info.height}');
print('Duration:   ${info.duration}s');
print('Bitrate:    ${info.bitrate} bps');
print('File size:  ${info.fileSize} bytes');

Extract thumbnail #

// Get a JPEG frame at 2 seconds with 90% quality
final bytes = await kit.getThumbnail(
  '/path/to/video.mp4',
  quality: 90,
  position: 2000,  // milliseconds
);

Complete API Reference #

VideoCompressKit methods #

Method Returns Description
compressVideo(path, {required sessionId, config}) Future<CompressionResult> Compress a video with per-session tracking
compressImage(path, {config}) Future<ImageCompressionResult> Compress an image (JPEG/PNG/WebP)
getMediaInfo(path) Future<MediaInfo> Get video metadata
getThumbnail(path, {quality, position}) Future<Uint8List?> Extract a single JPEG frame
cancelCompression({sessionId}) Future<void> Cancel one session or all
compressionProgress Stream<Map<String, dynamic>> Per-session progress stream
estimateFileSize({info, quality}) int Predict compressed file size in bytes

CompressionConfig fields #

Field Type Default Description
quality VideoQuality medium Quality preset
bitrate int? null Override bitrate in bps
width int? null Override output width
height int? null Override output height
frameRate int? null Override frame rate
includeAudio bool true Include audio track
deleteOrigin bool false Delete original file
outputPath String? null Custom output path
h264Profile H264Profile? null H.264 profile (baseline/main/high)
bitrateMode BitrateMode? null Bitrate mode (vbr/cbr/cq)
cqQuality int? null CQ quality (0–100). Used with BitrateMode.cq
colorStandard ColorStandard? null Color space (bt601/bt709)
faststart bool false Moov atom at front (both platforms)

Exported types #

Type Description
CompressionConfig Video compression configuration
CompressionResult Result of video compression
ImageCompressionConfig Image compression configuration
ImageCompressionResult Result of image compression
MediaInfo Video metadata
VideoQuality Preset enum: veryLow, low, medium, high, veryHigh
H264Profile Profile enum: baseline, main, high
BitrateMode Mode enum: vbr, cbr, cq
ColorStandard Standard enum: bt601, bt709
ImageFormat Format enum: jpeg, png, webp

Supported Platforms #

Platform Implementation Video API Image API
Android video_compress_kit_android MediaCodec + MediaMuxer BitmapFactory + Bitmap.compress
iOS video_compress_kit_ios AVFoundation / VideoToolbox UIImage / ImageIO

Architecture #

This is a federated Flutter plugin. App developers only import this package; platform implementations are resolved automatically at build time.

video_compress_kit              ← you import this
  └─ video_compress_kit_platform_interface
       ├─ video_compress_kit_android
       └─ video_compress_kit_ios

License #

MIT — see LICENSE.

0
likes
140
points
10
downloads

Publisher

verified publisherikolvi.com

Weekly Downloads

Hardware-accelerated video compression for Flutter using native platform APIs. Zero binary bloat — uses MediaCodec on Android and VideoToolbox on iOS.

Homepage
Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, video_compress_kit_android, video_compress_kit_ios, video_compress_kit_platform_interface

More

Packages that depend on video_compress_kit

Packages that implement video_compress_kit