light_compressor_v2 1.2.0 copy "light_compressor_v2: ^1.2.0" to clipboard
light_compressor_v2: ^1.2.0 copied to clipboard

A powerful and easy-to-use video compression plugin for Flutter.

light_compressor_v2 #

Pub Version Pub Platforms Pub Likes License: MIT

A powerful, easy-to-use video compression plugin for Flutter โ€” for single videos and batches.

It generates a compressed MP4 with reduced width, height, and bitrate while keeping good visual quality, and also exposes media metadata, thumbnail extraction, and cache cleanup.

๐Ÿ› ๏ธ How it Works #

Extreme high bitrates are reduced while maintaining good video quality, resulting in a much smaller file size.

  • Quality presets: choose between 5 compression qualities โ€” very_low, low, medium, high, very_high. The plugin automatically computes the target bitrate for the output.
  • Minimum bitrate guard: with isMinBitrateCheckEnabled (default 2 Mbps threshold), the plugin skips compression for low-bitrate or already-compressed videos, avoiding cumulative quality degradation.

โœจ Features #

  • Single & batch compression โ€” compress one video, or many in a single call with per-item results and progress.
  • Five quality presets โ€” the plugin calculates the optimal bitrate automatically.
  • Custom resolution & bitrate โ€” override width, height, and bitrate when presets aren't enough.
  • Structured success result โ€” OnSuccess carries originalSize, compressedSize, duration, and ratio (percentage reduction).
  • Media info โ€” read width, height, duration, bitrate, rotation, frame rate, and MIME type via getMediaInfo.
  • Thumbnail extraction โ€” grab a JPEG frame at any timecode via getVideoThumbnail.
  • Progress streams โ€” real-time percentage for single (onProgressUpdated) and per-item + overall for batch (onBatchUpdate).
  • Cancellation โ€” cancel any in-progress compression with a single call.
  • Typed exceptions โ€” PermissionDeniedException, UnsupportedVideoException, VideoNotFoundException, and more โ€” react programmatically instead of parsing strings.
  • Minimum bitrate guard โ€” optionally skip compression for already-low-bitrate videos.
  • Disable audio โ€” generate silent videos when audio isn't needed.
  • Cache cleanup โ€” remove temporary files with clearCache.
  • iOS / macOS: Swift Package Manager (SPM) support alongside CocoaPods.
  • Android: fully Kotlin native layer, Gradle KTS build script.

๐Ÿ“ธ Demo #

Demo GIF


๐Ÿ“ฑ Platform Support #

iOS Android macOS
โœ… โœ… โœ…

Minimum versions: iOS 11 ยท Android API 24 ยท macOS 10.15


๐Ÿ“ฆ Installation #

Add the dependency to your pubspec.yaml:

dependencies:
  light_compressor_v2: ^1.2.0

Then run:

flutter pub get

iOS / macOS โ€” Podfile #

No extra Podfile configuration is required. The plugin ships with both a .podspec (CocoaPods) and a Package.swift (SPM); Flutter picks the appropriate integration automatically.

Android โ€” minSdk #

The plugin requires minSdk 24. If your app targets a lower SDK, update your android/app/build.gradle:

android {
    defaultConfig {
        minSdk = 24
    }
}

๐Ÿš€ Usage #

import 'package:light_compressor_v2/light_compressor_v2.dart';

final compressor = LightCompressor();

Compress a single video #

final Result result = await compressor.compressVideo(
  path: '/path/to/source.mp4',
  videoQuality: VideoQuality.medium,
  isMinBitrateCheckEnabled: false,
  video: Video(videoName: 'compressed.mp4'),
  android: AndroidConfig(isSharedStorage: true, saveAt: SaveAt.Movies),
  ios: IOSConfig(saveInGallery: true),
);

if (result is OnSuccess) {
  print('Saved to ${result.destinationPath}');
  print('Reduced by ${result.ratio.toStringAsFixed(1)}% '
      '(${result.originalSize} โ†’ ${result.compressedSize} bytes)');
} else if (result is OnFailure) {
  print('Failed: ${result.message}');
} else if (result is OnCancelled) {
  print('Cancelled');
}

Compress a batch of videos #

