sojorn/sojorn_docs/legacy/PRO_VIDEO_EDITOR_CONFIG.md

11 KiB

Pro Video Editor H.264 Configuration Guide

Project: Sojorn - Friend's Only Social Platform
Date: January 24, 2026
Status: Configuration Specification Ready


Overview

This document provides the technical specifications and configuration requirements for implementing the pro_video_editor package with H.264 codec support via FFmpeg in the Sojorn application.


Required ProVideoEditorConfig Settings

Complete Configuration

ProVideoEditorConfigs _buildConfigs() {
  return ProVideoEditorConfigs(
    // ==================== THEME CONFIGURATION ====================
    theme: _buildEditorTheme(), // Custom dark theme with AppTheme.brightNavy
    
    videoEditorTheme: VideoEditorTheme(
      background: Color(0xFF0B0B0B),              // Matte black
      appBarBackgroundColor: Color(0xFF0B0B0B),   // Matte black
      appBarForegroundColor: Colors.white,
      bottomBarBackgroundColor: Color(0xFF0B0B0B), // Matte black
    ),

    // ==================== CROP & ROTATION ====================
    cropRotateEditorConfigs: CropRotateEditorConfigs(
      enabled: true,
      cropRotateEditorTheme: CropRotateEditorTheme(
        appBarBackgroundColor: Color(0xFF0B0B0B),
        appBarForegroundColor: Colors.white,
        background: Color(0xFF0B0B0B),
        cropCornerColor: Color(0xFF1974D1),        // AppTheme.brightNavy
        helperLineColor: Color(0xFF1974D1),        // AppTheme.brightNavy
      ),
    ),

    // ==================== FILTER EDITOR ====================
    filterEditorConfigs: FilterEditorConfigs(
      enabled: true,
      filterEditorTheme: FilterEditorTheme(
        appBarBackgroundColor: Color(0xFF0B0B0B),
        appBarForegroundColor: Colors.white,
        background: Color(0xFF0B0B0B),
        previewTextColor: Colors.white70,
        previewSelectedTextColor: Color(0xFF1974D1), // AppTheme.brightNavy
      ),
    ),

    // ==================== DISABLE DISTRACTING FEATURES ====================
    // Per 'Friend's Only' philosophy - focus on quality over clutter
    stickerEditorConfigs: const StickerEditorConfigs(
      enabled: false,
    ),
    
    textEditorConfigs: const TextEditorConfigs(
      enabled: false,
    ),

    // ==================== EXPORT CONFIGURATION (CRITICAL) ====================
    exportConfigs: ExportConfigs(
      // REQUIRED: Generate export in separate thread for non-blocking UI
      generateInsideSeparateThread: true,
      
      // REQUIRED: Export to .mp4 format
      exportFormat: ExportFormat.mp4,
      
      // REQUIRED: H.264 codec for compatibility
      videoCodec: VideoCodec.h264,
      
      // High quality output
      videoQuality: VideoQuality.high,
      
      // Audio settings
      audioCodec: AudioCodec.aac,
      audioQuality: AudioQuality.high,
      
      // Resolution settings (optional - maintains original by default)
      // maxWidth: 1920,
      // maxHeight: 1080,
      
      // Frame rate (optional - maintains original by default)
      // targetFrameRate: 30,
    ),

    // ==================== CUSTOM WIDGETS ====================
    customWidgets: VideoEditorCustomWidgets(
      appBar: (editor, rebuildStream) => ReactiveCustomAppbar(
        stream: rebuildStream,
        builder: (context) {
          return AppBar(
            backgroundColor: Color(0xFF0B0B0B),
            foregroundColor: Colors.white,
            leading: IconButton(
              tooltip: 'Cancel',
              icon: const Icon(Icons.close),
              onPressed: editor.closeEditor,
            ),
            actions: [
              TextButton(
                onPressed: editor.doneEditing,
                style: TextButton.styleFrom(
                  foregroundColor: Color(0xFF1974D1), // AppTheme.brightNavy
                ),
                child: const Text('Save'),
              ),
              const SizedBox(width: 6),
            ],
          );
        },
      ),
    ),
  );
}

FFmpeg Requirements

1. FFmpeg Kit Flutter Integration

NOTE: The ffmpeg_kit_flutter package has been temporarily removed due to build issues with Maven repository availability. When you're ready to implement the full video editor, you'll need to add it back:

dependencies:
  ffmpeg_kit_flutter: ^6.0.3

Or use an alternative video processing solution. The current video editor is a placeholder that passes through videos without editing.

2. Platform-Specific Configuration

Android (android/app/build.gradle)

android {
    // ...
    
    defaultConfig {
        // ...
        ndk {
            // Specify ABIs to include (reduces APK size)
            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
        }
    }
    
    packagingOptions {
        // Prevent duplicate FFmpeg libraries
        pickFirst 'lib/armeabi-v7a/libc++_shared.so'
        pickFirst 'lib/arm64-v8a/libc++_shared.so'
        pickFirst 'lib/x86_64/libc++_shared.so'
    }
}

iOS (ios/Podfile)

# Minimum iOS version for FFmpeg support
platform :ios, '12.1'

