Реалізація AI-аналізу емоцій співрозмовника під час відеодзвінка

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Реалізація AI-аналізу емоцій співрозмовника під час відеодзвінка
Складний
~2-4 тижні
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Аналіз емоцій AI під час відеозвонків у мобільних додатках

Аналіз емоцій через камеру в реальному часі технічно можливий, але вимагає особливої уваги до етики та UX. Ось технічна сторона без прихування обмежень: моделі аналізу емоцій — одні з найкритикованіших інструментів AI за надійність.

Важливе обмеження, яке не слід ігнорувати

Академічний консенсус (Lisa Feldman Barrett, 2019) та практика показують: вираз обличчя не однозначно відображає емоції. Один і той самий паттерн руху лицьових м'язів означає різне для різних людей та культур. Тому:

  • Називати результат «емоцією» некоректно—«афективний стан» або «вираз обличчя» точніше
  • Системи ніколи не повинні використовуватися для кадрових чи юридичних рішень
  • Користувачі повинні явно дати згоду на аналіз свого обличчя

Це не просто етична примітка—це архітектурна вимога.

Технічний стек

Детекція обличчя — MediaPipe Face Detection (iOS/Android), Vision VNDetectFaceRectanglesRequest (iOS).

Розпізнавання виразів — кілька варіантів:

  • Apple Vision VNDetectFaceExpressionsRequest (iOS 17+) — вбудований, без хмари, 7 базових Action Units
  • Microsoft Azure Face API — хмарний, детальний, включає Action Units
  • AWS Rekognition (DetectFaces) — хмарний, 7 базових емоцій
  • FER+ модель (TFLite/CoreML) — open source, 8 класів, on-device

Для відеозвонків on-device обов'язково: не можна стримити обличчя людини в хмару без явної згоди.

Реалізація на iOS з Vision (On-Device)

// iOS 17+: аналіз виразу обличчя через Vision
class FaceExpressionAnalyzer {

    func analyze(sampleBuffer: CMSampleBuffer) async throws -> ExpressionResult? {
        guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return nil }

        let faceRequest = VNDetectFaceLandmarksRequest()

        // iOS 17: аналіз виразів — brow action units, тощо
        let expressionRequest = VNDetectFaceExpressionsRequest()

        let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer)
        try handler.perform([faceRequest, expressionRequest])

        guard let faceObs = faceRequest.results?.first as? VNFaceObservation,
              let exprObs = expressionRequest.results?.first as? VNFaceExpressionObservation else {
            return nil
        }

        return ExpressionResult(
            faceBox: faceObs.boundingBox,
            browLower: exprObs.browLowerQuirk,
            browRaise: exprObs.browRaiseRight + exprObs.browRaiseLeft,
            eyesClosed: exprObs.eyeBlinkLeft + exprObs.eyeBlinkRight,
            mouthSmile: exprObs.mouthSmileLeft + exprObs.mouthSmileRight,
            mouthFrown: exprObs.mouthFrownLeft + exprObs.mouthFrownRight,
            mouthOpen: exprObs.mouthOpen,
            jawOpen: exprObs.jawOpen
        )
    }
}

VNDetectFaceExpressionsRequest працює з Action Units—базовими рухами лицьових м'язів з FACS (Facial Action Coding System). Це коректніше, ніж «посмішка = щастя»: конкретна дія м'яза, без інтерпретації.

Агрегація за часом

Один кадр — шум. Використовуйте агрегацію по ковзному вікну:

class ExpressionAggregator {
    private var history: [ExpressionResult] = []
    private let windowSize = 15  // ~0.5 сек при 30fps

    func update(_ result: ExpressionResult) -> AggregatedExpression {
        history.append(result)
        if history.count > windowSize { history.removeFirst() }

        return AggregatedExpression(
            averageSmile: history.map { $0.mouthSmile }.average(),
            averageBrowRaise: history.map { $0.browRaise }.average(),
            averageJawOpen: history.map { $0.jawOpen }.average(),
            // Тренд: посмішка зростає або падає за останні N кадрів
            smileTrend: computeTrend(history.map { $0.mouthSmile })
        )
    }
}

Інтеграція у відеозвонки

Аналіз виконується на локальному відеопотоці з вашої камери, не з потоку опонента. Потік опонента на їхньому пристрої; у вас немає доступу до сирих кадрів через стандартний WebRTC. Два підходи:

SDK з підтримкою аналізу — Agora Video SDK дозволяє локальний відеопроцесор:

// Agora: обробка локального відео перед відправкою
class EmotionVideoProcessor: AgoraVideoFrameDelegate {

    func onCapture(_ videoFrame: AgoraOutputVideoFrame,
                   sourceType: AgoraVideoSourceType) -> Bool {
        // Аналізуйте своє обличчя перед відправкою
        if let pixelBuffer = videoFrame.pixelBuffer {
            Task {
                let result = try? await expressionAnalyzer.analyze(buffer: pixelBuffer)
                // результат аналізує ваші емоції, не опонента
                await MainActor.run {
                    emotionDelegate?.didUpdateExpression(result)
                }
            }
        }
        return true  // передайте кадр у потік без змін
    }
}

Peer-to-peer аналіз — обидва учасники аналізують свої власні вирази та передають результати (не відео) через data channel. WebRTC data channel для JSON пакетів—мінімальні витрати.

// Передача даних про емоції через WebRTC DataChannel
struct EmotionDataPacket: Codable {
    let timestamp: Double
    let smile: Float
    let browRaise: Float
    let eyesClosed: Float
    // НЕ передавайте зображення—лише числа
}

func sendEmotionData(_ expression: AggregatedExpression) {
    let packet = EmotionDataPacket(
        timestamp: Date().timeIntervalSince1970,
        smile: expression.averageSmile,
        browRaise: expression.averageBrowRaise,
        eyesClosed: expression.averageJawOpen
    )
    let data = try! JSONEncoder().encode(packet)
    dataChannel.sendData(RTCDataBuffer(data: data, isBinary: false))
}

Кожен учасник аналізує лише себе, але видить агреговані дані від опонента. Приватно та технічно чисто.

UX: як показувати результати

Показування «злий / сумний / щасливий» некоректно та потенційно образливо. Правильні варіанти:

  • Індикатор залучення: «опонент активно бере участь» (на основі browRaise + eyeBlink ритму)
  • Рівень уваги: нейтральний індикатор залучення без інтерпретації емоцій
  • Настрій розмови: агрегація обох учасників в єдиний «тепловий» показник
@Composable
fun EngagementIndicator(score: Float) {
    Box(
        modifier = Modifier
            .size(12.dp)
            .clip(CircleShape)
            .background(
                when {
                    score > 0.7f -> Color(0xFF4CAF50)   // залучено
                    score > 0.4f -> Color(0xFFFFC107)   // нейтрально
                    else -> Color(0xFF9E9E9E)            // пасивно
                }
            )
    )
}

Жодних обличь з емоціями, жодних словесних міток—лише нейтральний кольоровий індикатор.

Кошторис за часом

On-device аналіз виразу через Vision + базовий індикатор залучення у існуючому відеозвонку займає 1–2 тижні. Повна система з peer-to-peer передачею даних через data channel, агрегацією, аналітикою розмови, екраном згоди та підтримкою iOS + Android вимагає 2–4 тижнів.