A single failing video does not stop the others โ€” its slot in the returned list becomes an OnFailure. Results are returned in the same order as paths.

final List<Result> results = await compressor.compressVideos(
  paths: ['/path/a.mp4', '/path/b.mp4'],
  videoNames: ['a_compressed.mp4', 'b_compressed.mp4'],
  videoQuality: VideoQuality.medium,
  android: AndroidConfig(saveAt: SaveAt.Movies),
  ios: IOSConfig(saveInGallery: false),
);

for (final (int i, Result r) in results.indexed) {
  if (r is OnSuccess) print('Video $i โ†’ ${r.destinationPath}');
}

Listen to progress #

Single video โ€” a Stream<double> from 0 to 100:

StreamBuilder<double>(
  stream: compressor.onProgressUpdated,
  builder: (context, snapshot) {
    final percent = snapshot.data ?? 0;
    return Text('${percent.toStringAsFixed(0)}%');
  },
);

Batch โ€” per-video and overall progress, plus a completion event per item:

compressor.onBatchUpdate.listen((BatchEvent event) {
  switch (event) {
    case BatchProgress(:final index, :final overallPercent):
      print('Video $index โ€” overall ${overallPercent.toStringAsFixed(0)}%');
    case BatchItemCompleted(:final index, :final result):
      print('Video $index finished: $result');
  }
});

Cancel compression #

await compressor.cancelCompression();

The cancelled job is reported as an OnCancelled result on the pending compressVideo / compressVideos call.

Read media info #

final MediaInfo info = await compressor.getMediaInfo('/path/to/video.mp4');
print('${info.displayWidth} ร— ${info.displayHeight}');
print('Duration: ${info.duration}, bitrate: ${info.bitrate} bps');

Extract a thumbnail #

final String thumbnailPath = await compressor.getVideoThumbnail(
  '/path/to/video.mp4',
  positionInMs: 2000, // grab the frame at 2s
  quality: 80,
);

Clear cached files #

await compressor.clearCache();

Handle errors #

Recognized native failures are thrown as typed exceptions; unclassified failures are returned as OnFailure instead.

try {
  final info = await compressor.getMediaInfo('/path/to/video.mp4');
  // use info...
} on VideoNotFoundException catch (e) {
  print(e.message);
} on PermissionDeniedException catch (e) {
  print(e.message);
} on LightCompressorException catch (e) {
  print(e.message); // base type โ€” catches any of the above
}

๐Ÿ“– API Reference #

compressVideo() โ†’ Future<Result> #

Parameter Type Required Default Description
path String โœ… โ€” Absolute path to the source video file.
videoQuality VideoQuality โœ… โ€” Quality preset: very_low, low, medium, high, very_high.
android AndroidConfig โœ… โ€” Android-specific storage configuration.
ios IOSConfig โœ… โ€” iOS/macOS-specific storage configuration.
video Video โœ… โ€” Output video configuration (name, resolution, bitrate).
isMinBitrateCheckEnabled bool true Skip compression when source bitrate is below 2 Mbps.
disableAudio bool? false Strip the audio track from the output.

compressVideos() โ†’ Future<List<Result>> #

Parameter Type Required Default Description
paths List<String> โœ… โ€” Source video paths.
videoNames List<String> โœ… โ€” Output file names; must match paths length.
videoQuality VideoQuality โœ… โ€” Quality preset, shared by every video.
android AndroidConfig โœ… โ€” Android-specific storage configuration.
ios IOSConfig โœ… โ€” iOS/macOS-specific storage configuration.
keepOriginalResolution bool false Keep source dimensions instead of downscaling.
videoWidth / videoHeight int? null Custom output size (set both together).
videoBitrateInMbps int? null Custom bitrate in Mbps (overrides the preset).
disableAudio bool false Strip the audio track from every output.
isMinBitrateCheckEnabled bool true Skip compression when source bitrate is below 2 Mbps.

Video #

Parameter Type Required Default Description
videoName String โœ… โ€” Output filename (.mp4 appended automatically if missing).
keepOriginalResolution bool? false Keep source dimensions instead of downscaling.
videoBitrateInMbps int? null Custom bitrate in Mbps (overrides the quality preset).
videoHeight int? null Custom height in pixels. Must be set with videoWidth.
videoWidth int? null Custom width in pixels. Must be set with videoHeight.

