DragonflAI SDK for iOS
Usage
Initialising
DragonflAI is a commercial product and requires licensing details during framework initialization. This should have been provided alongside this documentation, but if not please contact support@dragonflai.co.
Initialise early in your app’s startup.
For example here in the AppDelegate
method application:willFinishLaunchingWithOptions:
, we call useAccount()
with our license details.
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// To see debug log messages, pass a debug logger.
// NB: limit use to debug builds
DragonflAICore.useLogger(logger: ConsoleLogger(logLevel: .debug))
let account = Account(key: "your_key", secret: "your_secret")
DragonflAICore.useAccount(account)
return true
}
}
This is a basic example. You may wish to keep your credentials in config rather than code.
Moderating an image
Create a Moderator
instance, and pass an image to moderate()
.
Basic example using a closure to handle the result:
let image: UIImage = [your choice of image]
Moderator(algorithm: .nudity1).moderate(image) { (moderationResult) in
// *** update model in background thread ***
// *** example of expanding result ***
switch moderationResult {
case .success(let success):
switch success.analysis.decision {
case .ok:
// moderator allowed this image
case .blocked:
// moderator blocked this image
@unknown default:
// this covers any future return types
}
case .failure(let error):
// moderation error
}
DispatchQueue.main.async {
// *** update UI in main thread ***
}
}
⚠️ You should assume the closure is not called on the main queue, and dispatch UI updates accordingly.
Configuring a moderator
You may want to configure and reuse a Moderator
instance instead of creating it every time.
It can take an optional AlgorithmConfig object if you don’t want to use the defaults.
let config = AlgorithmConfig(blockThreshold: 50)
let moderator = Moderator(algorithm: .nudity1, config: config)
// ...
moderator.moderate(image) { (moderationResult) in
// use result
}
Promises (PromiseKit)
You can also get the results via PromiseKit promises.
moderator?.moderate(image)
.map { (success: ModeratorSuccess) in
// use analysis and metadata
}
.catch { error in
// handle error
}
Moderating a video stream
Streams of images can also be moderated in v1.4+. Typically these come from the device cameras and are passed to a codec for streaming or real-time communication.
Creating a StreamModerator
Get a StreamModerator
by asking a Moderator
to createStreamModerator()
class MyClass {
private var streamModerator: StreamModerator?
init() {
let moderator = Moderator(algorithm: .nudity1)
streamModerator = moderator.createStreamModerator()
streamModerator?.delegate = self
}
}
Supplying stream frames
Pass the frames, e.g. from the camera, to the process(frame:)
method.
extension MyClass: AVCaptureVideoDataOutputSampleBufferDelegate {
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
let pixelBuffer: CVPixelBuffer? = CMSampleBufferGetImageBuffer(sampleBuffer)
guard let pixelBuffer = pixelBuffer else {
return
}
streamModerator?.process(frame: pixelBuffer)
// pass pixelBuffer to codec (dependent on moderation result)
}
}
Getting results
To get results, assign a delegate, typically the same class.
extension MyClass: StreamModeratorDelegate {
func moderatorDidProduceNewResult(_ moderator: StreamModerator,
result moderationResult: ModeratorResult) {
guard moderator == self.streamModerator else {
return
}
// use moderationResult
}
func moderatorDidDropFrame(_ moderator: StreamModerator) {
// dropped frame
}
}
Getting stream statistics
The StreamModerator
can provide statistics on the number of frames it is receiving and processing.
func printStats() {
print("Input FPS: \(streamModerator.inputFramesPerSecond) / Processed FPS: \(moderator.processedFramesPerSecond)")
}
For consistent results, reset those stats when starting or resuming a session, so periods with no frames are not included.
func startVideoSession() {
// ...
streamModerator?.resetFPSStats()
// ...
}