Testing Guide: Phase 1-3 Implementation
This guide covers all features implemented in Phases 1-3 of the video processing enhancement project. Use this document to validate each feature works correctly before processing your 3,000+ video library.
Overview of Changes
Phase 1: Database Schema & Model Versioning
- Model version tracking (SigLIP, ArcFace, labels hash)
- New database columns for processing metadata
- FTS5 to regular table migration for proper score sorting
Phase 2: Processing Improvements
- Category-specific scene detection thresholds
- Enhanced hybrid approach (scene + interval fallback)
- Face crop size increased to 256x256 pixels
Phase 3: Settings UI
- Scene threshold controls in Settings page
- Preset configurations (static, moderate, dynamic)
- Minimum thumbnails configuration
Test 1: Backend Settings Module
1.1 Verify Presets Load Correctly
cd /home/user/Search-UI/backend
python3 -c "
import settings
print('Presets:')
for name, config in settings.PRESET_SETTINGS.items():
print(f' {name}: threshold={config[\"scene_threshold\"]}, interval={config[\"thumbnail_interval\"]}s, min={config[\"min_thumbnails\"]}')
print(f'\nDefaults: {settings.get_defaults()}')
"
Expected Output:
Presets:
static: threshold=0.12, interval=10.0s, min=30
moderate: threshold=0.2, interval=5.0s, min=35
dynamic: threshold=0.35, interval=2.0s, min=50
Defaults: {'scene_threshold': 0.29, 'thumbnail_interval': 3.0, 'min_thumbnails': 30}
1.2 Test get_processing_settings()
cd /home/user/Search-UI/backend
python3 -c "
import settings
print(f'Default: {settings.get_processing_settings()}')
settings.set_scene_threshold(0.35)
print(f'Updated: {settings.get_processing_settings()}')
"
Expected Output:
- Default returns
scene_threshold=0.2 - Updated returns
scene_threshold=0.35
Test 2: Search Images Model Versioning
2.1 Verify Version Constants
cd /home/user/Search-UI/backend
python3 -c "
# Check the source file for constants
with open('search_images.py', 'r') as f:
content = f.read()
import re
version_match = re.search(r'SIGLIP_MODEL_VERSION = \"([^\"]+)\"', content)
threshold_match = re.search(r'CLASSIFICATION_THRESHOLD = ([0-9.]+)', content)
print(f'SIGLIP_MODEL_VERSION: {version_match.group(1) if version_match else \"NOT FOUND\"}')
print(f'CLASSIFICATION_THRESHOLD: {threshold_match.group(1) if threshold_match else \"NOT FOUND\"}')
print('get_labels_version(): defined' if 'def get_labels_version()' in content else 'get_labels_version(): NOT FOUND')
"
Expected Output:
SIGLIP_MODEL_VERSION: siglip2-so400m-patch16-naflex-v1
CLASSIFICATION_THRESHOLD: 0.1
get_labels_version(): defined
2.2 Verify Database Schema (processed_videos table)
cd /home/user/Search-UI/backend
python3 -c "
from database import get_db
conn = get_db()
cursor = conn.execute('PRAGMA table_info(processed_videos)')
columns = [row[1] for row in cursor.fetchall()]
required = ['siglip_model_version', 'labels_version', 'classification_threshold',
'resolution_label', 'scene_threshold', 'duration_seconds', 'fps', 'total_frames']
for col in required:
status = 'β' if col in columns else 'β'
print(f'{status} {col}')
"
Expected: All columns marked with β
2.3 Verify image_categories is Regular Table (not FTS5)
cd /home/user/Search-UI/backend
python3 -c "
from database import get_db
conn = get_db()
# Check if it's a regular table (not FTS5 virtual table)
cursor = conn.execute(\"SELECT sql FROM sqlite_master WHERE name='image_categories'\")
row = cursor.fetchone()
if row:
sql = row[0]
if 'VIRTUAL TABLE' in sql.upper():
print('β Still FTS5 virtual table')
else:
print('β Regular table')
print(f' Schema: {sql[:100]}...')
else:
print('β Table not found')
# Check indexes
cursor = conn.execute(\"SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='image_categories'\")
indexes = [row[0] for row in cursor.fetchall()]
print(f' Indexes: {indexes}')
"
Expected:
- Regular table (not virtual)
- Indexes include: idx_categories_natural_key, idx_categories_category_name, idx_categories_score
Test 3: Face Search Constants
3.1 Verify Constants
cd /home/user/Search-UI/backend
python3 -c "
with open('face_search.py', 'r') as f:
content = f.read()
import re
crop_match = re.search(r'FACE_CROP_SIZE = (\d+)', content)
conf_match = re.search(r'MIN_FACE_CONFIDENCE = ([0-9.]+)', content)
version_match = re.search(r'ARCFACE_MODEL_VERSION = \"([^\"]+)\"', content)
print(f'FACE_CROP_SIZE: {crop_match.group(1) if crop_match else \"NOT FOUND\"} (expected: 256)')
print(f'MIN_FACE_CONFIDENCE: {conf_match.group(1) if conf_match else \"NOT FOUND\"}')
print(f'ARCFACE_MODEL_VERSION: {version_match.group(1) if version_match else \"NOT FOUND\"}')
"
Expected:
FACE_CROP_SIZE: 256 (expected: 256)
MIN_FACE_CONFIDENCE: 0.5
ARCFACE_MODEL_VERSION: arcface-mtcnn-v1
Test 4: Process Video Integration
4.1 Verify Scene Threshold Usage
cd /home/user/Search-UI/backend
grep -n "scene_threshold = processing_settings" process_video.py
grep -n "gt(scene" process_video.py
Expected: Both patterns found, showing scene_threshold is used dynamically from settings.
4.2 Verify FACE_CROP_SIZE Usage
cd /home/user/Search-UI/backend
grep -n "face_search.FACE_CROP_SIZE" process_video.py
Expected: Found in process_video.py (not hardcoded 128)
4.3 Verify Enhanced Hybrid Approach
cd /home/user/Search-UI/backend
grep -n "fallback_threshold" process_video.py
grep -n "int(min_thumbnails \* 0.5)" process_video.py
Expected: 50% threshold used for fallback decision
Test 5: API Endpoints
5.1 Start Backend Server
cd /home/user/Search-UI
tmux new -d -s backend "cd backend && source venv/bin/activate && uvicorn main:app --reload --host 0.0.0.0 2>&1 | tee ../backend.log"
sleep 3
tail -5 backend.log
Expected: Server running on http://0.0.0.0:8000
5.2 Test GET /api/settings/series
curl -s "http://localhost:8000/api/settings/series?language=E" | python3 -m json.tool | head -50
Expected Response Structure:
{
"settings": [...],
"available_categories": [...],
"presets": {
"static": {"scene_threshold": 0.12, ...},
"moderate": {...},
"dynamic": {...}
},
"defaults": {
"scene_threshold": 0.29,
"thumbnail_interval": 3.0,
"min_thumbnails": 30
}
}
5.3 Test POST /api/settings/series
# Add a test setting
curl -X POST "http://localhost:8000/api/settings/series?category=TestDrama&thumbnail_interval=2.0&scene_threshold=0.35&min_thumbnails=50&preset=dynamic"
# Verify it was added
curl -s "http://localhost:8000/api/settings/series?language=E" | python3 -c "
import sys, json
data = json.load(sys.stdin)
for s in data.get('settings', []):
if s.get('category') == 'TestDrama':
print(f'Found: {s}')
break
else:
print('Not found')
"
# Clean up
curl -s "http://localhost:8000/api/settings/series?language=E" | python3 -c "
import sys, json
data = json.load(sys.stdin)
for s in data.get('settings', []):
if s.get('category') == 'TestDrama':
print(f'Setting ID to delete: {s[\"id\"]}')
"
# Delete using the ID from above
# curl -X DELETE "http://localhost:8000/api/settings/series/{id}"
Test 6: Frontend Settings Page
6.1 Start Frontend Server
cd /home/user/Search-UI
tmux new -d -s frontend "cd frontend && npm run dev -- --host 0.0.0.0 2>&1 | tee ../frontend.log"
sleep 5
tail -5 frontend.log
6.2 Visual Testing Checklist
Open browser to http://localhost:5173 (or your network IP:5173)
Navigate to Settings page and verify:
Presets Section displays all three presets with values:
- Static: Threshold 0.12, Interval 10s, Min 30
- Moderate: Threshold 0.20, Interval 5s, Min 35
- Dynamic: Threshold 0.35, Interval 2s, Min 50
- Default: Shows current defaults
Add Series Setting Form has:
- Category dropdown (populated from available categories)
- Subcategory dropdown (optional)
- Preset dropdown (static, moderate, dynamic, or custom)
- Scene Threshold input (0.05-0.5, step 0.01)
- Fallback Interval input (0.5-60, step 0.5)
- Min Thumbnails input (10-200, step 5)
Preset Selection auto-fills values:
- Select "Static" preset β threshold=0.12, interval=10, min=30
- Select "Dynamic" preset β threshold=0.35, interval=2, min=50
- Custom settings inputs become disabled when preset selected
Current Settings Table shows columns:
- Category | Subcategory | Threshold | Interval | Min | Preset | Actions
Add/Delete works:
- Add a test category with dynamic preset
- Verify it appears in table with correct values
- Delete it and verify it's removed
Test 7: End-to-End Video Processing
7.1 Test with Single Video
Prerequisites: Have a test video in the system with known category.
# Process a single video with explicit settings
curl -X POST "http://localhost:8000/api/process-video?natural_key=YOUR_TEST_KEY&label=480p"
7.2 Verify Processing Metadata Saved
cd /home/user/Search-UI/backend
python3 -c "
from database import get_db
conn = get_db()
cursor = conn.execute('''
SELECT natural_key, resolution_label, scene_threshold,
siglip_model_version, labels_version, duration_seconds
FROM processed_videos
ORDER BY processed_at DESC
LIMIT 5
''')
print('Recent processed videos:')
for row in cursor.fetchall():
print(f' {row}')
"
Expected: Shows processing metadata including scene_threshold, model versions
7.3 Verify Thumbnail Count
After processing, check the thumbnails directory:
# Replace with actual natural_key and label
ls -la /home/user/Search-UI/backend/videos/{natural_key}/{label}/thumbnails/ | wc -l
Expected: Number of thumbnails appropriate for the content type and settings
Automated Test Script
Run the comprehensive test script:
cd /home/user/Search-UI
python3 scratchpad/2025-12-25-1708-test-phase1-3.py
Expected: All 6 modules pass (6/6)
Known Limitations
Phase 4 (Deferred)
The Unified Person system (combining face + speaker recognition) requires:
- ECAPA-TDNN model integration for speaker embeddings
- New Person management UI
- Cross-reference system for face β speaker associations
- This is planned for future implementation
Phase 5 (Deferred)
Validation and performance improvements:
- Bulk reprocessing detection
- Performance profiling
- These will be addressed after Phase 4
Troubleshooting
Backend Won't Start
# Check for Python environment issues
cd /home/user/Search-UI/backend
source venv/bin/activate
pip list | grep -E "fastapi|uvicorn|sqlite-vec"
Database Migration Issues
# Force recreate tables (WARNING: loses data)
cd /home/user/Search-UI/backend
python3 -c "
from database import get_db
conn = get_db()
# Drop and recreate problematic tables
conn.execute('DROP TABLE IF EXISTS image_categories')
# Re-run the app to recreate
"
Frontend Build Issues
cd /home/user/Search-UI/frontend
npm install
npm run build
Summary Checklist
Before processing your video library, verify:
- All automated tests pass (6/6)
- Backend API returns presets and defaults correctly
- Frontend Settings page displays and functions correctly
- Test video processes with correct scene threshold
- Processing metadata saved to database
- Thumbnail count appropriate for content type