Add pet labeling UI overlay to recording playback

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Aaron D. Lee
2026-04-03 13:30:52 -04:00
parent 32955bc7e4
commit 4274d1373f
3 changed files with 615 additions and 1 deletions

View File

@@ -1,6 +1,10 @@
{% extends "base.html" %}
{% block title %}Vigilar — Recordings{% endblock %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/pet-labeling.css') }}">
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-3">
<h5 class="mb-0"><i class="bi bi-camera-video me-2"></i>Recordings</h5>
@@ -38,7 +42,10 @@
</button>
</div>
<div class="card-body p-0">
<video id="player-video" class="w-100" controls></video>
<!-- data-pet-labeling and data-detections are updated by JS when a recording is loaded -->
<div class="position-relative" id="player-video-wrap" data-pet-labeling="true" data-detections="[]">
<video id="player-video" class="w-100" controls></video>
</div>
</div>
</div>
@@ -90,6 +97,7 @@
</div>
<script src="{{ url_for('static', filename='js/timeline.js') }}"></script>
<script src="{{ url_for('static', filename='js/pet-labeling.js') }}"></script>
<script>
(function() {
'use strict';
@@ -112,11 +120,35 @@
playerVideo.src = '';
});
const playerVideoWrap = document.getElementById('player-video-wrap');
async function loadDetections(recordingId) {
try {
const resp = await fetch(`/recordings/${recordingId}/detections`);
if (!resp.ok) return [];
return await resp.json();
} catch (e) {
return [];
}
}
function handleSegmentClick(seg) {
playerCard.classList.remove('d-none');
playerTitle.textContent = `Recording #${seg.id} (${seg.type || 'motion'})`;
playerVideo.src = `/recordings/${seg.id}/download`;
playerVideo.play().catch(() => {});
// Reset overlay while detections load
if (window.PetLabeling) {
PetLabeling.updateDetections(playerVideoWrap, []);
}
// Fetch detections for this recording and render overlay
loadDetections(seg.id).then(detections => {
if (window.PetLabeling) {
PetLabeling.updateDetections(playerVideoWrap, detections);
}
});
}
function loadTimeline() {