# 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 ```dart 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: ```yaml 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`) ```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`) ```ruby # 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`) ```xml ``` #### iOS (`ios/Runner/Info.plist`) ```xml NSPhotoLibraryUsageDescription We need access to your photo library to edit videos. NSCameraUsageDescription We need access to your camera to record videos. NSMicrophoneUsageDescription We need access to your microphone to record audio. ``` --- ## 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 ```dart // 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 ```dart class _VideoEditorState extends State { 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 ```dart // Verify exported video codec Future 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 --- ## Related Files - **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 - [pro_video_editor Documentation](https://pub.dev/packages/pro_video_editor) - [ffmpeg_kit_flutter Documentation](https://pub.dev/packages/ffmpeg_kit_flutter) - [H.264 Specification](https://www.itu.int/rec/T-REC-H.264) - [MP4 Container Format](https://en.wikipedia.org/wiki/MP4_file_format) --- **Last Updated:** January 24, 2026 **Next Review:** After FFmpeg configuration is completed