lut_transformer

pub version

A Flutter plugin for applying 3D LUT (Look-Up Table) filters to videos on the Android platform. This plugin allows you to transform the colors of your videos using .cube LUT files. It also applies a 1:1 aspect ratio crop, centering the crop based on the video's shorter dimension, to the output video.

Features

  • Apply .cube LUT files to videos.
  • Reports transformation progress.
  • Output video is cropped to a 1:1 aspect ratio, centered, using the shorter dimension of the video as the side length.
  • Option to adjust the intensity of the LUT effect (0.0 to 1.0).
  • Option to flip the video horizontally.
  • Works on both Android and iOS using platform specific implementations.

Platform Support

Android iOS Web macOS Windows Linux

The plugin now provides full transformation functionality on both Android and iOS.

Getting Started

Prerequisites

  • Flutter SDK: Version >=3.32.0 (as per pubspec.yaml)
  • Dart SDK: Version >=3.8.0 <4.0.0 (as per pubspec.yaml)

Installation

Add lut_transformer to your pubspec.yaml file:

dependencies:
  lut_transformer: ^1.0.0 # Use the latest version from pub.dev

Then, run flutter pub get to install the package.

Android Setup

No specific additional setup is required for Android beyond the standard Flutter project setup. Ensure your project meets the minimum Android SDK requirements if any are imposed by the underlying Media3 library (typically API level 21 or higher).

iOS Setup

The plugin includes a minimal iOS implementation which currently emits an error when video transformation is requested. No special setup is required aside from standard Flutter iOS configuration.

Usage

Importing the plugin

import 'package:lut_transformer/lut_transformer.dart';
import 'dart:io'; // For File objects
// Import 'package:flutter/services.dart' for PlatformException if you need to specifically catch it.

Transforming a Video

To transform a video, use the static method LutTransformer.transformVideo. You need to provide:

  • The input video File.
  • Optionally, the asset path to your .cube LUT file (lutAsset).
  • Optionally, the intensity of the LUT effect (lutIntensity), a double value between 0.0 (no effect) and 1.0 (full effect). If lutAsset is provided and lutIntensity is null, it defaults to 1.0.
  • Optionally, a boolean flipHorizontally (defaults to false) to indicate if the video should be flipped horizontally.
  • Optionally, cropSquareSize to specify the output video dimension.

If lutAsset is null, the video will only be cropped (and potentially flipped), and lutIntensity will be ignored.

The method returns a Stream<TransformProgress> which emits progress updates and the final result (output path or error).

  1. Ensure your LUT file is in assets: Add your .cube file to your project's assets folder (e.g., assets/luts/my_custom_lut.cube) and declare it in your pubspec.yaml:

    flutter:
      assets:
        - assets/luts/my_custom_lut.cube
        # Add other assets here
    
  2. Call transformVideo and listen to the stream:

    Future<void> applyLutToVideo(File videoFile, String? lutAssetPath, double? lutStrength, bool shouldFlip) async {
      final Stream<TransformProgress> progressStream = LutTransformer.transformVideo(
        videoFile,
        lutAsset: lutAssetPath, // e.g., 'assets/luts/my_custom_lut.cube' or null
        lutIntensity: lutStrength, // e.g., 0.5 for 50% intensity, or null for default (1.0)
        flipHorizontally: shouldFlip,
      );
    
      await for (final TransformProgress progressData in progressStream) {
        print('Video transformation progress: ${progressData.progress * 100}%');
    
        if (progressData.error != null) {
          print('Error during transformation: ${progressData.error!.code}');
          print('Error message: ${progressData.error!.message}');
          // Handle error (e.g., show a message to the user)
          break; // Stop listening if an error occurs
        }
    
        if (progressData.outputPath != null) {
          print('Video transformation complete! Output path: ${progressData.outputPath}');
          // Use the outputPath to access the transformed video file
          // e.g., display it, save it, upload it.
          File transformedVideo = File(progressData.outputPath!);
          // ... do something with transformedVideo ...
        }
      }
    }
    
    // Example usage:
    // File myVideo = File('path/to/your/input_video.mp4');
    // String myLut = 'assets/luts/my_custom_lut.cube';
    // double? intensity = 0.75; // 75% strength
    // bool flip = true;
    // await applyLutToVideo(myVideo, myLut, intensity, flip);
    

TransformProgress Class

The TransformProgress object emitted by the stream has the following properties:

  • double progress: The transformation progress from 0.0 (0%) to 1.0 (100%).
  • String? outputPath: The file path of the transformed video. This is non-null only when the transformation is successfully completed (i.e., progress is 1.0 and no error).
  • PlatformException? error: If an error occurs during transformation, this will contain the PlatformException with error details. It's null if no error occurred.

Getting the Platform Version (for debugging)

You can get the underlying platform version (e.g., "Android 12") using getPlatformVersion. This is mostly for debugging or informational purposes.

String? platformVersion = await LutTransformer.getPlatformVersion();
print('Running on: $platformVersion');

Example Application

An example application demonstrating the use of lut_transformer can be found in the example/ directory of this package. Run it to see the plugin in action.

Testing

This plugin includes unit and integration tests.

Running Integration Tests (Flutter)

Navigate to the example directory and run:

flutter test integration_test

Running Unit Tests (Android Native - Kotlin)

To run the native Android (Kotlin) unit tests for components like CubeParser:

  1. Prepare Test Assets (Important for CubeParserTest): The CubeParserTest.kt requires specific .cube files to be present in the example/android/src/androidTest/assets/ directory. You'll need to manually create these files:

    • example/android/src/androidTest/assets/test_correct.cube
    • example/android/src/androidTest/assets/test_invalid_size_mismatch.cube
    • example/android/src/androidTest/assets/test_no_size.cube The content for these files can be found within the CubeParserTest.kt file itself (e.g., testLutContent string).
  2. Run Gradle Task: Navigate to the android/ directory of the plugin (not the example's android directory) and run:

    ./gradlew testDebugUnitTest
    

    Or, if you are in the example/android/ directory:

    ./gradlew :lut_transformer:testDebugUnitTest
    

    (The exact command might vary slightly based on your project structure if it's part of a larger mono-repo). Alternatively, run them directly from Android Studio.

Contributing

Contributions are welcome! If you find any issues or have suggestions for improvements, please feel free to:

Please ensure that your contributions adhere to the project's coding style and that all tests pass.

License

This plugin is released under the MIT License. See the LICENSE file for more details.

Libraries

lut_transformer