AndroidConfig #

Parameter Type Default Description
isSharedStorage bool true true = shared storage (MediaStore); false = app-specific directory.
saveAt SaveAt Movies Target collection: Pictures, Movies, or Downloads. Ignored when isSharedStorage is false.

IOSConfig #

Parameter Type Default Description
saveInGallery bool true Save the compressed video to the photo library.

Result types #

Type Properties Description
OnSuccess destinationPath: String, originalSize: int, compressedSize: int, duration: double, ratio: double Output path, byte sizes, duration (seconds) and percentage size reduction.
OnFailure message: String Unclassified failure with an error message.
OnCancelled isCancelled: bool Compression was cancelled via cancelCompression().

BatchEvent (from onBatchUpdate) #

Type Properties Description
BatchProgress index: int, percent: double, overallPercent: double Progress of one video and the batch average.
BatchItemCompleted index: int, result: Result A video finished; result is OnSuccess / OnFailure / OnCancelled.

MediaInfo (from getMediaInfo) #

All fields are nullable โ€” a container/device may not expose every value.

Property Type Description
width / height int? Encoded dimensions in pixels (before rotation).
displayWidth / displayHeight int? Dimensions as displayed (rotation-aware).
duration Duration? Total duration.
fileSize int? File size in bytes.
bitrate int? Bitrate in bits per second.
rotation int? Rotation in degrees (0, 90, 180, 270).
frameRate double? Frames per second.
mimeType String? Container MIME type.

Exceptions #

All extend LightCompressorException (catch the base type to handle any):

Exception Thrown when
PermissionDeniedException Missing read/write permission.
UnsupportedVideoException Unsupported format/codec or missing track.
VideoNotFoundException The source video was not found.
MediaInfoException Metadata could not be read (getMediaInfo).
ThumbnailException A frame could not be extracted (getVideoThumbnail).

Other members #

Member Signature Description
onProgressUpdated Stream<double> Single-video progress, 0โ€“100.
onBatchUpdate Stream<BatchEvent> Per-video + overall progress and completion events during compressVideos.
getMediaInfo() Future<MediaInfo> Read video metadata.
getVideoThumbnail() Future<String> Extract a JPEG frame; returns its file path.
clearCache() Future<void> Delete temporary .mp4 files created during compression.
cancelCompression() Future<void> Cancel any running compression.

โš™๏ธ Configuration #

iOS / macOS #

SPM vs CocoaPods โ€” the plugin includes both Package.swift and .podspec. Flutter โ‰ฅ 3.24 uses SPM by default; older versions fall back to CocoaPods automatically.

Info.plist โ€” if you use IOSConfig(saveInGallery: true), add the photo library usage description:

<key>NSPhotoLibraryUsageDescription</key>
<string>Used to save compressed videos.</string>

Android #

Permissions โ€” add the appropriate permissions to AndroidManifest.xml based on your target API level:

<!-- API < 29 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="28"
    tools:ignore="ScopedStorage" />

<!-- API 29โ€“32 -->
<uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="32" />

<!-- API โ‰ฅ 33 -->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

ProGuard โ€” no special ProGuard or R8 rules are required.


๐Ÿค Contributing #

Contributions are welcome! To get started:

  1. Fork the repository: github.com/Farid023/light_compressor_v2
  2. Create a feature branch: git checkout -b feat/my-feature
  3. Make your changes and run the example app to verify:
    cd example
    flutter run
    
  4. Open a Pull Request with a clear description of the change.

Please report bugs via GitHub Issues. Include the device name, OS version, and whether the issue reproduces in the example app.


๐Ÿ“„ License #

License: MIT

Released under the MIT License โ€” see LICENSE for the full text.

MIT ยฉ 2025 Farid Gurbanov

10
likes
0
points
5.91k
downloads

Publisher

unverified uploader

Weekly Downloads

A powerful and easy-to-use video compression plugin for Flutter.

Repository (GitHub)
View/report issues

Topics

#video #compression #video-compression #media #compressor

License

unknown (license)

Dependencies

flutter

More

Packages that depend on light_compressor_v2

Packages that implement light_compressor_v2