""" VideoDetect Review UI - Flask Application Lightweight web interface for annotating low-confidence videos. Accessible via http://:5000 No authentication or SSL (per TC-06). """ import os from flask import Flask, jsonify, request, render_template_string app = Flask(__name__) # In-memory storage for demo (replace with DB queries in production) review_queue = [] # ------ Routes ------ @app.route("/") def index(): """Queue page - list of videos awaiting review.""" page = request.args.get("page", 1, type=int) per_page = 20 # Filter unannotated unannotated = [v for v in review_queue if not v.get("annotated")] total = len(unannotated) start = (page - 1) * per_page end = start + per_page videos = unannotated[start:end] return render_template_string( INDEX_TEMPLATE, videos=videos, page=page, per_page=per_page, total=total, total_pages=(total + per_page - 1) // per_page, ) @app.route("/api/review/queue") def api_queue(): """API: List videos in review queue.""" page = request.args.get("page", 1, type=int) per_page = 20 unannotated = [v for v in review_queue if not v.get("annotated")] total = len(unannotated) start = (page - 1) * per_page end = start + per_page return jsonify({ "videos": unannotated[start:end], "total": total, "page": page, "per_page": per_page, }) @app.route("/api/review/") def api_video_details(video_id): """API: Get video details for annotation.""" video = next((v for v in review_queue if v["id"] == video_id), None) if not video: return jsonify({"error": "Video not found"}), 404 return jsonify(video) @app.route("/api/review//label", methods=["POST"]) def api_label(video_id): """API: Submit annotation for a video.""" data = request.get_json() ground_truth = data.get("ground_truth") notes = data.get("notes", "") if ground_truth is None: return jsonify({"error": "ground_truth is required"}), 400 video = next((v for v in review_queue if v["id"] == video_id), None) if not video: return jsonify({"error": "Video not found"}), 404 video["annotated"] = True video["ground_truth"] = ground_truth video["notes"] = notes video["annotated_at"] = "2026-08-03T10:30:00Z" return jsonify({"status": "annotated", "video_id": video_id, "ground_truth": ground_truth}) @app.route("/api/review/stats") def api_stats(): """API: Review queue statistics.""" total = len(review_queue) annotated = sum(1 for v in review_queue if v.get("annotated")) unannotated = total - annotated avg_conf = sum(v.get("confidence_score", 0) for v in review_queue) / max(total, 1) dist = {"0.0-0.2": 0, "0.2-0.4": 0, "0.4-0.6": 0, "0.6-0.8": 0, "0.8-1.0": 0} for v in review_queue: c = v.get("confidence_score", 0) if c < 0.2: dist["0.0-0.2"] += 1 elif c < 0.4: dist["0.2-0.4"] += 1 elif c < 0.6: dist["0.4-0.6"] += 1 elif c < 0.8: dist["0.6-0.8"] += 1 else: dist["0.8-1.0"] += 1 return jsonify({ "total_in_queue": total, "annotated": annotated, "unannotated": unannotated, "avg_confidence": round(avg_conf, 4), "confidence_distribution": dist, }) # ------ HTML Templates ------ INDEX_TEMPLATE = """ VideoDetect - Review Queue

VideoDetect

Review Queue: {{ total }} videos | Page {{ page }} of {{ total_pages }}
{% if videos %}
{% for video in videos %} {% endfor %}
Video ID File Path Confidence Routing Model Frames Added Action
{{ video.id }} {{ video.file_path }} {{ "%.2f"|format(video.confidence_score) }} {{ video.routing_decision }} {{ video.model_version }} {{ video.frame_count }} {{ video.created_at[:10] if video.created_at else 'N/A' }} Annotate
{% else %}

No videos in review queue

All videos have been processed and classified.

{% endif %}
""" REVIEW_TEMPLATE = """ VideoDetect - Review #{{ video.id }}

VideoDetect

« Back to Queue

Video Information

Video ID
{{ video.id }}
Confidence
{{ "%.2f"|format(video.confidence_score) }}
Routing
{{ video.routing_decision }}
Model
{{ video.model_version }}
Frames
{{ video.frame_count }}
Duration
{{ "%.1f"|format(video.video_duration) if video.video_duration else 'N/A' }}s

Video

Contributing Frames (Top {{ video.top_k_frames|default(5) }})

{% for frame in video.contributing_frames %}
⏱ {{ "%.0f"|format(frame.timestamp) }}s {{ "%.2f"|format(frame.confidence) }}
{% endfor %}

Annotate

Does this video contain the target demographic?

""" # ------ Entry Point ------ if __name__ == "__main__": host = os.environ.get("FLASK_HOST", "0.0.0.0") port = int(os.environ.get("FLASK_PORT", "5000")) app.run(host=host, port=port, debug=False)