Skip to main content

Videos API

List videos, retrieve metadata, stream video files, and perform object detection. Videos are served from the /data directory.

List Videos

Retrieve all available videos with metadata.

Request

GET /api/videos

Response

Status: 200 OK

[
{
"id": "abc123def456",
"filename": "sample-video.mp4",
"path": "/api/videos/abc123def456/stream",
"size": 104857600,
"createdAt": "2025-10-06T14:30:00.000Z",
"title": "Baseball Game Footage",
"description": "Spring training game footage",
"duration": 120.5,
"width": 1920,
"height": 1080,
"fps": 30,
"format": "mp4"
}
]

Status: 500 Internal Server Error

{
"error": "Failed to list videos"
}

Response Schema

Base fields (always present):

FieldTypeDescription
idstringMD5 hash of filename (first 16 chars)
filenamestringOriginal filename
pathstringStreaming endpoint path
sizenumberFile size in bytes
createdAtstringISO 8601 timestamp of file creation

Metadata fields (from .info.json file, if present):

FieldTypeDescription
titlestringDisplay title
descriptionstringVideo description
durationnumberDuration in seconds
widthnumberVideo width in pixels
heightnumberVideo height in pixels
fpsnumberFrames per second
formatstringVideo format
uploaderstringOptional uploader name
uploadDatestringOptional upload date
tagsarrayOptional array of tags
thumbnailstringOptional thumbnail path

Example

curl http://localhost:3001/api/videos

Get Video Metadata

Retrieve metadata for a specific video.

Request

GET /api/videos/:videoId

Parameters

ParameterTypeDescription
videoIdstringVideo identifier (MD5 hash of filename)

Response

Status: 200 OK

{
"id": "abc123def456",
"filename": "sample-video.mp4",
"path": "/api/videos/abc123def456/stream",
"size": 104857600,
"createdAt": "2025-10-06T14:30:00.000Z",
"title": "Baseball Game Footage",
"description": "Spring training game footage",
"duration": 120.5,
"width": 1920,
"height": 1080,
"fps": 30,
"format": "mp4"
}

Status: 404 Not Found

{
"error": "Video not found"
}

Status: 500 Internal Server Error

{
"error": "Failed to get video"
}

Example

curl http://localhost:3001/api/videos/abc123def456

Stream Video

Stream video file content for playback.

Request

GET /api/videos/:videoId/stream

Parameters

ParameterTypeDescription
videoIdstringVideo identifier (MD5 hash of filename)

Response

Status: 200 OK

Content-Type: video/mp4

Headers:

  • Content-Length: File size in bytes
  • Accept-Ranges: bytes

Binary video stream.

Status: 404 Not Found

{
"error": "Video not found"
}

Status: 500 Internal Server Error

{
"error": "Failed to stream video"
}

Example

curl http://localhost:3001/api/videos/abc123def456/stream --output video.mp4

Notes

  • Supports HTTP range requests for seeking.
  • Used by video.js player in frontend for playback.
  • Returns entire file if no range header is provided.

Detect Objects

Detect objects in video frames using persona-based or manual queries.

Request

POST /api/videos/:videoId/detect

Content-Type: application/json

{
"personaId": "660e8400-e29b-41d4-a716-446655440001",
"confidenceThreshold": 0.3,
"frameNumbers": [0, 30, 60, 90],
"enableTracking": false
}

Parameters

ParameterTypeDescription
videoIdstringVideo identifier (MD5 hash of filename)

Request Body Schema

FieldTypeRequiredDescription
personaIdUUIDNo*Persona UUID for building query from ontology
manualQuerystringNo*Manual query string (overrides personaId)
queryOptionsobjectNoOptions for building query from persona
confidenceThresholdnumberNoMinimum confidence (default: 0.3, range: 0-1)
frameNumbersarrayNoSpecific frames to process (omit for all)
enableTrackingbooleanNoEnable object tracking (default: false)

*Either personaId or manualQuery must be provided.

Query Options Schema

Used when personaId is provided to control which parts of the ontology are included in the detection query:

