# 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