This guide provides step-by-step instructions for manually testing the Audio Sync Platform, including the sync with scoreboard feature.
- Prerequisites
- System Health Checks
- Testing Audio Streaming
- Testing OCR Upload
- Testing Sync with Scoreboard
- Complete End-to-End Test
- Troubleshooting
- Test Checklist
cd /path/to/applications
docker compose up -dWait ~30 seconds for all services to be healthy:
docker compose psExpected output:
NAME STATUS
audio-sync-backend Up 2 minutes (healthy)
audio-sync-ffmpeg Up 2 minutes (healthy)
audio-sync-frontend Up 2 minutes
audio-sync-indexer Up 2 minutes
audio-sync-ocr Up 2 minutes
# Backend API
curl http://localhost:4000/api/health
# Frontend
curl http://localhost:3030
# OCR Service
curl http://localhost:3001/health- Browser: Chrome, Firefox, or Safari (latest version)
- curl: For API testing
- jq: For JSON formatting (optional)
- Test Images: Sample scoreboard screenshots
# Check backend health
curl -s http://localhost:4000/api/health | jq .
# Expected response:
# {
# "status": "ok",
# "timestamp": "2025-12-11T18:00:00.000Z",
# "service": "audio-sync-backend",
# "version": "1.0.0"
# }# Check if HLS playlist exists
curl -I http://localhost:4000/api/hls/playlist
# Expected: HTTP/1.1 200 OK (or 404 if stream not started yet)# Check for any errors in services
docker logs audio-sync-backend --tail 50
docker logs audio-sync-ffmpeg --tail 50
docker logs audio-sync-indexer --tail 50
docker logs audio-sync-ocr --tail 50
docker logs audio-sync-frontend --tail 50Look for:
- ✅ No error messages
- ✅ Services reporting "ready" or "listening"
- ✅ No connection failures
- Open browser and navigate to: http://localhost:3030
- Click "Open Player" button
- You should see the Audio Player page
- Click the Play button (blue button)
- Verify:
- ✅ Button changes to "Pause"
- ✅ Green pulsing indicator appears
- ✅ Status shows "Playing"
- ✅ Current time counter starts updating
Expected Behavior:
- If stream is available: Audio should play
- If no stream yet: You may see errors in console (normal during initial startup)
-
While playing, click the +10s button
-
Verify:
- ✅ Time jumps forward ~10 seconds
- ✅ Audio continues playing
-
Click the -10s button
-
Verify:
- ✅ Time jumps backward ~10 seconds
-
Test fine controls:
- Click +1.5s: time increases by 1.5 seconds
- Click -1.5s: time decreases by 1.5 seconds
-
Click Pause button
-
Verify:
- ✅ Status changes to "Paused"
- ✅ Indicator turns gray
- ✅ Time counter stops
-
Click Play again
-
Verify:
- ✅ Audio resumes from same position
- ✅ Time counter continues
Create or use sample scoreboard screenshots. For testing, you can use the provided test images or create your own:
Good Test Images Should Have:
- Clear, legible scoreboard with game clock (MM:SS format)
- Good lighting (not too dark or bright)
- Scoreboard centered in frame
- High resolution (720p or higher)
Create a Test Image: You can use any scoreboard image or create a simple one:
# Create a test directory
mkdir -p test-images
# Download or add your scoreboard screenshots here
# Supported formats: JPEG, PNG# Test with a sample image
curl -X POST http://localhost:4000/api/ocr/upload \
-F "image=@test-images/scoreboard.jpg" \
| jq .Expected Response:
{
"success": true,
"result": {
"clock": "12:34",
"score": {
"home": 21,
"away": 17
},
"confidence": 0.89,
"metadata": {
"processingTime": 1823,
"imageSize": {
"width": 1920,
"height": 1080
},
"rawText": "12:34\\nHOME 21 AWAY 17\\nQ3"
}
}
}Verify:
- ✅
successistrue - ✅
clockmatches the time in your image (format: "MM:SS") - ✅
confidenceis between 0.0 and 1.0 - ✅
processingTimeis < 3000ms
# Test with invalid file type
curl -X POST http://localhost:4000/api/ocr/upload \
-F "image=@test.txt" \
| jq .
# Expected: 400 Bad Request
# {
# "statusCode": 400,
# "message": "Only JPEG and PNG images are allowed"
# }# Test without file
curl -X POST http://localhost:4000/api/ocr/upload | jq .
# Expected: 400 Bad Request
# {
# "statusCode": 400,
# "message": "No file uploaded"
# }- Navigate to: http://localhost:3030
- Click "Open Player"
- Start audio playback (click Play button)
- Click the "Sync with Scoreboard" button (top-right)
- The sync modal should open
- Verify:
- ✅ Upload area is visible
- ✅ "Browse Files" button works
- ✅ Drag-and-drop zone is active
Method A: Drag and Drop
- Drag a scoreboard image file onto the upload area
- Release to upload
Method B: Click to Browse
- Click "Browse Files" button
- Select a scoreboard image from your computer
- Click "Open"
After upload, the modal will show:
- Image Preview: Your uploaded image
- Processing Indicator: Spinner while processing (2-3 seconds)
- OCR Results:
- Game Clock: Detected time (e.g., "12:34")
- Score: Detected score (e.g., "21 - 17")
- Confidence Meter: Visual indicator (green/yellow/red)
- Confidence Score: Percentage (e.g., "89%")
- Metadata: Processing time, image size, raw text
Verify Results:
- ✅ Clock time matches what's in your image
- ✅ Confidence score > 70% (ideally > 80%)
- ✅ Processing time < 3 seconds
- ✅ No error messages
- If results look good, click "Sync Player" button
- Verify:
- ✅ Success message appears: "Synced to XX:XX"
- ✅ Modal closes
- ✅ Audio player seeks to detected time
- ✅ Green confirmation banner shows synced timestamp
- ✅ Playback continues from new position
OR
- If results look wrong, click "Retake Photo" button
- Upload area reappears
- Try again with a better image
# Upload scoreboard image
OCR_RESPONSE=$(curl -s -X POST http://localhost:4000/api/ocr/upload \
-F "image=@test-images/scoreboard.jpg")
echo "$OCR_RESPONSE" | jq .
# Extract clock and confidence
CLOCK=$(echo "$OCR_RESPONSE" | jq -r '.result.clock')
CONFIDENCE=$(echo "$OCR_RESPONSE" | jq -r '.result.confidence')
echo "Detected Clock: $CLOCK"
echo "Confidence: $CONFIDENCE"# Sync player with detected clock time
SYNC_RESPONSE=$(curl -s -X POST http://localhost:4000/api/sync \
-H "Content-Type: application/json" \
-d "{
\"clock\": \"$CLOCK\",
\"confidence\": $CONFIDENCE
}")
echo "$SYNC_RESPONSE" | jq .Expected Response:
{
"success": true,
"syncedTimestamp": 754, // seconds
"confidence": 0.92,
"drift": 0.3, // seconds
"metadata": {
"segmentId": 377,
"segmentStart": 754,
"segmentEnd": 756,
"clockTime": "12:34"
}
}OR if segment not found:
{
"statusCode": 404,
"message": "No segment found for clock time: 12:34"
}Verify:
- ✅
successistrue - ✅
syncedTimestampis a positive number - ✅
confidenceis high (> 0.80) - ✅
driftis small (< 1.0 second) - ✅
metadataincludes segment information
This test simulates a complete user journey from start to finish.
# Ensure all services are running
docker compose ps
# Verify backend health
curl -s http://localhost:4000/api/health | jq .- Open browser: http://localhost:3030
- Click "Open Player"
- Click "Play" button
- Wait for audio to start (may take 5-10 seconds for first segments)
- Find or create a clear scoreboard image
- Note the actual time shown on scoreboard (e.g., 12:34)
- Save as JPEG or PNG
- In the player page, click "Sync with Scoreboard"
- Upload your scoreboard image
- Wait for OCR processing (~2 seconds)
Check that:
- ✅ Detected clock time matches actual time in image
- ✅ Confidence score > 70% (preferably > 80%)
- ✅ Processing completed within 3 seconds
- ✅ No errors displayed
- Click "Sync Player" button
- Observe:
- ✅ Success message appears
- ✅ Modal closes
- ✅ Audio seeks to new position
- ✅ Time display updates to synced time
- ✅ Playback continues smoothly
- Compare current player time with original scoreboard time
- They should be within ±1 second
- If drift is larger, check confidence scores
After syncing, verify:
- ✅ Seek controls still work (-10s, +10s, ±1.5s)
- ✅ Pause/Play still functions
- ✅ Time display continues updating
- ✅ Can re-sync with another image if needed
Setup: Clear, well-lit scoreboard screenshot (1920x1080 or higher)
Expected Result:
- ✅ Confidence > 90%
- ✅ Clock detection accurate
- ✅ Processing time < 2 seconds
Setup: Dark scoreboard image with visible clock
Expected Result:
- ✅ Confidence 70-90%
- ✅ Clock detection may be accurate
- ✅ Processing time < 3 seconds
Setup: Slightly blurred scoreboard
Expected Result:
- ✅ Confidence 50-80%
⚠️ Clock detection may be inaccurate- ✅ System handles gracefully (no crashes)
Setup: Scoreboard without standard MM:SS format
Expected Result:
- ✅ Low confidence score
⚠️ May not detect clock- ✅ Error message or "No clock detected"
Setup: High-resolution image (>5MB, <10MB)
Expected Result:
- ✅ Upload succeeds
- ✅ Processing takes longer (~3-5 seconds)
- ✅ Results still accurate
Setup: Image >10MB
Expected Result:
- ❌ Upload fails
- ✅ Error message: "File size exceeds 10MB limit"
Setup: Upload PDF, GIF, or text file
Expected Result:
- ❌ Upload fails
- ✅ Error message: "Only JPEG and PNG images are allowed"
Symptoms: Sync fails with "No segment found for clock time"
Causes:
- HLS stream hasn't generated segments yet
- Requested time is in the future
- Segments have aged out (>20 seconds old)
Solutions:
- Wait 10-15 seconds for segments to be generated
- Check FFmpeg is running:
docker logs audio-sync-ffmpeg - Verify indexer is indexing:
docker logs audio-sync-indexer - Check segment directory:
docker exec audio-sync-backend ls -la /storage/hls/
Symptoms: Confidence < 50%
Causes:
- Poor image quality
- Non-standard scoreboard format
- Glare or reflections
- Image too small
Solutions:
- Retake photo with better lighting
- Ensure scoreboard is centered and in focus
- Use higher resolution image
- Avoid glare/reflections
- Crop image to focus on scoreboard
Symptoms: Synced time doesn't match scoreboard
Causes:
- OCR misread the clock
- Segments not properly indexed
- Time drift in system
Solutions:
- Check OCR confidence score
- Manually verify detected clock time
- Use seek controls to fine-tune (±1.5s)
- Re-sync with a better image
- Check indexer logs for errors
Symptoms: Click Play but no audio
Causes:
- FFmpeg not streaming yet
- HLS playlist not available
- Browser audio policy (requires user interaction)
Solutions:
- Wait 10-15 seconds after starting services
- Check FFmpeg:
docker logs audio-sync-ffmpeg - Verify HLS playlist:
curl http://localhost:4000/api/hls/playlist - Try refreshing the page
- Check browser console for errors
Symptoms: Image upload returns error
Causes:
- File too large (>10MB)
- Wrong file type
- OCR service not running
Solutions:
- Check file size:
ls -lh your-image.jpg - Verify file type:
file your-image.jpg - Check OCR service:
docker logs audio-sync-ocr - Resize image if too large
- Convert to JPEG or PNG if needed
- All Docker containers running
- Services show as "healthy"
- Backend health check passes
- HLS playlist accessible (or generating)
- Test images prepared
- Frontend loads at http://localhost:3030
- Player page accessible
- Play button starts audio
- Pause button stops audio
- Seek controls work (+/-10s, +/-1.5s)
- Time display updates correctly
- Status indicator changes (playing/paused)
- Sync modal opens
- Image upload works (drag & drop)
- Image upload works (file browser)
- Processing indicator shows
- OCR results displayed
- Clock time detected correctly
- Confidence score shown
- Metadata displayed
- Retake button works
- File size validation (reject >10MB)
- File type validation (reject non-JPEG/PNG)
- Sync button available after OCR
- Sync succeeds with valid data
- Success message displayed
- Modal closes after sync
- Audio seeks to correct time
- Playback continues after sync
- Seek controls work after sync
- Can re-sync multiple times
- GET /api/health returns 200
- POST /api/ocr/upload works
- POST /api/ocr/upload rejects invalid files
- POST /api/sync works with valid data
- POST /api/sync rejects invalid clock format
- GET /api/hls/playlist works
- Invalid file type shows error
- File too large shows error
- Missing segments handled gracefully
- Low confidence warnings shown
- Network errors handled
- OCR service down handled
- Invalid clock format rejected
- OCR processing < 3 seconds
- Sync operation < 500ms
- Page load < 2 seconds
- No memory leaks after multiple syncs
- Concurrent uploads handled
- Clock time 00:00 works
- Clock time 59:59 works
- Very small images processed
- Very large (but valid) images processed
- Multiple rapid syncs work
- Sync with low confidence (<70%)
- Sync with future time (not yet available)
OCR Upload with curl:
curl -X POST http://localhost:4000/api/ocr/upload \
-F "image=@path/to/scoreboard.jpg" \
-vSync Request with curl:
curl -X POST http://localhost:4000/api/sync \
-H "Content-Type: application/json" \
-d '{"clock": "12:34", "confidence": 0.95}' \
-vCheck HLS Segments:
# List HLS files
docker exec audio-sync-backend ls -la /storage/hls/
# Check segment database
docker exec audio-sync-backend sqlite3 /storage/index/segments.db \
"SELECT sequence, start, end FROM segments ORDER BY sequence DESC LIMIT 10;"Create a quick test script:
#!/bin/bash
# quick-test.sh
echo "=== Audio Sync Platform - Quick Test ==="
echo "1. Checking services..."
docker compose ps
echo "2. Testing backend health..."
curl -s http://localhost:4000/api/health | jq .
echo "3. Testing OCR upload..."
curl -s -X POST http://localhost:4000/api/ocr/upload \
-F "image=@test-images/scoreboard.jpg" | jq .
echo "4. Testing sync (requires segments)..."
curl -s -X POST http://localhost:4000/api/sync \
-H "Content-Type: application/json" \
-d '{"clock": "12:34", "confidence": 0.95}' | jq .
echo "5. Checking HLS playlist..."
curl -I http://localhost:4000/api/hls/playlist
echo "=== Tests Complete ==="Make it executable and run:
chmod +x quick-test.sh
./quick-test.shExpected performance on modern hardware:
| Metric | Target | Typical |
|---|---|---|
| OCR Processing Time | < 3s | 1.5-2s |
| Sync Operation | < 500ms | ~10ms |
| HLS Latency | < 6s | ~5.8s |
| Page Load Time | < 3s | ~1.5s |
| API Response Time | < 200ms | 50-100ms |
If you encounter issues during testing:
-
Check Logs:
docker compose logs -f -
Restart Services:
docker compose restart -
Rebuild:
docker compose up --build -d -
Clean Start:
docker compose down -v docker compose up --build -d
-
Report Issues: Include:
- Steps to reproduce
- Expected vs actual behavior
- Screenshots
- Relevant log outputs
- System information
Version: 1.0.0 Last Updated: December 11, 2025 Platform: Audio Sync Platform