FieldTypeDefaultDescription
includeEntityTypesbooleantrueInclude entity type names
includeEntityGlossesbooleanfalseInclude entity type definitions
includeEventTypesbooleanfalseInclude event type names
includeEventGlossesbooleanfalseInclude event type definitions
includeRoleTypesbooleanfalseInclude role type names
includeRoleGlossesbooleanfalseInclude role type definitions
includeRelationTypesbooleanfalseInclude relation type names
includeRelationGlossesbooleanfalseInclude relation type definitions
includeEntityInstancesbooleanfalseInclude world entity names
includeEntityInstanceGlossesbooleanfalseInclude world entity descriptions
includeEventInstancesbooleanfalseInclude world event names
includeEventInstanceGlossesbooleanfalseInclude world event descriptions
includeLocationInstancesbooleanfalseInclude world location names
includeLocationInstanceGlossesbooleanfalseInclude world location descriptions
includeTimeInstancesbooleanfalseInclude world time names
includeTimeInstanceGlossesbooleanfalseInclude world time descriptions

Response

Status: 200 OK

{
"videoId": "abc123def456",
"query": "pitcher, batter, baseball, glove",
"frameResults": [
{
"frameNumber": 0,
"detections": [
{
"x": 100,
"y": 100,
"width": 200,
"height": 150,
"confidence": 0.95,
"label": "pitcher"
},
{
"x": 500,
"y": 200,
"width": 180,
"height": 160,
"confidence": 0.92,
"label": "batter"
}
]
},
{
"frameNumber": 30,
"detections": [
{
"x": 110,
"y": 105,
"width": 200,
"height": 150,
"confidence": 0.93,
"label": "pitcher"
}
]
}
]
}

Status: 400 Bad Request

{
"error": "Either personaId or manualQuery must be provided"
}

or

{
"error": "Generated query is empty. Persona may have no entity types defined."
}

Status: 404 Not Found

{
"error": "Video not found"
}

Status: 500 Internal Server Error

{
"error": "Failed to detect objects"
}

or

{
"error": "Model service error: <error details>"
}

Example with Persona

curl -X POST http://localhost:3001/api/videos/abc123def456/detect \
-H "Content-Type: application/json" \
-d '{
"personaId": "660e8400-e29b-41d4-a716-446655440001",
"confidenceThreshold": 0.5,
"frameNumbers": [0, 30, 60, 90]
}'

Example with Manual Query

curl -X POST http://localhost:3001/api/videos/abc123def456/detect \
-H "Content-Type: application/json" \
-d '{
"manualQuery": "person, ball, bat, glove",
"confidenceThreshold": 0.7
}'

Example with Tracking Enabled

curl -X POST http://localhost:3001/api/videos/abc123def456/detect \
-H "Content-Type: application/json" \
-d '{
"personaId": "660e8400-e29b-41d4-a716-446655440001",
"enableTracking": true,
"confidenceThreshold": 0.6
}'

Notes

Video ID Format

Video IDs are created by taking the first 16 characters of the MD5 hash of the filename:

const id = crypto.createHash('md5').update(filename).digest('hex').slice(0, 16)

Metadata Files

Each video file (video.mp4) can have an associated metadata file (video.info.json) in the same directory. If present, metadata fields are merged with the base response.

Example .info.json file:

{
"title": "Baseball Game Footage",
"description": "Spring training game footage",
"duration": 120.5,
"width": 1920,
"height": 1080,
"fps": 30,
"format": "mp4",
"uploader": "John Doe",
"uploadDate": "2025-10-01",
"tags": ["baseball", "sports", "training"]
}

Detection Query Building

When personaId is provided, the system builds a query string by concatenating terms from the persona's ontology based on queryOptions. The default includes only entity type names.

Example query for a sports scout persona:

"pitcher, batter, catcher, umpire, baseball, glove, bat"

Object Detection Model

Detection requests are forwarded to the model service at MODEL_SERVICE_URL (default: http://localhost:8000). The model service uses GroundingDINO or similar models for open-vocabulary object detection.

Tracking

When enableTracking: true, the model service tracks detected objects across frames and assigns consistent IDs. This is useful for following specific objects through the video.