Video Processing
Real-time video processing on iOS with camera preview and deflickering
This guide covers real-time video processing on iOS, including camera preview with AVCaptureSession and deflickering configuration.
Understanding deflickering
When processing video frames, the correction applied to each frame can vary based on the frame's content. Without temporal smoothing, this causes visible flickering between frames.
The SDK provides deflickering parameters that smooth corrections across frames:
| Parameter | Description | Recommended |
|---|---|---|
deflickerCurve | Smooths tone curve adjustments (0.0–1.0) | 0.08 |
deflickerImage | Smooths overall corrections (0.0–1.0) | 0.9 |
skip | Process every Nth frame (0 = all) | 0–1 |
Deflickering has a cumulative effect. Call resetDeflicker() when switching cameras, starting a new video, or seeking to a different position.
Camera preview with AVCaptureSession
Process live camera frames using AVCaptureSession:
class CameraViewController: UIViewController {
private let pfcDynamic: PFCDynamic
private let session = AVCaptureSession()
private let videoOutput = AVCaptureVideoDataOutput()
private let videoQueue = DispatchQueue(label: "video.processing")
private var previewImageView: UIImageView!
private var dynamicStrength: Float = 0.8
init(apiKey: String, certificate: String) {
self.pfcDynamic = PFCDynamic(apiKey: apiKey, certificate: certificate)
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
// Verify initialization
let status = pfcDynamic.checkStatus()
if status != 0 {
print("SDK initialization failed with code: \(status)")
return
}
// Configure deflickering for video
pfcDynamic.setParams(
deflickerCurve: 0.08,
deflickerImage: 0.9,
skip: 0
)
setupCamera()
}
@objc func switchCamera() {
// Reset deflicker when switching cameras
pfcDynamic.resetDeflicker()
// Switch camera logic...
}
}
extension CameraViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
func captureOutput(
_ output: AVCaptureOutput,
didOutput sampleBuffer: CMSampleBuffer,
from connection: AVCaptureConnection
) {
guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer),
let cgImage = createCGImage(from: imageBuffer) else { return }
do {
let processed = try pfcDynamic.processImage(
cgImage,
strength: dynamicStrength
)
let image = UIImage(cgImage: processed)
DispatchQueue.main.async {
self.previewImageView.image = image
}
} catch {
print("Frame processing error: \(error)")
}
}
private func createCGImage(from imageBuffer: CVImageBuffer) -> CGImage? {
let ciImage = CIImage(cvImageBuffer: imageBuffer)
let context = CIContext()
return context.createCGImage(ciImage, from: ciImage.extent)
}
private func setupCamera() {
// AVCaptureSession setup code here
}
}Frame skipping for performance
Use the skip parameter to reduce processing load:
// Process all frames (highest quality, most CPU)
pfcDynamic.setParams(deflickerCurve: 0.08, deflickerImage: 0.9, skip: 0)
// Skip every other frame (good balance)
pfcDynamic.setParams(deflickerCurve: 0.08, deflickerImage: 0.9, skip: 1)
// Skip 2 frames between processed frames (performance mode)
pfcDynamic.setParams(deflickerCurve: 0.08, deflickerImage: 0.9, skip: 2)When skipping frames, the SDK reuses the previous frame's correction for skipped frames, maintaining visual consistency.
When to reset deflicker
Always call resetDeflicker() in these situations:
| Scenario | Action |
|---|---|
| Switch camera (front/back) | Call resetDeflicker() |
| Start new video recording | Call resetDeflicker() |
| Seek in video player | Call resetDeflicker() |
| Load new video file | Call resetDeflicker() |
| Resume from background | Call resetDeflicker() |
VIDEO-SDK Version 1.0.0.23 built from aa5eef97017e23db1d3051b079500606825ef474 on 5-6-2023.
Copyright © 2026 EyeQ Imaging Inc. All rights reserved.