133 lines
3.6 KiB
Markdown
133 lines
3.6 KiB
Markdown
# Extractors API
|
|
|
|
## Base URL
|
|
|
|
```
|
|
{BASE_URL}
|
|
```
|
|
|
|
- **Local development:** `http://localhost:54400`
|
|
- **Docker (internal):** `http://extractors:54400`
|
|
- **Production:** use your configured hostname (port `14400`)
|
|
|
|
## Authentication
|
|
|
|
None at the service level — access is mediated by the platform API gateway
|
|
(Bearer token at the perimeter). Do not expose this service directly.
|
|
|
|
## Endpoints
|
|
|
|
### GET /health
|
|
|
|
Liveness probe.
|
|
|
|
```json
|
|
{ "status": "ok", "version": "0.1.0" }
|
|
```
|
|
|
|
### GET /ready
|
|
|
|
Readiness + optional tooling availability (informational; the service degrades
|
|
gracefully if ffprobe/ffmpeg are absent).
|
|
|
|
```json
|
|
{ "status": "ready", "ffprobe": true, "ffmpeg": true }
|
|
```
|
|
|
|
### POST /v1/metadata
|
|
|
|
Extract deterministic media metadata & integrity features. The applicable
|
|
extractors are chosen automatically from the detected media type.
|
|
|
|
**Request** — `multipart/form-data`
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `file` | file | Image, video or audio file |
|
|
|
|
```bash
|
|
curl -X POST http://localhost:54400/v1/metadata \
|
|
-F "file=@photo.jpg"
|
|
```
|
|
|
|
**Response** `200 OK`
|
|
|
|
```json
|
|
{
|
|
"filename": "photo.jpg",
|
|
"media_type": "image",
|
|
"sha256": "9f86d081884c7d65...",
|
|
"size_bytes": 84211,
|
|
"analyses": {
|
|
"integrity": {
|
|
"tool_id": "integrity",
|
|
"name": "Integrity & signature",
|
|
"ok": true,
|
|
"results": { "container": "JPEG", "sha256": "9f86...", "size_bytes": 84211 },
|
|
"evidence": ["Container: JPEG.", "SHA-256: 9f86d081884c7d65…"],
|
|
"anomalies": [],
|
|
"confidence": 1.0
|
|
},
|
|
"exif": {
|
|
"tool_id": "exif",
|
|
"name": "EXIF metadata",
|
|
"ok": true,
|
|
"results": {
|
|
"format": "JPEG", "dimensions": [4032, 3024],
|
|
"make": "Apple", "model": "iPhone 13",
|
|
"datetimeoriginal": "2024:06:15 14:30:00",
|
|
"gps": { "latitude": 44.426, "longitude": 26.102 },
|
|
"software": "Adobe Photoshop 25.0"
|
|
},
|
|
"evidence": ["Captured with Apple iPhone 13.", "GPS location present: 44.426, 26.102."],
|
|
"anomalies": ["Editing/generation software detected in EXIF: Adobe Photoshop 25.0."],
|
|
"confidence": 0.95
|
|
},
|
|
"ela": {
|
|
"tool_id": "ela", "name": "Error Level Analysis", "ok": true,
|
|
"results": { "quality": 90, "mean_error": 6.1, "max_error": 211.0, "p99_error": 38.0, "hot_pixel_fraction": 0.031 },
|
|
"evidence": ["ELA mean error 6.1, p99 38.0 (quality=90)."],
|
|
"anomalies": ["Localized high-error region(s) detected — possible splice/edit (3.1% of pixels)."],
|
|
"confidence": 0.6
|
|
}
|
|
},
|
|
"evidence": ["..."],
|
|
"anomalies": ["..."],
|
|
"execution_time_ms": 42.7
|
|
}
|
|
```
|
|
|
|
For **video** inputs the `analyses` block contains `integrity`, `video_metadata`
|
|
(codec/width/height/fps/bitrate/encoder) and `spectrogram`. For **audio**:
|
|
`integrity` + `spectrogram`.
|
|
|
|
Each extractor returns a uniform `FeatureResult`:
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `tool_id` | string | Stable extractor id |
|
|
| `name` | string | Human-readable name |
|
|
| `ok` | bool | Ran without error |
|
|
| `results` | object | Structured extracted data |
|
|
| `evidence` | string[] | Neutral findings (LLM-readable) |
|
|
| `anomalies` | string[] | Tampering/edit hints |
|
|
| `confidence` | number\|null | 0..1 (extraction confidence, not a verdict) |
|
|
| `error` | string\|null | Set when `ok` is false |
|
|
|
|
## Error Responses
|
|
|
|
| Status | Meaning |
|
|
|--------|---------|
|
|
| 400 | Empty file |
|
|
| 413 | File exceeds `EXTRACTORS_MAX_UPLOAD_MB` |
|
|
| 422 | Missing `file` field |
|
|
|
|
```json
|
|
{ "detail": "empty file" }
|
|
```
|
|
|
|
## Request Headers
|
|
|
|
| Header | Required | Notes |
|
|
|--------|----------|-------|
|
|
| `Content-Type` | yes | `multipart/form-data` (set by the client) |
|