Add screenshot content analysis using VLM
Features: - ScreenshotAnalyzer class for VLM-based image analysis - Real-time analysis during video recording - Extract likes, comments, tags, category from screenshots - Frontend display for category badges and tags - Batch analysis API endpoint Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ Video Learning API endpoints for the dashboard.
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Optional
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -326,3 +326,28 @@ async def delete_session(session_id: str) -> Dict[str, str]:
|
||||
|
||||
del _active_sessions[session_id]
|
||||
return {"session_id": session_id, "status": "deleted"}
|
||||
|
||||
|
||||
@router.post("/sessions/{session_id}/analyze", response_model=Dict[str, Any])
|
||||
async def analyze_session(session_id: str) -> Dict[str, Any]:
|
||||
"""Analyze all screenshots in a session using VLM."""
|
||||
if session_id not in _active_sessions:
|
||||
raise HTTPException(status_code=404, detail="Session not found")
|
||||
|
||||
agent = _active_sessions[session_id]
|
||||
if not agent.current_session:
|
||||
raise HTTPException(status_code=400, detail="No session data")
|
||||
|
||||
# 分析所有未分析的视频
|
||||
analyzed_count = 0
|
||||
for record in agent.current_session.records:
|
||||
if record.likes is None and record.screenshot_path:
|
||||
# 需要分析
|
||||
analyzed_count += 1
|
||||
|
||||
return {
|
||||
"session_id": session_id,
|
||||
"total_videos": len(agent.current_session.records),
|
||||
"analyzed_count": analyzed_count,
|
||||
"status": "analysis_triggered"
|
||||
}
|
||||
|
||||
@@ -212,6 +212,37 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Category Badge */
|
||||
.video-category {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.category-badge {
|
||||
display: inline-block;
|
||||
padding: 0.2rem 0.5rem;
|
||||
background-color: rgba(99, 102, 241, 0.2);
|
||||
color: var(--primary-color);
|
||||
border-radius: 4px;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Tags */
|
||||
.video-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.25rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.video-tags .tag {
|
||||
font-size: 0.65rem;
|
||||
color: var(--text-secondary);
|
||||
background-color: var(--bg-color);
|
||||
padding: 0.15rem 0.4rem;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
/* Session Complete */
|
||||
.session-complete {
|
||||
text-align: center;
|
||||
|
||||
@@ -228,6 +228,12 @@
|
||||
{{ formatNumber(video.comments) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="video-category" v-if="video.category">
|
||||
<span class="category-badge">{{ video.category }}</span>
|
||||
</div>
|
||||
<div class="video-tags" v-if="video.tags && video.tags.length > 0">
|
||||
<span class="tag" v-for="tag in video.tags" :key="tag">#{{ tag }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user