Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions backend/core/audio_sensor_vertex.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import subprocess
import os

from .energy_analyzer import enrich_segments_with_energy


class AudioSensor:
def __init__(self, project_id: str, location: str = "us-central1"):
Expand Down Expand Up @@ -266,6 +268,9 @@ def create_semantic_segments(
"llm_reason": seg_data.get("reason", "")
})

if final_segments:
final_segments = enrich_segments_with_energy(final_segments, word_segments)

Comment on lines +271 to +273
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

create_semantic_segments() (and _fallback_segmentation()) now enrich segments with energy_level, word_rate, and pause_count, but the method docstring still states it returns only text, start, end, and duration. Please update the docstring (and any callers’ expectations, if documented elsewhere) to reflect the expanded segment schema.

Copilot uses AI. Check for mistakes.
print(f"✓ LLM created {len(final_segments)} semantic segments")
for i, seg in enumerate(final_segments):
print(f" Segment {i+1}: {seg['text'][:40]}... ({seg['duration']:.1f}s)")
Expand Down Expand Up @@ -324,6 +329,9 @@ def _fallback_segmentation(
"duration": current["end"] - current["start"]
})

if segments:
segments = enrich_segments_with_energy(segments, word_segments)

return segments

def cleanup(self):
Expand Down
80 changes: 80 additions & 0 deletions backend/core/energy_analyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""
Energy Analyzer - Pacing Analysis for Audio Segments
Analyzes word rate, pauses, and energy levels for B-roll matching
"""
Comment on lines +1 to +4
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

PR description mentions adding an EnergyAnalyzer class, but this module currently only adds standalone functions. Either introduce the class as described, or update the PR description/module docs to match the actual API to avoid confusing downstream users.

Copilot uses AI. Check for mistakes.

from typing import Dict, List


def calculate_word_rate(word_segments: List[Dict]) -> float:
"""Calculate average speaking rate in words per second"""
if len(word_segments) < 2:
return 0.0
total_words = len(word_segments)
total_duration = word_segments[-1]["end"] - word_segments[0]["start"]
return total_words / total_duration if total_duration > 0 else 0.0


def analyze_pauses(word_segments: List[Dict], threshold: float = 0.5) -> Dict:
"""Analyze pause patterns in word segments"""
pauses = []
for i, word in enumerate(word_segments[:-1]):
gap = word_segments[i + 1]["start"] - word["end"]
if gap > threshold:
pauses.append(gap)
return {
"pause_count": len(pauses),
"total_pause_duration": sum(pauses),
"avg_pause_duration": sum(pauses) / len(pauses) if pauses else 0.0,
}


def classify_energy(word_rate: float, pause_analysis: Dict) -> str:
"""Classify segment energy level: low, medium, high"""
if word_rate > 3.0 and pause_analysis["pause_count"] < 2:
return "high"
elif word_rate < 1.5 and pause_analysis["pause_count"] > 4:
return "low"
else:
return "medium"


def tag_segment_energy(segment: Dict, word_segments: List[Dict]) -> Dict:
"""Add energy metadata to segment based on word segments within time range"""
seg_start = segment["start"]
seg_end = segment["end"]

segment_words = [
w for w in word_segments
if w["start"] >= seg_start and w["end"] <= seg_end
]

if not segment_words:
segment_words = [
w for w in word_segments
if w["start"] >= seg_start and w["start"] < seg_end
]

if len(segment_words) < 2:
word_rate = 0.0
pause_analysis = {"pause_count": 0, "total_pause_duration": 0.0, "avg_pause_duration": 0.0}
else:
word_rate = calculate_word_rate(segment_words)
pause_analysis = analyze_pauses(segment_words)

energy_level = classify_energy(word_rate, pause_analysis)

return {
**segment,
"energy_level": energy_level,
"word_rate": round(word_rate, 2),
"pause_count": pause_analysis["pause_count"],
}


def enrich_segments_with_energy(
segments: List[Dict],
word_segments: List[Dict]
) -> List[Dict]:
"""Enrich all segments with energy analysis metadata"""
return [tag_segment_energy(seg, word_segments) for seg in segments]
1 change: 1 addition & 0 deletions energy-analysis.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Energy Analysis branch
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

This file looks like an accidental branch marker / placeholder and doesn’t appear related to the energy analysis feature. Consider removing it from the PR (or moving any intended documentation into README/DEPLOYMENT docs).

Copilot uses AI. Check for mistakes.
1 change: 1 addition & 0 deletions segmentation.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Segmentation branch
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

This file looks like an accidental branch marker / placeholder and doesn’t appear related to the energy analysis feature. Consider removing it from the PR (or moving any intended documentation into README/DEPLOYMENT docs).

Copilot uses AI. Check for mistakes.