Skip to main content
The labeling interface provides a TikTok-style full-screen video player for rapid manual sorting and prediction review. It’s the final piece of the active learning workflow.

Starting the Server

1

Ensure Predictions Exist

The UI loads predictions from artifacts/predictions.json. Run the full pipeline first:
python extract_features.py  # Extract features
python train.py             # Train model
python predict.py           # Generate predictions
2

Launch the Server

python server.py
Expected output:
INFO:     Started server process [12345]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
3

Open the Interface

Navigate to http://localhost:8000 in your browser.
Works best in Chrome/Edge. Safari may have video playback issues with certain codecs.

Interface Layout

The UI has three main sections:
┌─────────────┬──────────────────────┬─────────────────┐
│             │                      │                 │
│  Folder     │   Video Player       │  Predictions    │
│  Buttons    │                      │                 │
│             │   [controls]         │  Top-3 bars     │
│  (1-8 keys) │                      │                 │
│             │                      │  Progress       │
└─────────────┴──────────────────────┴─────────────────┘
  • Lists all category folders with video counts
  • Click to assign current video to that folder
  • Keyboard shortcuts: 1-8 for first 8 folders
  • Predicted folder has blue border highlight
  • Low-confidence predictions have orange border

Center: Video Player

  • Full-screen video with auto-play
  • Space: Play/pause
  • Arrow keys: Skip forward/backward 5 seconds
  • Auto-advances to next video after sorting

Right Panel: Predictions

  • Top-3 predicted folders with confidence bars
  • Current video filename
  • Progress counter: “23 / 42 remaining”
  • Progress bar visualization
  • Retrain button (triggers full pipeline)

Labeling Workflow

1

Review Prediction

The interface auto-loads the first unsorted video and shows predictions:
Predictions:
soccer      ████████████████████ 94%
tiktok      ██ 4%
travel      █ 2%
The predicted folder (soccer) is highlighted with a blue border in the left sidebar.
2

Accept or Override

If prediction is correct:
  • Click the highlighted folder button or press its number key (e.g., 5 for soccer)
  • Video is moved to that folder and removed from unsorted queue
If prediction is wrong:
  • Click the correct folder button (e.g., “travel”)
  • Press the correct folder’s number key
The interface automatically advances to the next video after sorting.
3

Handle Uncertain Predictions

Low-confidence predictions (<70%) show an orange border:
Predictions:
funny       ████████████ 62%
tiktok      ██████ 31%
cooking     █ 7%
Options:
  • Watch the full video to decide
  • Assign to the most appropriate folder
  • Skip with Ctrl+→ if you need to review later (manually refresh)
4

Complete the Queue

Continue until you see:
All videos sorted!
Completion screen shows:
  • Total videos processed
  • Link to retrain model

Keyboard Shortcuts

KeyAction
1-8Assign video to folder 1-8
SpacePlay/pause video
←/→Skip backward/forward 5 seconds
MMute/unmute
Number keys are assigned to folders in alphabetical order. Check the left sidebar for the mapping.

Active Learning: Retrain Workflow

After manually labeling videos, you can retrain the model directly from the UI:
1

Click Retrain Button

Located in the right panel. Clicking triggers:
  1. Feature extraction (extract_features.py)
  2. Model training (train.py)
  3. Prediction generation (predict.py)
The button shows “Retraining…” with a spinner during execution.
2

Monitor Progress

The retrain process runs in the background (may take 5-30 minutes depending on dataset size).Check server logs for real-time progress:
Using device: cuda
Loading CLIP (ViT-B/32)...
Extracting features for labeled videos...
Labeled: 45%|████████      | 72/160 [03:42<04:32, 3.09s/it]
The UI remains responsive during retraining. You can continue labeling, but predictions won’t update until retraining completes.
3

Reload Predictions

When retraining finishes, the server automatically reloads predictions.json.Refresh your browser to see updated predictions.New predictions will reflect the videos you just labeled, improving accuracy on similar content.

API Endpoints

The server exposes these endpoints (used by the frontend):

GET /api/videos

List all unsorted videos with predictions:
{
  "videos": [
    {
      "filename": "7234567890123456.mp4",
      "predicted_folder": "soccer",
      "confidence": 0.94,
      "top_predictions": [
        {"folder": "soccer", "confidence": 0.94},
        {"folder": "tiktok", "confidence": 0.04},
        {"folder": "travel", "confidence": 0.02}
      ]
    }
  ],
  "total": 42
}

GET /api/folders

List category folders with counts:
{
  "folders": [
    {"name": "cooking", "count": 12},
    {"name": "funny", "count": 8},
    {"name": "soccer", "count": 45}
  ]
}

POST /api/sort

