Update pipeline.py
Browse files- pipeline.py +35 -9
pipeline.py
CHANGED
|
@@ -287,16 +287,21 @@ def draw_metric_bars(panel, bars_x_start, bar_y_top, bar_height, bar_width,
|
|
| 287 |
|
| 288 |
|
| 289 |
def draw_question_overlay(frame, text: str, width: int, height: int):
|
| 290 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 291 |
if frame is None or not text:
|
| 292 |
return frame
|
| 293 |
try:
|
| 294 |
-
font
|
| 295 |
-
font_scale
|
| 296 |
-
thickness
|
| 297 |
-
side_margin
|
| 298 |
bottom_limit = height - 270
|
| 299 |
-
line_height = 35
|
| 300 |
|
| 301 |
max_w = width - (2 * side_margin)
|
| 302 |
words, lines, current_line = text.split(' '), [], ""
|
|
@@ -644,6 +649,10 @@ def process_full_video(video_path: str, output_dir: str, questions_config: list,
|
|
| 644 |
Annotate the video with emotion wheel, face box, and live metric bars.
|
| 645 |
Returns the path to the raw annotated video (no audio).
|
| 646 |
Returns None on fatal failure.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 647 |
"""
|
| 648 |
if not os.path.exists(video_path):
|
| 649 |
log.error("process_full_video: video not found β %s", video_path)
|
|
@@ -721,6 +730,9 @@ def process_full_video(video_path: str, output_dir: str, questions_config: list,
|
|
| 721 |
next_text = f"Q) {next_q['question_text']}" if next_q else "Preparing..."
|
| 722 |
|
| 723 |
# ββ Live audio (every 10 frames) βββββββββββββββββββββββββββββ
|
|
|
|
|
|
|
|
|
|
| 724 |
if frame_idx % 10 == 0 and len(full_audio) > 1:
|
| 725 |
try:
|
| 726 |
start_s = max(0, int((current_time - 3) * sr))
|
|
@@ -773,11 +785,25 @@ def process_full_video(video_path: str, output_dir: str, questions_config: list,
|
|
| 773 |
draw_full_emotion_wheel(
|
| 774 |
frame, (width - 130, height - 100), 90, smooth_v, smooth_a, dom_emo
|
| 775 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 776 |
draw_metric_bars(
|
| 777 |
frame, 30, height - 160, 28, 200, 6,
|
| 778 |
-
|
| 779 |
-
|
| 780 |
-
|
| 781 |
)
|
| 782 |
|
| 783 |
if not active_answer:
|
|
|
|
| 287 |
|
| 288 |
|
| 289 |
def draw_question_overlay(frame, text: str, width: int, height: int):
|
| 290 |
+
"""
|
| 291 |
+
Draws a semi-transparent wrapped-text box above the wheel and bars.
|
| 292 |
+
|
| 293 |
+
CHANGE: font_scale reduced from 0.65 β 0.52 and line_height from 35 β 28
|
| 294 |
+
so the question text appears smaller on screen.
|
| 295 |
+
"""
|
| 296 |
if frame is None or not text:
|
| 297 |
return frame
|
| 298 |
try:
|
| 299 |
+
font = cv2.FONT_HERSHEY_DUPLEX
|
| 300 |
+
font_scale = 0.52 # CHANGED: was 0.65 β smaller text on screen
|
| 301 |
+
thickness = 1
|
| 302 |
+
side_margin = 50
|
| 303 |
bottom_limit = height - 270
|
| 304 |
+
line_height = 28 # CHANGED: was 35 β tighter rows to match smaller font
|
| 305 |
|
| 306 |
max_w = width - (2 * side_margin)
|
| 307 |
words, lines, current_line = text.split(' '), [], ""
|
|
|
|
| 649 |
Annotate the video with emotion wheel, face box, and live metric bars.
|
| 650 |
Returns the path to the raw annotated video (no audio).
|
| 651 |
Returns None on fatal failure.
|
| 652 |
+
|
| 653 |
+
CHANGE: Metric bars (confidence, clarity, stress) are forced to 0.0 whenever
|
| 654 |
+
active_answer is None β i.e. during AI speech / between questions β so that
|
| 655 |
+
the AI's own voice does not pollute the live analysis display.
|
| 656 |
"""
|
| 657 |
if not os.path.exists(video_path):
|
| 658 |
log.error("process_full_video: video not found β %s", video_path)
|
|
|
|
| 730 |
next_text = f"Q) {next_q['question_text']}" if next_q else "Preparing..."
|
| 731 |
|
| 732 |
# ββ Live audio (every 10 frames) βββββββββββββββββββββββββββββ
|
| 733 |
+
# We still compute live_scores every 10 frames so they are
|
| 734 |
+
# ready to display the moment the candidate starts answering.
|
| 735 |
+
# The decision of whether to SHOW them is made at render time.
|
| 736 |
if frame_idx % 10 == 0 and len(full_audio) > 1:
|
| 737 |
try:
|
| 738 |
start_s = max(0, int((current_time - 3) * sr))
|
|
|
|
| 785 |
draw_full_emotion_wheel(
|
| 786 |
frame, (width - 130, height - 100), 90, smooth_v, smooth_a, dom_emo
|
| 787 |
)
|
| 788 |
+
|
| 789 |
+
# CHANGE: only show real bar values while the candidate is
|
| 790 |
+
# answering (active_answer is not None). During AI speech
|
| 791 |
+
# or between questions the bars are rendered as 0 so the
|
| 792 |
+
# AI's own voice doesn't pollute the display.
|
| 793 |
+
if active_answer:
|
| 794 |
+
bar_confidence = live_scores["confidence_audio"]
|
| 795 |
+
bar_clarity = live_scores["clarity"]
|
| 796 |
+
bar_stress = live_scores["stress"]
|
| 797 |
+
else:
|
| 798 |
+
bar_confidence = 0.0
|
| 799 |
+
bar_clarity = 0.0
|
| 800 |
+
bar_stress = 0.0
|
| 801 |
+
|
| 802 |
draw_metric_bars(
|
| 803 |
frame, 30, height - 160, 28, 200, 6,
|
| 804 |
+
bar_confidence,
|
| 805 |
+
bar_clarity,
|
| 806 |
+
bar_stress,
|
| 807 |
)
|
| 808 |
|
| 809 |
if not active_answer:
|