startCamera method
Future<int>
startCamera({
- required CameraConfig cameraConfig,
- HandConfig? handConfig,
- FaceConfig? faceConfig,
- AnimalConfig? animalConfig,
- PoseConfig? poseConfig,
- required ModelPaths models,
override
Implementation
@override
Future<int> startCamera({
required CameraConfig cameraConfig,
HandConfig? handConfig,
FaceConfig? faceConfig,
AnimalConfig? animalConfig,
PoseConfig? poseConfig,
required ModelPaths models,
}) async {
// Clamp to 1-60 if set, 0 means no throttle
final maxResults = cameraConfig.maxResultsPerSecond <= 0
? 0
: cameraConfig.maxResultsPerSecond.clamp(1, 60);
final result = await _commandChannel.invokeMethod<int>('startCamera', {
'cameraFacing': cameraConfig.facing.index,
'resolution': cameraConfig.resolution.index,
'maxResultsPerSecond': maxResults,
'enableHand': handConfig != null,
'enableFace': faceConfig != null,
'enableAnimal': animalConfig != null,
'enablePose': poseConfig != null,
// Model file paths — native loads each enabled model from these. Core bundles none.
if (handConfig != null) 'handModelPath': models.handModel,
if (faceConfig?.detectEmotion == true)
'emotionModelPath': models.emotionModel,
if (animalConfig != null) ...{
'animalModelPath': models.animalModel,
'animalScoreThreshold': animalConfig.scoreThreshold,
'animalMaxResults': animalConfig.maxResults,
if (animalConfig.allowedCategories != null)
'animalAllowedCategories': animalConfig.allowedCategories!.toList(),
if (animalConfig.deniedCategories != null)
'animalDeniedCategories': animalConfig.deniedCategories!.toList(),
'detectBreed': animalConfig.detectBreed,
if (animalConfig.detectBreed) 'breedModelPath': models.breedModel,
'breedMaxResults': animalConfig.breedMaxResults,
'breedClassifiableCategories':
animalConfig.breedClassifiableCategories.toList(),
'breedScoreThreshold': animalConfig.breedScoreThreshold,
if (animalConfig.breedAllowedCategories != null)
'breedAllowedCategories': animalConfig.breedAllowedCategories!.toList(),
if (animalConfig.breedDeniedCategories != null)
'breedDeniedCategories': animalConfig.breedDeniedCategories!.toList(),
if (animalConfig.displayNamesLocale != null)
'displayNamesLocale': animalConfig.displayNamesLocale,
if (animalConfig.rotationDegrees != null)
'rotationDegrees': animalConfig.rotationDegrees,
},
if (poseConfig != null) ...{
// Model path is start-time-only; native loads the .task from here.
'poseModelPath': models.poseModel,
'numPoses': poseConfig.numPoses,
'minPoseDetectionConfidence': poseConfig.minPoseDetectionConfidence,
'minPosePresenceConfidence': poseConfig.minPosePresenceConfidence,
'minPoseTrackingConfidence': poseConfig.minTrackingConfidence,
},
if (handConfig != null) ...{
'maxHands': handConfig.maxHands,
'minDetectionConfidence': handConfig.minDetectionConfidence,
'minPresenceConfidence': handConfig.minPresenceConfidence,
'minTrackingConfidence': handConfig.minTrackingConfidence,
// Each custom gesture serializes its fingerStates in thumb→pinky order.
'customGestures': handConfig.customGestures
.map(
(g) => {
'name': g.name,
'fingerStates': [
_fingerStateToNative(g.fingerStates[Finger.thumb]),
_fingerStateToNative(g.fingerStates[Finger.indexFinger]),
_fingerStateToNative(g.fingerStates[Finger.middle]),
_fingerStateToNative(g.fingerStates[Finger.ring]),
_fingerStateToNative(g.fingerStates[Finger.pinky]),
],
},
)
.toList(),
..._serializeGestureFilters(handConfig),
},
if (faceConfig != null) ...{
'detectEmotion': faceConfig.detectEmotion,
'detectLandmarks': faceConfig.detectLandmarks,
'detectContours': faceConfig.detectContours,
'minFaceSize': faceConfig.minFaceSize,
'enableFaceTracking': faceConfig.enableTracking,
'minEmotionConfidence': faceConfig.minEmotionConfidence,
'accurateMode': faceConfig.accurateMode,
},
});
// result! is safe: native always returns an int on success, throws on failure.
return result!;
}