Core Changes: - Fix SearchView to use start_frame/end_frame directly (no time*fps conversion) - Add hard_delete support to delete_trace API - VideoPlayer: Main timeline + Mark system foundation - Proxy: Add local routes for auth, media, identity-matches, cluster-results - Add .gitignore to exclude build artifacts and dependencies Design Documents: - Multi-track Mark system design (.opencode/plans/) - Video editing positioning standards research Files Modified: - src/views/SearchView.vue: Frame positioning, ensureMinDuration (240 frames) - src/views/PeopleView.vue: batchDeleteGroups with hard_delete - src/api/index.ts: delete_trace with hard_delete body - src/components/VideoPlayer.vue: Timeline + Mark UI - src-tauri/src/proxy.rs: New local routes - AGENTS.md: Update documentation
4.9 KiB
4.9 KiB
Core API Fix Request: Video Range Requests Support
Issue
Video player in Studio cannot seek (跳轉) because Core API video endpoint does not support HTTP Range requests.
Current Behavior
$ curl -I "http://localhost:3002/api/v1/file/{uuid}/video?start_time=0&end_time=5"
HTTP/1.1 200 OK
content-type: video/mp4
content-length: 1918410
# Missing: Accept-Ranges header
# Missing: 206 Partial Content support
Expected Behavior
$ curl -I "http://localhost:3002/api/v1/file/{uuid}/video" -H "Range: bytes=0-1000"
HTTP/1.1 206 Partial Content
content-type: video/mp4
content-range: bytes 0-1000/1918410
accept-ranges: bytes
content-length: 1001
Why This Matters
- Browser seeking requires Range support - HTML5
<video>element uses Range requests to seek to different timestamps - Current workaround is inefficient - Users must download entire video or use
start_timeparam (re-downloads video) - High bitrate videos suffer most - 4K/10Mbps videos cannot be quickly navigated
Implementation Requirements
1. Add Accept-Ranges: bytes header to video endpoint
GET /api/v1/file/{uuid}/video
Response Headers:
Accept-Ranges: bytes
2. Handle Range requests with 206 Partial Content
// Pseudo-code for Rust implementation
if let Some(range_header) = request.headers().get("Range") {
let (start, end) = parse_range(range_header)?;
let file_chunk = read_file_range(file_path, start, end)?;
Response::builder()
.status(206)
.header("Content-Range", format!("bytes {}-{}/{}", start, end, file_size))
.header("Accept-Ranges", "bytes")
.header("Content-Length", end - start + 1)
.body(file_chunk)
} else {
// Full file response
Response::builder()
.status(200)
.header("Accept-Ranges", "bytes")
.body(full_file)
}
3. Support multiple Range formats
Range: bytes=0-999(first 1000 bytes)Range: bytes=1000-(from byte 1000 to end)Range: bytes=-500(last 500 bytes)
Affected Files (Core API)
src/api/files.rs- Video streaming endpoint- Possibly
src/api/video.rsif exists
Testing
# Test 1: Initial request should include Accept-Ranges
curl -I "http://localhost:3002/api/v1/file/{uuid}/video"
# Expect: Accept-Ranges: bytes
# Test 2: Range request should return 206
curl -I "http://localhost:3002/api/v1/file/{uuid}/video" -H "Range: bytes=0-1000"
# Expect: HTTP/1.1 206 Partial Content
# Expect: Content-Range: bytes 0-1000/{total}
# Test 3: Browser seeking should work
# Open Studio, play video, click on timeline
# Video should seek without re-downloading
Priority
High - Critical for user experience when navigating long videos
Related Studio Files
src/components/VideoPlayer.vue- Uses<video>element with native controlssrc-tauri/src/proxy.rs- Already streams video, will pass through Range headers
Notes
- Studio proxy already supports streaming (lines 325-367 in proxy.rs)
- Just need Core API to handle Range requests properly
- This is standard HTTP behavior for video streaming
Additional Request: Adaptive Bitrate / Resolution Selection
Problem
High bitrate videos (4K, 10+ Mbps) cause playback lag in browser due to software decoding limitations.
Solution Options
Option A: Resolution Parameter
GET /api/v1/file/{uuid}/video?start_time=0&end_time=60&resolution=720p
GET /api/v1/file/{uuid}/video?start_time=0&end_time=60&resolution=480p
Implementation:
- Use FFmpeg to transcode on-the-fly or pre-generate proxy versions
- Store proxy videos at lower bitrates (720p @ 2Mbps, 480p @ 1Mbps)
Option B: Quality Parameter (1-100)
GET /api/v1/file/{uuid}//video?start_time=0&end_time=60&quality=50
Option C: Max Bitrate Parameter
GET /api/v1/file/{uuid}/video?start_time=0&end_time=60&max_bitrate=2000
Recommended Approach
Pre-generate proxy videos during processing:
// During file processing, generate multiple versions:
// - Original: {uuid}_original.mp4 (preserve original quality)
// - 720p: {uuid}_720p.mp4 (2 Mbps)
// - 480p: {uuid}_480p.mp4 (1 Mbps)
Storage Impact:
- Original 100MB video → ~105MB total (5% overhead for proxies)
API Changes:
pub fn get_video_stream(
file_uuid: String,
start_time: f64,
end_time: f64,
resolution: Option<String>, // "original" | "720p" | "480p"
) -> Result<VideoStream, Error>
Frontend Integration
Studio VideoPlayer can add quality selector:
<select v-model="selectedResolution">
<option value="original">Original (1080p)</option>
<option value="720p">HD (720p)</option>
<option value="480p">SD (480p)</option>
</select>
Benefits
- Eliminates lag on high bitrate videos
- Faster loading with smaller file sizes
- Bandwidth savings for remote access
- Better UX - smooth playback on all devices