gyanmeet_flutter_sdk 1.6.0 copy "gyanmeet_flutter_sdk: ^1.6.0" to clipboard
gyanmeet_flutter_sdk: ^1.6.0 copied to clipboard

PlatformAndroid
unlisted

Gyanmeet meeting SDK for Flutter — a self-contained video meeting widget with host controls, chat, polls, batch exams, certificate verification, and optional on-device AI proctoring.

gyanmeet_flutter_sdk #

A self-contained Flutter meeting widget for Gyanmeet. Drop a single widget into your app to get the full Gyanmeet meeting experience — video grid, host controls, chat, polls, and optional on-device AI proctoring.

The consumer embeds one widget. No API key ever lives in the client: your backend mints a short-lived external-join token, and the SDK performs the validate-join round-trip itself.

Usage #

import 'package:gyanmeet_flutter_sdk/gyanmeet_flutter_sdk.dart';

GyanmeetMeeting(
  backendUrl: 'https://your.gyanmeet.com/api', // REST base
  token: externalJoinToken,                   // minted by YOUR backend
  config: const GyanmeetConfig(
    chatMode: ChatMode.open,                   // or hostModerated
    videoMode: VideoMode.all,                  // or hostsOnly
    showParticipantsTab: true,
    showPolls: true,                           // show/hide the Polls button for all
    allowPoll: false,                          // let attendees create polls (hosts always can)
    showHeader: true,                          // show/hide the top meeting header
    showPreJoin: true,
    initialAudio: true,
    initialVideo: true,
    waitingOverlayText: 'Waiting for others…', // optional text under the join spinner
    enableAiMonitoring: true,                  // Enables on-device Face & Gaze detection
    enableExam: true,                          // batch exams, when the backend runs them
  ),
  primaryColor: '#366D5A',                     // optional brand theming
  onJoined: (meetingId, role) {},
  onLeave: () {},                              // local user left
  onEnded: () {},                              // host ended for everyone
  onError: (error) {},
  onFacePresenceChanged: (isPresent) {},       // emitted when face appears/disappears
  onGazeViolation: (reason) {},                // emitted for looking away/up/down
)

chat is a server meeting-setting the host toggles live in-meeting; polls are always available.

Features #

  • Join flow with optional PreJoin device check.
  • Video grid + pagination, debounced active-speaker pin, fullscreen tap.
  • Mic / camera / screen-share toggles, hand raise.
  • Host controls: mute / disable video & audio, promote/demote, remove, end meeting, live chat toggle.
  • Chat (open + host-moderated), participants panel, polls (create/vote/results).
  • Adaptive bandwidth: only the visible page and active speaker are subscribed, screen-share is always subscribed, and your upload is paused when no one is viewing you.
  • AI Monitoring: optional built-in on-device proctoring — face presence, gaze (exam mode), and identity verification — all running on-device.
  • Batch exams sat inside the class meeting, with host start/end and optional section selection.
  • Public certificate verification, with no session required.

AI Monitoring & proctoring #

When the server enables AI monitoring for a meeting, the SDK runs on-device checks and reports violations. The SDK itself enforces nothing — you decide what to do in your handlers (log, warn, end meeting, report to your backend).

Backends that implement the AI violation policy are the exception: there the server counts violations and removes the participant itself. See Server-enforced removal below.

Use the unified handler, the type-specific ones, or both (all fire):

GyanmeetMeeting(
  // one place for every violation kind
  onProctoringViolation: (v) {
    switch (v.type) {
      case ProctoringViolationType.identity:   // v.similarity set
      case ProctoringViolationType.gaze:       // v.reason: looking_far_*
      case ProctoringViolationType.faceAbsence:
    }
  },
  // or react to specific ones
  onFacePresenceChanged: (present) {},
  onGazeViolation: (reason) {},
  onIdentityMismatch: (similarity) {},
)

Server-enforced removal #

Some backends run a default AI violation policy: face-absence and identity mismatch feed one shared warning counter, and the participant is removed once the warnings run out. Removal is sticky — they cannot rejoin the meeting, or any other meeting in the same batch, without re-registering.

The SDK detects support automatically. Against a backend without the policy these callbacks never fire and nothing is reported, so no consumer change is needed either way.

GyanmeetMeeting(
  onAiViolationWarning: (v) {
    // v.message carries the server's copy, including the configured limits.
    showBanner(v.message, persistent: v.isFinalWarning);
  },
  onAiViolationRemoved: (v) {
    // Terminal — they cannot rejoin. Show a blocking notice, then leave.
    showRemovedScreen(v.message);
  },
)

Both callbacks are optional, and the SDK draws its own UI for whichever you leave unset — a warning pill under the connection banner, and a blocking notice on removal with a Leave button. Handle a callback and the SDK's version of it stays out of the way, so you can take over one without taking over both. The last warning before removal stays up until dismissed; earlier ones fade after ten seconds.

Gaze violations are never reported to the policy, so looking away cannot cost a warning. Reports are also suppressed for the duration of a host break.

Hosts and admins are exempt. A host or co-host runs the class rather than sits it, and a platform admin / super_admin joins to supervise it, so their face leaving frame is never a violation and they can never be removed from the meeting. Monitoring is not started for them at all, so no proctoring callbacks fire either. The platform role comes from the join response (user_role); the server applies the same exemption, so an older client cannot burn a warning against a host or admin.

