nosmai_camera_sdk 1.0.1
nosmai_camera_sdk: ^1.0.1 copied to clipboard
A Flutter plugin for Nosmai SDK - Real-time video filtering and beauty effects
Nosmai Camera SDK Flutter Plugin #
A Flutter plugin for integrating the Nosmai SDK - Real-time video filtering and beauty effects for iOS applications.
Features #
- 🎥 Real-time video processing with GPU acceleration and camera preview
- ✨ Beauty filters (skin smoothing, whitening, face slimming, eye enlargement, nose size)
- 🎨 Color adjustments (brightness, contrast, HSB, white balance, RGB)
- 🎭 Effects and filters with .nosmai file support
- 📱 Camera controls (front/back switching, photo capture, video recording)
- 💾 Media management (save photos and videos to gallery)
- 📡 Stream-based events for real-time callbacks
- 🏷️ Metadata-based filter categorization (beauty, effect, filter)
- ♻️ Automatic lifecycle management with proper cleanup
Platform Support #
| Platform | Status |
|---|---|
| iOS | ✅ Supported (iOS 14.0+) |
| Android | 🚧 Planned |
Requirements #
- iOS: 14.0+
- Flutter: 3.0.0+
- Dart: 2.17.0+
Installation #
Add this to your package's pubspec.yaml file:
dependencies:
nosmai_camera_sdk: ^1.0.0+1
Setup #
iOS Setup #
- Add camera permissions to your
ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>This app uses the camera to apply real-time filters and beauty effects.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app may use the microphone for video recording with filters.</string>
Usage #
App Initialization #
For production apps, it's recommended to initialize the SDK once at app startup using a manager pattern:
// main.dart
import 'package:flutter/material.dart';
import 'nosmai_app_manager.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Nosmai SDK once for the entire app
await NosmaiAppManager.instance.initialize('YOUR_LICENSE_KEY');
runApp(const MyApp());
}
Create a NosmaiAppManager class to handle SDK lifecycle:
// nosmai_app_manager.dart
import 'package:nosmai_camera_sdk/nosmai_flutter.dart';
class NosmaiAppManager {
static final NosmaiAppManager _instance = NosmaiAppManager._internal();
static NosmaiAppManager get instance => _instance;
NosmaiAppManager._internal();
final NosmaiFlutter _nosmai = NosmaiFlutter.instance;
NosmaiFlutter get nosmai => _nosmai;
bool _isInitialized = false;
bool get isInitialized => _isInitialized;
Future<bool> initialize(String licenseKey) async {
if (_isInitialized) return true;
try {
_isInitialized = await _nosmai.initWithLicense(licenseKey);
return _isInitialized;
} catch (e) {
return false;
}
}
}
Basic Setup with Camera Preview #
import 'package:nosmai_camera_sdk/nosmai_flutter.dart';
class CameraScreen extends StatefulWidget {
@override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<CameraScreen> {
bool _isInitialized = false;
@override
void initState() {
super.initState();
_checkInitialization();
}
void _checkInitialization() {
// Check if SDK is already initialized through NosmaiAppManager
setState(() {
_isInitialized = NosmaiFlutter.instance.isInitialized;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Stack(
children: [
// Camera Preview with automatic lifecycle management
if (_isInitialized)
const Positioned.fill(
child: NosmaiCameraPreview(),
)
else
const Center(
child: CircularProgressIndicator(),
),
// Your UI controls here
Positioned(
bottom: 100,
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
onPressed: () async {
final result = await NosmaiFlutter.instance.capturePhoto();
if (result.success && result.imageData != null) {
// Handle captured photo
await NosmaiFlutter.instance.saveImageToGallery(
result.imageData!,
name: 'photo_${DateTime.now().millisecondsSinceEpoch}',
);
}
},
icon: const Icon(Icons.camera_alt, color: Colors.white),
),
IconButton(
onPressed: () async {
await NosmaiFlutter.instance.switchCamera();
},
icon: const Icon(Icons.flip_camera_ios, color: Colors.white),
),
],
),
),
],
),
);
}
@override
void dispose() {
// NosmaiCameraPreview handles cleanup automatically
super.dispose();
}
}
Applying Filters #
Basic Color Adjustments
final nosmai = NosmaiFlutter.instance;
// Brightness adjustment
await nosmai.applyBrightnessFilter(0.3); // -1.0 to 1.0
// Contrast adjustment
await nosmai.applyContrastFilter(1.5); // 0.0 to 2.0
// RGB color adjustments
await nosmai.applyRGBFilter(
red: 1.2, // 0.0 to 2.0
green: 0.8, // 0.0 to 2.0
blue: 1.1, // 0.0 to 2.0
);
// HSB adjustments
await nosmai.adjustHSB(
hue: 0.0, // -360 to 360
saturation: 1.2, // 0.0 to 2.0
brightness: 1.1, // 0.0 to 2.0
);
// White balance
await nosmai.applyWhiteBalance(
temperature: 5500.0, // 2000-8000
tint: 0.0, // -100 to 100
);
Beauty Filters
final nosmai = NosmaiFlutter.instance;
// Enable face detection for beauty filters
await nosmai.setFaceDetectionEnabled(true);
// Skin smoothing (requires face detection)
await nosmai.applySkinSmoothing(0.7); // 0.0 to 10.0
// Skin whitening
await nosmai.applySkinWhitening(0.5); // 0.0 to 10.0
// Face slimming
await nosmai.applyFaceSlimming(0.3); // 0.0 to 10.0
// Eye enlargement
await nosmai.applyEyeEnlargement(0.2); // 0.0 to 10.0
// Nose size adjustment
await nosmai.applyNoseSize(50.0); // 0.0 to 100.0
Effect Filters
final nosmai = NosmaiFlutter.instance;
// Apply .nosmai effect files
await nosmai.applyEffect('/path/to/filter.nosmai');
// Load and apply custom filters
final success = await nosmai.loadNosmaiFilter('/path/to/filter.nosmai');
if (success) {
// Filter is now loaded and applied
}
// Get available filters
final filters = await nosmai.getFilters();
for (final filter in filters) {
if (filter is NosmaiLocalFilter) {
await nosmai.applyEffect(filter.path);
}
}
// Get filters by category
final beautyFilters = await nosmai.getFiltersByCategory(NosmaiFilterCategory.beauty);
final effectFilters = await nosmai.getFiltersByCategory(NosmaiFilterCategory.effect);
Camera Controls and Media Capture #
final nosmai = NosmaiFlutter.instance;
// Switch between front and back camera
await nosmai.switchCamera();
// Capture photo with applied filters
final result = await nosmai.capturePhoto();
if (result.success && result.imageData != null) {
// Save to gallery
final saveResult = await nosmai.saveImageToGallery(
result.imageData!,
name: 'my_photo_${DateTime.now().millisecondsSinceEpoch}',
);
}
// Video recording
final recordingStarted = await nosmai.startRecording();
if (recordingStarted) {
// Stop recording after some time
final result = await nosmai.stopRecording();
if (result.success && result.videoPath != null) {
// Save to gallery
await nosmai.saveVideoToGallery(
result.videoPath!,
name: 'my_video_${DateTime.now().millisecondsSinceEpoch}',
);
}
}
// Remove all applied filters
await nosmai.removeAllFilters();
await nosmai.removeBuiltInFilters();
await nosmai.resetHSBFilter();
Event Handling #
final nosmai = NosmaiFlutter.instance;
// Listen for errors
nosmai.onError.listen((error) {
debugPrint('Nosmai Error: ${error.message}');
// Handle error appropriately
});
// Listen for download progress (for cloud filters)
nosmai.onDownloadProgress.listen((progress) {
debugPrint('Download: ${progress.progress}%');
});
// Listen for SDK state changes
nosmai.onStateChanged.listen((state) {
debugPrint('SDK State: ${state.toString()}');
});
// Listen for recording progress
nosmai.onRecordingProgress.listen((duration) {
debugPrint('Recording duration: ${duration}s');
});
Filter Management and Organization #
The SDK provides metadata-based filter categorization:
final nosmai = NosmaiFlutter.instance;
// Get all available filters
final allFilters = await nosmai.getFilters();
// Organize filters by category
final organized = await nosmai.organizeFiltersByCategory();
final beautyFilters = organized[NosmaiFilterCategory.beauty] ?? [];
final effectFilters = organized[NosmaiFilterCategory.effect] ?? [];
// Check if a filter is a beauty filter
for (final filter in allFilters) {
if (nosmai.isBeautyFilter(filter)) {
debugPrint('${filter.displayName} is a beauty filter');
}
}
// Get only filters of a specific category
final beautyOnly = await nosmai.getFiltersByCategory(NosmaiFilterCategory.beauty);
// Apply filters based on type
for (final filter in allFilters) {
if (filter is NosmaiLocalFilter) {
await nosmai.applyEffect(filter.path);
}
}
API Reference #
NosmaiFlutter #
Main class for interacting with the Nosmai SDK.
Properties
bool isInitialized- Whether the SDK has been initializedbool isProcessing- Whether video processing is activebool isRecording- Whether video recording is activeStream<NosmaiError> onError- Stream of error eventsStream<NosmaiDownloadProgress> onDownloadProgress- Stream of download progressStream<NosmaiSdkState> onStateChanged- Stream of SDK state changes
Methods
Initialization & Lifecycle
Future<bool> initWithLicense(String licenseKey)- Initialize SDK with licenseFuture<void> configureCamera({required NosmaiCameraPosition position, String? sessionPreset})- Configure cameraFuture<void> startProcessing()- Start video processingFuture<void> stopProcessing()- Stop video processingFuture<void> cleanup()- Clean up SDK resourcesvoid dispose()- Dispose instance and stream controllers
Camera Controls
Future<bool> switchCamera()- Switch between front and back cameraFuture<void> setPreviewView()- Set preview view (iOS only)Future<void> detachCameraView()- Detach camera viewFuture<void> setFaceDetectionEnabled(bool enable)- Enable/disable face detection
Media Capture
Future<NosmaiPhotoResult> capturePhoto()- Capture photo with applied filtersFuture<bool> startRecording()- Start video recordingFuture<NosmaiRecordingResult> stopRecording()- Stop video recordingFuture<bool> isCurrentlyRecording()- Check if currently recordingFuture<double> getCurrentRecordingDuration()- Get current recording durationFuture<Map<String, dynamic>> saveImageToGallery(List<int> imageData, {String? name})- Save image to galleryFuture<Map<String, dynamic>> saveVideoToGallery(String videoPath, {String? name})- Save video to gallery
Color & Basic Filters
Future<void> applyBrightnessFilter(double brightness)- Apply brightness (-1.0 to 1.0)Future<void> applyContrastFilter(double contrast)- Apply contrast (0.0 to 2.0)Future<void> applyRGBFilter({required double red, required double green, required double blue})- Apply RGB adjustmentsFuture<void> adjustHSB({required double hue, required double saturation, required double brightness})- Adjust HSBFuture<void> resetHSBFilter()- Reset HSB to defaultsFuture<void> applyWhiteBalance({required double temperature, required double tint})- Apply white balanceFuture<void> applyHue(double hueAngle)- Apply hue rotation
Beauty Filters (require face detection)
Future<void> applySkinSmoothing(double level)- Apply skin smoothing (0.0 to 10.0)Future<void> applySkinWhitening(double level)- Apply skin whitening (0.0 to 10.0)Future<void> applyFaceSlimming(double level)- Apply face slimming (0.0 to 10.0)Future<void> applyEyeEnlargement(double level)- Apply eye enlargement (0.0 to 10.0)Future<void> applyNoseSize(double size)- Apply nose size adjustment (0.0 to 100.0)
Effect Filters
Future<bool> applyEffect(String effectPath)- Apply .nosmai effect fileFuture<bool> loadNosmaiFilter(String filePath)- Load custom filterFuture<List<NosmaiEffectParameter>> getEffectParameters()- Get current effect parametersFuture<bool> setEffectParameter(String parameterName, double value)- Set effect parameter
Filter Management
Future<List<dynamic>> getFilters()- Get all available filtersFuture<List<NosmaiLocalFilter>> getLocalFilters()- Get local filters onlyFuture<List<NosmaiCloudFilter>> getCloudFilters()- Get cloud filters onlyFuture<Map<String, dynamic>> downloadCloudFilter(String filterId)- Download cloud filterbool isBeautyFilter(dynamic filter)- Check if filter is beauty typeFuture<List<dynamic>> getFiltersByCategory(NosmaiFilterCategory category)- Get filters by categoryFuture<Map<NosmaiFilterCategory, List<dynamic>>> organizeFiltersByCategory()- Organize filters by categoryFuture<void> clearFilterCache()- Clear filter cache to force refreshFuture<List<dynamic>> getInitialFilters()- Get initial filters available from SDKFuture<void> fetchCloudFilters()- Fetch cloud filters from server
Filter Removal
Future<void> removeAllFilters()- Remove all applied filtersFuture<void> removeBuiltInFilters()- Remove built-in filtersFuture<void> removeBuiltInFilterByName(String filterName)- Remove specific built-in filter
Additional Beauty and Color Methods
Future<void> applySharpening(double level)- Apply sharpening (0.0 to 10.0)Future<void> applyMakeupBlendLevel(String filterName, double level)- Apply makeup blend levelFuture<void> applyGrayscaleFilter()- Apply grayscale filter
License Feature Methods
Future<bool> isBeautyEffectEnabled()- Check if beauty effects are enabled for licenseFuture<bool> isCloudFilterEnabled()- Check if cloud filters are enabled for license
Utility Methods
Future<String?> getPlatformVersion()- Get platform version for debugging
Core Types #
NosmaiCameraPosition
front- Front-facing cameraback- Back-facing camera
NosmaiFilterCategory
beauty- Beauty enhancement filters (face slimming, skin smoothing, etc.)effect- Creative/artistic effects (glitch, holographic, etc.)filter- Standard filters (color adjustments, basic effects, etc.)unknown- Unknown or uncategorized filters
NosmaiError
String code- Error codeString message- Error messageString? details- Additional error details
NosmaiDownloadProgress
String filterId- Filter being downloadeddouble progress- Download progress (0.0-1.0)String? status- Download status
NosmaiSdkState
- Various SDK state values for monitoring
NosmaiRecordingResult
bool success- Whether recording was successfulString? videoPath- Path to recorded video filedouble duration- Recording duration in secondsint fileSize- Video file size in bytesString? error- Error message if recording failed
NosmaiPhotoResult
bool success- Whether photo capture was successfulString? imagePath- Path to captured image fileList<int>? imageData- Raw image data as bytesString? error- Error message if capture failedint? width- Image width in pixelsint? height- Image height in pixels
Filter Types #
NosmaiLocalFilter
String name- Filter nameString path- Local file pathString displayName- Human-readable nameint fileSize- File size in bytesString type- Filter type ('local')NosmaiFilterCategory filterCategory- Filter category
NosmaiCloudFilter
String id- Unique cloud filter IDString name- Filter nameString displayName- Human-readable namebool isFree- Whether filter is freebool isDownloaded- Whether filter is downloadedString? localPath- Local path if downloadedint? fileSize- File size in bytesString? previewUrl- Preview image URLString? category- Category stringNosmaiFilterCategory filterCategory- Filter category
NosmaiEffectParameter
String name- Parameter nameString type- Parameter type (e.g., 'float')double defaultValue- Default parameter valuedouble currentValue- Current parameter valuedouble minValue- Minimum allowed valuedouble maxValue- Maximum allowed valueString? passId- Pass ID for multi-pass effects
Example #
The example folder contains a comprehensive demo app showcasing all plugin features:
- UnifiedCameraScreen: Complete camera interface with filters, recording, and photo capture
- Real-time filter switching with horizontal scrollable filter panels
- Interactive parameter adjustment with sliders for beauty and color filters
- Camera controls: front/back switching, photo capture, video recording
- Media management: Save photos and videos to gallery
- Filter organization: Categorized by Effects, Beauty, Color, and HSB
- Error handling and status monitoring
- Automatic lifecycle management
Running the Example #
cd example
flutter pub get
cd ios && pod install
cd .. && flutter run
Key Example Files #
lib/unified_camera_screen.dart- Main camera interface with professional naming conventions and all featureslib/nosmai_app_manager.dart- SDK initialization and lifecycle managementlib/filter_example.dart- Individual filter testing interfacelib/beauty_filter_screen.dart- Dedicated beauty filter demonstration
Integration with Existing Project #
If you're integrating this plugin into an existing project that already uses the Nosmai SDK:
- The plugin expects to find your SDK headers at the relative path shown in the podspec
- Update the header search paths in
ios/nosmai_flutter.podspecif needed - Ensure your license key is valid and matches the one used in your existing app
- The plugin will work alongside your existing Nosmai implementation
Troubleshooting #
Common Issues #
-
SDK initialization fails
- Verify your license key is correct and active
- Check that the Nosmai SDK headers are found at the expected path
- Ensure iOS deployment target is 13.0+
-
Camera permission denied
- Add camera usage description to Info.plist
- Request permissions before initializing SDK
-
Build errors on iOS
- Clean build folder:
flutter clean - Update CocoaPods:
cd ios && pod update - Check header search paths in nosmai_camera_sdk.podspec
- Clean build folder:
-
Framework not found
- Verify the relative path to your Nosmai SDK
- Check that all required frameworks are linked
- Ensure the SDK is built for the correct architecture
Performance Tips #
- Initialize SDK once at app startup using
NosmaiAppManagerpattern - Use
NosmaiFlutter.instancesingleton for all SDK operations - Use
NosmaiCameraPreviewwidget for automatic lifecycle management - Stop processing when app goes to background to save battery with
stopProcessing() - Remove filters when switching between different effect types using
removeAllFilters() - Beauty filters automatically enable face detection - disable when not needed with
setFaceDetectionEnabled(false) - Use horizontal scrollable filter panels for better UX as shown in the example
- Call
cleanup()instead ofdispose()for SDK resource cleanup - Use
dispose()only when completely done with the SDK instance - Cache filter lists and organize by category for better performance
License #
This plugin is provided under the MIT License. However, the use of the underlying Nosmai SDK is subject to separate licensing terms and conditions.
To use this plugin, you must:
- Obtain a valid license for the Nosmai SDK
- Comply with all Nosmai SDK licensing terms
- Include the Nosmai SDK framework in your application
Support #
For issues related to:
- Plugin functionality: Create an issue in this repository
- Nosmai SDK: Contact Nosmai support
- Flutter integration: Check Flutter documentation
Contributing #
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
Version History #
1.0.0 #
- Initial release
- iOS platform support
- Complete filter API implementation
- Example app with comprehensive demos
- Real Nosmai SDK integration
- Stream-based event handling
- Comprehensive documentation