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
186 lines
4.9 KiB
Markdown
186 lines
4.9 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
$ 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
|
|
|
|
```bash
|
|
$ 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
|
|
|
|
1. **Browser seeking requires Range support** - HTML5 `<video>` element uses Range requests to seek to different timestamps
|
|
2. **Current workaround is inefficient** - Users must download entire video or use `start_time` param (re-downloads video)
|
|
3. **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
|
|
|
|
```rust
|
|
// 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.rs` if exists
|
|
|
|
## Testing
|
|
|
|
```bash
|
|
# 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 controls
|
|
- `src-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
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
GET /api/v1/file/{uuid}//video?start_time=0&end_time=60&quality=50
|
|
```
|
|
|
|
#### Option C: Max Bitrate Parameter
|
|
|
|
```bash
|
|
GET /api/v1/file/{uuid}/video?start_time=0&end_time=60&max_bitrate=2000
|
|
```
|
|
|
|
### Recommended Approach
|
|
|
|
**Pre-generate proxy videos during processing:**
|
|
|
|
```rust
|
|
// 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:**
|
|
|
|
```rust
|
|
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:
|
|
|
|
```vue
|
|
<select v-model="selectedResolution">
|
|
<option value="original">Original (1080p)</option>
|
|
<option value="720p">HD (720p)</option>
|
|
<option value="480p">SD (480p)</option>
|
|
</select>
|
|
```
|
|
|
|
### Benefits
|
|
|
|
1. **Eliminates lag** on high bitrate videos
|
|
2. **Faster loading** with smaller file sizes
|
|
3. **Bandwidth savings** for remote access
|
|
4. **Better UX** - smooth playback on all devices |