Skip to content

feat: implement AI-driven behavioral video sentiment analyzer (#1744) - #1749

Open
desireddymohithreddy0925 wants to merge 2 commits into
Canopus-Labs:mainfrom
desireddymohithreddy0925:feat/1744-ai-video-sentiment
Open

feat: implement AI-driven behavioral video sentiment analyzer (#1744)#1749
desireddymohithreddy0925 wants to merge 2 commits into
Canopus-Labs:mainfrom
desireddymohithreddy0925:feat/1744-ai-video-sentiment

Conversation

@desireddymohithreddy0925

@desireddymohithreddy0925 desireddymohithreddy0925 commented Aug 10, 2026

Copy link
Copy Markdown

Fixes #1744

Description

This PR implements the foundation for the AI-Driven Behavioral Interview Video Sentiment Analyzer. It introduces a client-side WebAssembly pipeline using face-api.js to process video frames locally, evaluating user sentiment in real-time during mock interviews.

Changes Made

  • Created VideoSentimentAnalyzer.jsx in frontend/src/components/.
  • Integrated face-api.js for facial expression recognition.
  • Built a UI for starting/stopping the webcam and rendering real-time AI confidence metrics.

Checklist

  • Code compiles without errors
  • Implemented client-side ML pipeline for privacy compliance
  • Tested locally

Summary

  • Added face-api.js for client-side facial expression analysis.
  • Added VideoSentimentAnalyzer with webcam controls, local model processing, real-time expression metrics, and completion callbacks.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The frontend adds a webcam sentiment analyzer. It loads face-api.js models, detects facial expressions during a session, displays expression percentages, and reports the latest results when the session ends.

Changes

Video sentiment analysis

Layer / File(s) Summary
Model setup and dependency
frontend/package.json, frontend/src/components/VideoSentimentAnalyzer.jsx
The frontend adds face-api.js and loads the detector and facial expression models from /models.
Webcam capture and expression analysis
frontend/src/components/VideoSentimentAnalyzer.jsx
The component starts and stops webcam capture, detects expressions every second, and reports the latest results when the session ends.
Analyzer interface and completion callback
frontend/src/components/VideoSentimentAnalyzer.jsx
The component renders loading feedback, session controls, webcam video, and expression percentages.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant VideoSentimentAnalyzer
  participant Browser
  participant FaceApi
  User->>VideoSentimentAnalyzer: Start analysis
  VideoSentimentAnalyzer->>Browser: Request webcam access
  Browser-->>VideoSentimentAnalyzer: Return video stream
  VideoSentimentAnalyzer->>FaceApi: Detect facial expressions
  FaceApi-->>VideoSentimentAnalyzer: Return expression scores
  User->>VideoSentimentAnalyzer: End session
  VideoSentimentAnalyzer-->>User: Display final expression results
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements local webcam facial-expression analysis, but it does not provide speech metrics, eye contact, speech clarity, or a post-interview report. Implement or explicitly scope the missing speech, eye-contact, confidence, and post-interview reporting requirements from issue #1744.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the implementation of the behavioral video sentiment analyzer and references issue #1744.
Out of Scope Changes check ✅ Passed The dependency addition and VideoSentimentAnalyzer component directly support the linked issue objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/VideoSentimentAnalyzer.jsx`:
- Around line 16-18: Update the model-loading flow in VideoSentimentAnalyzer to
store a user-visible error when either face-api model request fails, instead of
only logging it in the catch block. Render the error state in place of “Loading
AI Models...” with a retry action that re-invokes the existing model-loading
function and resets the error state.
- Around line 23-29: Update startVideo and the component lifecycle effect to
store the acquired stream in a ref, stop all tracks on effect cleanup, and stop
any existing stream before assigning a replacement; preserve the End Session
behavior while ensuring unmount releases the webcam.
- Around line 13-14: Add the Tiny Face Detector and face-expression model
manifests and weight shards under frontend/public/models, ensuring the existing
loadFromUri('/models') calls in the model-loading effect can retrieve them.
Alternatively, update both loadFromUri calls to the deployed URL containing
these assets.
- Around line 43-55: Update handleVideoPlay to store the created interval
identifier in a ref instead of leaving it unmanaged. Clear that interval in
stopVideo and the component’s unmount cleanup, preventing duplicate detection
loops after playback restarts while preserving the existing analysis behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e35b4cb-f376-496a-9613-3f81b9af78a6

📥 Commits

Reviewing files that changed from the base of the PR and between fd811d3 and ae57342.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • frontend/package.json
  • frontend/src/components/VideoSentimentAnalyzer.jsx

Comment thread frontend/src/components/VideoSentimentAnalyzer.jsx
Comment thread frontend/src/components/VideoSentimentAnalyzer.jsx
Comment thread frontend/src/components/VideoSentimentAnalyzer.jsx
Comment thread frontend/src/components/VideoSentimentAnalyzer.jsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/src/components/VideoSentimentAnalyzer.jsx (2)

44-49: 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Prevent overlapping face detections.

setInterval invokes the async callback every second without waiting for the previous detectAllFaces call. If inference takes longer than one second, concurrent calls can consume excessive CPU and update expressions out of order. Use one in-flight loop or a recursive setTimeout scheduled after each detection.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/VideoSentimentAnalyzer.jsx` around lines 44 - 49,
Update the interval logic around the face detection callback in
VideoSentimentAnalyzer so only one detectAllFaces invocation is in flight at a
time. Replace setInterval with a recursive setTimeout or equivalent sequential
loop that schedules the next run only after detection completes, while
preserving the existing videoRef.current and isAnalyzing checks and expression
updates.

24-29: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Show camera-start failures in the UI.

If getUserMedia rejects, the handler logs the error only. The user sees no reason for failure and no recovery state. Track a camera error and render a retry message or action.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/VideoSentimentAnalyzer.jsx` around lines 24 - 29,
Update the getUserMedia error handler in VideoSentimentAnalyzer to store the
camera-start failure in component state instead of only logging it, reset the
analyzing state as needed, and render that error with a retry message or action
so users can recover from camera permission or startup failures.
🧹 Nitpick comments (1)
frontend/src/components/VideoSentimentAnalyzer.jsx (1)

76-85: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Prevent analyzer controls from submitting a parent form.

If this component is rendered inside a <form>, neither button declares type, so both default to submit. Clicking Start or End can submit the parent form and unmount the analyzer. Add type="button" to both controls.

Proposed button fix
-<button onClick={startVideo}
+<button type="button" onClick={startVideo}
...
-<button onClick={stopVideo}
+<button type="button" onClick={stopVideo}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/VideoSentimentAnalyzer.jsx` around lines 76 - 85,
Prevent the analyzer controls from submitting a containing form by adding
type="button" to both buttons rendered in the !isAnalyzing conditional around
startVideo and stopVideo, while preserving their existing click handlers and
styling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/VideoSentimentAnalyzer.jsx`:
- Line 39: Update the expression state handling in the video analysis component:
set expressions to {} when detections.length is zero, and reset it at the start
of startVideo before processing the new stream. Ensure onAnalysisComplete
receives the cleared state when no face is detected and cannot retain the
previous session’s expression.

---

Outside diff comments:
In `@frontend/src/components/VideoSentimentAnalyzer.jsx`:
- Around line 44-49: Update the interval logic around the face detection
callback in VideoSentimentAnalyzer so only one detectAllFaces invocation is in
flight at a time. Replace setInterval with a recursive setTimeout or equivalent
sequential loop that schedules the next run only after detection completes,
while preserving the existing videoRef.current and isAnalyzing checks and
expression updates.
- Around line 24-29: Update the getUserMedia error handler in
VideoSentimentAnalyzer to store the camera-start failure in component state
instead of only logging it, reset the analyzing state as needed, and render that
error with a retry message or action so users can recover from camera permission
or startup failures.

---

Nitpick comments:
In `@frontend/src/components/VideoSentimentAnalyzer.jsx`:
- Around line 76-85: Prevent the analyzer controls from submitting a containing
form by adding type="button" to both buttons rendered in the !isAnalyzing
conditional around startVideo and stopVideo, while preserving their existing
click handlers and styling.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0b5506ef-11fd-412f-9c47-b0050b6e81de

📥 Commits

Reviewing files that changed from the base of the PR and between ae57342 and 0fc2994.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • frontend/package.json
  • frontend/src/components/VideoSentimentAnalyzer.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/package.json

}
setIsAnalyzing(false);
if (onAnalysisComplete) {
onAnalysisComplete(expressions);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Clear expression state between frames and sessions.

expressions is updated only when detections.length > 0, and startVideo never resets it. If the face leaves the frame or a new session has no detection yet, the UI and onAnalysisComplete(expressions) can report the previous session's last expression. Set {} when no face is detected and when a new stream starts.

Proposed state reset
 .then((stream) => {
   videoRef.current.srcObject = stream;
+  setExpressions({});
   setIsAnalyzing(true);
 ...
-        if (detections.length > 0) {
-          setExpressions(detections[0].expressions);
-        }
+        setExpressions(detections[0]?.expressions ?? {});

Also applies to: 51-52

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/VideoSentimentAnalyzer.jsx` at line 39, Update the
expression state handling in the video analysis component: set expressions to {}
when detections.length is zero, and reset it at the start of startVideo before
processing the new stream. Ensure onAnalysisComplete receives the cleared state
when no face is detected and cannot retain the previous session’s expression.

@github-actions github-actions Bot added the merge ready PR is mergeable and has no conflicts label Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge ready PR is mergeable and has no conflicts

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: AI-Driven Behavioral Interview Video Sentiment Analyzer

1 participant