Move a video to a folder:
curl -X POST http://localhost:8000/api/sort \
  -H "Content-Type: application/json" \
  -d '{"filename": "7234567890123456.mp4", "folder": "soccer"}'
Response:
{
  "success": true,
  "filename": "7234567890123456.mp4",
  "folder": "soccer",
  "folders": [...]
}

POST /api/retrain

Trigger full pipeline retrain:
curl -X POST http://localhost:8000/api/retrain
Response:
{"status": "started"}

GET /api/retrain/status

Check retrain progress:
curl http://localhost:8000/api/retrain/status
Response:
{
  "running": true,
  "last_result": null
}
When complete:
{
  "running": false,
  "last_result": "success"
}
If failed:
{
  "running": false,
  "last_result": "Failed at train.py: IndexError: ..."
}

Customizing the Interface

The UI is a single-file HTML application (index.html:1-450). Common customizations:

Changing Video Playback Speed

Edit index.html around line 140:
videoEl.playbackRate = 1.5;  // 1.5x speed

Auto-advance Delay

Add delay before loading next video:
// After sorting (around line 250)
setTimeout(() => {
  loadNextVideo();
}, 1000);  // 1 second delay

Keyboard Shortcut Changes

Edit key mappings around line 300:
if (e.key >= '1' && e.key <= '9') {  // Extend to 9 folders
  const idx = parseInt(e.key) - 1;
  // ...
}

Security Considerations

The server is designed for local use only:
  • Listens on 0.0.0.0:8000 (all interfaces)
  • No authentication
  • No HTTPS
  • Path traversal protection for filenames
Do NOT expose this server to the internet. It’s meant for localhost access only. If you need remote access, use SSH port forwarding:
ssh -L 8000:localhost:8000 user@your-server
Then access via http://localhost:8000 on your local machine.

Troubleshooting

Codec compatibility issues. Try re-encoding:
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -strict experimental output.mp4
Or use Chrome/Edge instead of Safari.
All videos are already sorted (in category folders). To test the interface:
# Move some videos back to root
mv data/Favorites/videos/soccer/*.mp4 data/Favorites/videos/

# Re-extract unlabeled embeddings
python extract_features.py

# Regenerate predictions
python predict.py

# Reload browser
The UI caches predictions on startup. After retraining completes:
  1. Check server logs confirm “success”
  2. Hard refresh your browser: Ctrl+Shift+R (Windows) or Cmd+Shift+R (Mac)
  3. Or restart the server:
    # Ctrl+C to stop
    python server.py  # Restart
    
A previous retrain is still in progress (or crashed). Check server logs:
# In server terminal, look for errors
If stuck, restart the server:
# Ctrl+C
python server.py
The retrain status resets on server restart.
Another process is using port 8000. Options:
  1. Kill the other process:
    lsof -ti:8000 | xargs kill -9  # macOS/Linux
    
  2. Use a different port: Edit server.py:182:
    uvicorn.run(app, host="0.0.0.0", port=8080)  # Change to 8080
    
    Access via http://localhost:8080

Advanced: Batch Import from TikTok

If you have TikTok’s data export:
  1. Extract videos from the archive:
    unzip tiktok_data.zip
    cp -r tiktok_data/Videos/*.mp4 data/Favorites/videos/
    
  2. Rename files to numeric format (optional):
    # The system works with any .mp4 filename
    # No need to rename unless you prefer it
    
  3. Run the pipeline:
    python extract_features.py
    python train.py
    python predict.py
    python server.py  # Label any uncertain videos
    

Performance Optimization

Reduce Server Load

The server loads predictions into memory on startup. For 1000+ videos:
# server.py: Lazy-load predictions
@app.on_event("startup")
def load_predictions():
    pass  # Don't load on startup

@app.get("/api/videos")
def list_videos():
    # Load predictions on-demand
    pred_file = ARTIFACTS_DIR / "predictions.json"
    if pred_file.exists():
        predictions = json.loads(pred_file.read_text())
    # ...

Faster Video Serving

Enable FastAPI’s StaticFiles for video directory:
from fastapi.staticfiles import StaticFiles

app.mount("/videos", StaticFiles(directory=DATA_DIR), name="videos")
Then update index.html to use /videos/{filename} instead of the custom endpoint.

Next Steps

You’ve completed the full pipeline! From here:

Setup

Return to setup to add more categories or scale to larger datasets

Feature Extraction

Re-extract with larger models for better accuracy

Continuous Improvement Loop

  1. Label videos via UI
  2. Click Retrain
  3. Review new predictions
  4. Repeat until satisfied with accuracy
Typically achieves 85-95% accuracy after 2-3 iterations.

Build docs developers (and LLMs) love