Timings come from the server. How long a participant may be out of frame before it counts, and how long before the same violation is raised again, are both taken from GET /meetings/ai-violation-policy. The constants in the SDK are named kFallbackAi… and apply only until that call answers. Switching the camera off is treated as the same absence as walking away — it is not a way out of monitoring.

A later join by a removed participant fails with GyanmeetJoinError, reason aiViolationRemoved (or insufficientAttendance when they fell short of the batch's minimum attendance).

Identity verification #

Confirms the live face is the same person throughout. The first detected face is enrolled as a baseline; later frames are compared (cosine similarity) and onIdentityMismatch / a ProctoringViolation(type: identity) fires after a sustained mismatch.

A MobileFaceNet model ships with the SDK, so this works out of the box — no consumer setup. Tune or replace via config:

GyanmeetConfig(
  // override with your own asset, or set null to disable identity checks
  faceModelAssetPath: GyanmeetConfig.defaultFaceModelAssetPath,
  faceMatchThreshold: 0.6, // lower = more permissive
)

The bundled model is MobileFaceNet (BSD-3-Clause, © 2020 Marcos Carlomagno); see assets/models/mobilefacenet.LICENSE.

The identity gate (before joining) #

GyanmeetConfig(enableIdentityVerificationGate: true) puts a capture screen in front of the meeting. It runs in one of two modes, decided by whether you pass identityReferenceImage:

identityReferenceImage Mode Behaviour
a photo verify The selfie is matched against it — on-device, or through faceCompareUrl when set. A mismatch refuses entry and fires onIdentityMismatch.
null enroll Nothing to match against, so the selfie only has to hold a usable face. It is then the base for in-meeting monitoring.

Either way the selfie taken at the gate — not the reference photo — becomes the enrollment base for monitoring, so the class is matched against a capture from the same camera. Both modes persist the images to POST /verification-images when the backend supports it (MATCH / NO_MATCH for verify, ENROLLED for enroll).

GyanmeetMeeting(
  config: const GyanmeetConfig(enableIdentityVerificationGate: true),
  // omit for enroll mode; pass the applicant's photo for verify mode
  identityReferenceImage: referencePhotoBytes,
)

Batch exams #

When the backend supports exam phases and the meeting's hub is configured for one, the exam runs inside the class meeting rather than as a separate session:

  • The host sees a Start exam / End exam control in the meeting bar. Its terms — question count, time limit, pass mark, attempts — come from the hub's configuration and are not editable from here, so a host cannot change the rules of an exam while the class is sitting it.
  • Before starting, the host may confine the exam to one or more sections of the question bank. Selecting none draws from the entire bank, which is the behaviour of every exam that predates sections.
  • Each attendee gets their own randomised paper as an overlay. The overlay is layered on top of the meeting, so their camera, identity check and proctoring keep running while they sit it. Hosts invigilate and never sit the exam.
  • The countdown runs against the server's expiry rather than a client-side duration, and the paper auto-submits when time runs out.

Opt out entirely with GyanmeetConfig(enableExam: false). On a backend without exam routes the feature simply never appears — no configuration needed.

Certificate verification #

GyanmeetCertificateVerification is a standalone screen for checking a certificate. It requires no session and no join token, because whoever is verifying a certificate — an employer, an inspector — has no account with you.

GyanmeetCertificateVerification(
  backendUrl: 'https://your.gyanmeet.com/api',
  certificateId: scannedId, // optional: pre-fills and verifies immediately
  primaryColor: '#366D5A',
)

It accepts either a bare certificate ID or the full URL a certificate's QR code encodes, and reports one of VALID, REVOKED, INVALID or NOT_FOUND.

Two properties are worth being explicit about, because they are what make the result trustworthy:

  • Nothing displayed comes from the scanned code or the PDF. The ID is used purely as a lookup key; every fact shown is fetched from the backend, which re-checks the issuer's signature over its own stored record. Altering a name on a printed certificate changes nothing about what this screen reports.
  • No signing key ever reaches the client. Verification is performed server-side against the issuer's private key; the SDK only reads the verdict. CertificateVerificationService.getPublicKey() exposes the public half for third parties who want to check a signature independently.

A revoked certificate is reported as REVOKED, never as missing — "not found" would be indistinguishable from a forgery.

Platform setup #

The meeting needs camera/mic permissions, and screen share needs extra native plumbing.

Android #

AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />

The MediaProjection foreground service used for screen share is provided internally by the SDK — no extra wiring required.

iOS #

Info.plist:

<key>NSCameraUsageDescription</key>
<string>Camera access for video meetings.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access for audio in meetings.</string>

Screen-share publishing on iOS additionally requires a Broadcast Upload Extension + an App Group (registered under your Apple Developer account). Screen-share viewing works without it.

Release IPA builds (flutter build ipa): identity verification uses TF Lite, whose symbols Xcode strips by default, causing Failed to lookup symbol. Fix in Xcode → target Runner → Build Settings → Strip Style → change All Symbols to Non-Global Symbols. Android needs no change.

1
likes
130
points
178
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Gyanmeet meeting SDK for Flutter — a self-contained video meeting widget with host controls, chat, polls, batch exams, certificate verification, and optional on-device AI proctoring.

Repository (GitHub)
View/report issues

License

(pending) (license)

Dependencies

dio, flutter, google_mlkit_face_detection, image, livekit_client, livekit_components, path_provider, provider, tflite_flutter

More

Packages that depend on gyanmeet_flutter_sdk