target 'Runner' do
  use_frameworks!
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
  
  # FFmpeg pod is automatically handled by ffmpeg_kit_flutter
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    
    # Ensure proper architecture support
    target.build_configurations.each do |config|
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.1'
      config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'
    end
  end
end

3. Permissions

Android (android/app/src/main/AndroidManifest.xml)

<manifest>
    <!-- Required for video processing -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="32" />
    
    <!-- ... -->
</manifest>

iOS (ios/Runner/Info.plist)

<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to edit videos.</string>
<key>NSCameraUsageDescription</key>
<string>We need access to your camera to record videos.</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need access to your microphone to record audio.</string>

H.264 Codec Specifications

Video Settings

  • Codec: H.264 (AVC)
  • Profile: High Profile (for best quality/compression ratio)
  • Level: 4.1 (supports 1080p @ 30fps)
  • Container: MP4
  • Bitrate: Variable (VBR) - automatically adjusted based on quality setting

Audio Settings

  • Codec: AAC-LC
  • Sample Rate: 44.1 kHz or 48 kHz
  • Bitrate: 128 kbps (high quality)
  • Channels: Stereo (2 channels)

Quality Presets

Quality Resolution Target Bitrate Use Case
High Up to 1080p 8-12 Mbps Default - Best quality
Medium Up to 720p 4-6 Mbps Balanced
Low Up to 480p 1-2 Mbps Quick uploads

Implementation Steps

Step 1: Initialize Video Editor

// In your video_editor_screen.dart
ProVideoEditor.file(
  File(videoPath),
  configs: _buildConfigs(),
  callbacks: ProVideoEditorCallbacks(
    onVideoEditingComplete: (String outputPath) async {
      // outputPath contains the exported .mp4 file with H.264 codec
      // Move to temp directory
      final tempDir = await getTemporaryDirectory();
      final timestamp = DateTime.now().millisecondsSinceEpoch;
      final tempFile = File('${tempDir.path}/sojorn_video_$timestamp.mp4');
      await File(outputPath).copy(tempFile.path);
      
      // Return result
      Navigator.pop(context, SojornMediaResult.video(
        filePath: tempFile.path,
        name: 'sojorn_video_$timestamp.mp4',
      ));
    },
    
    onVideoExporting: () {
      // Show progress indicator
      print('Video exporting...');
    },
    
    onVideoExported: () {
      // Export completed
      print('Video export completed');
    },
    
    onExportProgress: (double progress) {
      // Update progress indicator (0.0 to 1.0)
      print('Export progress: ${(progress * 100).toInt()}%');
    },
  ),
);

Step 2: Handle Export Progress

class _VideoEditorState extends State<VideoEditorScreen> {
  double _exportProgress = 0.0;
  bool _isExporting = false;
  
  Widget _buildExportOverlay() {
    if (!_isExporting) return SizedBox.shrink();
    
    return Container(
      color: Colors.black54,
      child: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            CircularProgressIndicator(
              value: _exportProgress,
              color: AppTheme.brightNavy,
            ),
            SizedBox(height: 16),
            Text(
              'Exporting... ${(_exportProgress * 100).toInt()}%',
              style: TextStyle(color: Colors.white),
            ),
          ],
        ),
      ),
    );
  }
}

Step 3: Test H.264 Export

// Verify exported video codec
Future<void> verifyVideoCodec(String videoPath) async {
  final result = await FFmpegKit.execute(
    '-i $videoPath -hide_banner'
  );
  
  final output = await result.getOutput();
  print('Video info: $output');
  
  // Should show: Video: h264, Audio: aac
}

Troubleshooting

Issue: FFmpeg Not Found

Solution: Run flutter clean and flutter pub get, then rebuild the app.

Issue: Export Fails on iOS

Solution: Ensure iOS deployment target is >= 12.1 in ios/Podfile.

Issue: Large APK Size

Solution: Use abiFilters in android/app/build.gradle to include only necessary architectures.

Issue: Slow Export

Solution: Verify generateInsideSeparateThread: true is set. Consider lowering quality preset.

Issue: Audio Missing in Export

Solution: Ensure audioCodec: AudioCodec.aac is specified in exportConfigs.


Performance Considerations

  1. Threading: Always use generateInsideSeparateThread: true to prevent UI freezing
  2. Memory: Monitor memory usage during export, especially on low-end devices
  3. Storage: Exported videos are saved to temp directory and cleaned up automatically by OS
  4. Battery: Video encoding is CPU-intensive; warn users on low battery

Testing Checklist

  • Export video with H.264 codec
  • Verify .mp4 container format
  • Test crop and rotation
  • Test filter application
  • Verify stickers/text are disabled
  • Test on Android device
  • Test on iOS device
  • Verify temp storage implementation
  • Test upload integration
  • Verify exported video plays in standard players

  • Video Editor Implementation: sojorn_app/lib/screens/compose/video_editor_screen.dart
  • Quip Video Editor: sojorn_app/lib/screens/quips/create/quip_editor_screen.dart
  • Upload Service: sojorn_app/lib/services/image_upload_service.dart
  • Result Class: sojorn_app/lib/models/sojorn_media_result.dart

References


Last Updated: January 24, 2026
Next Review: After FFmpeg configuration is completed