VoD (Video Upload)
Mengunggah file video per chunk dengan resume, menyimpannya dengan waktu rekam nyata, memutarnya ulang sebagai stream, dan mengaksesnya lewat playback berbasis waktu.
Pengenalan
VoD (Video on Demand) membuat Liodra menerima file video yang sudah ada (ekspor CCTV, rekaman drone, bukti dari pihak ketiga) dan memperlakukannya seperti rekaman lain: bisa ditonton, dipotong berdasarkan waktu, dan dijadikan sumber analitik Visionaire. Fitur ini aktif dengan flag --with-vod (ENABLE_VOD=true).
Yang membedakannya dari sekadar file server:
- Unggah per chunk dengan resume: file sampai
MAX_UPLOAD_FILE_SIZE(50 GB) dikirim dalam potonganMAX_UPLOAD_CHUNK_SIZE(1 MB), boleh paralel, dan dapat dilanjutkan setelah koneksi putus. - Waktu rekam nyata (
started_at): Liodra menebak kapan video direkam (dari nama file, metadata, atau input Anda) agar playback berbasis waktu dan timeline Lenz sejajar dengan kejadian sebenarnya. - Autoplay sebagai stream: dengan
autoplay=true, video didaftarkan sebagai devicefiledi channelvoddan diputar berulang, sehingga tersedia di RTSP/RTMP/HTTP-TS seperti kamera.
Di Lenz, fitur ini adalah halaman Video Management: unggah (autoplay aktif secara default), pratinjau lewat /play/ts/vod/{id}?transcode=true, koreksi timestamp, dan penugasan analitik offline ke Visionaire.
File disimpan di storage/vods/ bersama file .info (metadata) dan thumbnail JPEG. Channel vod tidak direkam, jadi memutar video sebagai stream tidak menghasilkan rekaman baru.
Cara Menggunakan
Unggah chunk pertama
curl -X POST "http://localhost:9080/api/v1/videos/upload?autoplay=true" \
-F "file=@part-000.bin" \
-F "filename=cctv lobby 20260915103000.mp4" \
-F "chunk_index=0" \
-F "total_chunks=1200" \
-F "total_size=1258291200"Respons berisi session_id dan video_id. Simpan keduanya. Anda juga bisa mengirim started_at (RFC3339) untuk menetapkan waktu rekam secara eksplisit.
Kirim chunk berikutnya
Sertakan session_id pada setiap chunk (chunk_index 1 sampai total_chunks - 1). Urutan bebas dan boleh paralel. Pantau kemajuan dengan GET /api/v1/videos/upload/status/{session_id} (progress, chunks_received, bytes_written).
Lanjutkan bila terputus
curl http://localhost:9080/api/v1/videos/upload/resume/{session_id}Field missing_chunks menyebutkan indeks yang belum diterima; kirim ulang hanya itu dengan session_id yang sama. Sesi yang tidak diinginkan dibatalkan dengan POST /api/v1/videos/upload/cancel/{session_id}.
Setelah lengkap
Liodra merakit file, membaca durasi dan metadata, membuat thumbnail, lalu (bila autoplay=true) mendaftarkan device vod/{video_id}. Status video berubah uploading → processing → completed. Periksa dengan GET /api/v1/videos/{id}.
Tonton, potong, atau analisis
# tonton sebagai stream berulang (autoplay)
ffplay "http://localhost:9080/api/v1/play/ts/vod/{video_id}"
# ambil 5 menit mulai 10:35 UTC sebagai MP4
curl -o clip.mp4 "http://localhost:9080/api/v1/playbacks/vod/{video_id}?start=2026-09-15T10:35:00Z&duration=300&download=true"Untuk Visionaire, isi stream_address dengan rtsp://<host-liodra>:8554/vod/{video_id} (atau RTMP dengan ?vhost=vod).
Fitur Utama
Penentuan started_at
Prioritas dari tertinggi ke terendah:
started_atyang dikirim klien saat chunk pertama (started_at_src: original).- Pola tanggal pada nama file sesuai
UPLOAD_FILENAME_DATETIME_FORMAT(defaultYYYYMMDDHHMMSS, mis.cam01_20260915103000.mp4) (filename). - Tanggal encode atau tanggal modifikasi dari metadata container file; nilai epoch atau sebelum tahun 2000 diabaikan (
mediainfo). - Tanggal unggah pukul 00:00 UTC.
Nilainya dapat dikoreksi kapan saja dengan PATCH /api/v1/videos/{id} (started_at, opsional started_at_src: manual atau vllm bila berasal dari ekstraksi AI seperti yang dilakukan Lenz dari thumbnail). ended_at dihitung ulang otomatis.
Playback berbasis waktu untuk file
GET /api/v1/playbacks/vod/{id} memakai pola yang sama dengan playback DVR: tanpa parameter mengembalikan satu segmen (start = started_at, duration = durasi video); dengan start + duration mengalirkan MPEG-TS dari offset start - started_at; download=true menghasilkan MP4. start harus berada di dalam started_at..ended_at, kalau tidak ditolak 400. Endpoint daily dan hourly juga tersedia agar komponen date picker dan scrubber yang sama di Lenz dapat dipakai ulang.
Daftar, pencarian, dan paginasi
GET /api/v1/videos mendukung search (parsial pada id dan original_filename), sort_by (original_filename, file_size, duration, started_at, created_at), sort_order, page, dan per_page (0 = semua). Setiap item menyertakan objek device bila video sedang diputar sebagai stream, sehingga status streaming tampil tanpa panggilan tambahan.
Thumbnail
Dibuat otomatis saat unggah: 10 frame pertama diekstrak, frame hitam/seragam/rusak dibuang berdasarkan varian piksel, frame valid pertama diubah ukurannya maksimum 720p dan dikompresi JPEG 80%. GET /api/v1/videos/{id}/thumbnail mengembalikan JPEG (dibuat saat diminta bila belum ada); POST pada path yang sama membuatnya ulang. Video dengan tinggi di atas MAX_UPLOAD_RESOLUTION (4096) mendapat placeholder.
Autoplay dan kendali stream
Device autoplay bernama vod/{video_id} bisa dikelola seperti device lain: POST /api/v1/devices/file/vod/{video_id}/stop untuk menjeda, .../restart untuk melanjutkan, dan muncul di GET /api/v1/devices/file. Menghapus video (DELETE /api/v1/videos/{id}) juga menghapus device, metadata, dan thumbnail-nya.
Batas dan format
| Batas | Default | Variabel |
|---|---|---|
| Ukuran file | 50 GB | MAX_UPLOAD_FILE_SIZE |
| Ukuran chunk | 1 MB | MAX_UPLOAD_CHUNK_SIZE |
| Tinggi maksimum untuk thumbnail | 4096 px | MAX_UPLOAD_RESOLUTION |
| Format | mp4, avi, mov, mkv |
API Reference
Detail lengkap di API Reference: VoD.
| Method | Path | Fungsi |
|---|---|---|
POST | /api/v1/videos/upload | Unggah satu chunk (?autoplay=true) |
GET | /api/v1/videos/upload/resume/{session_id} | Chunk yang masih hilang |
GET | /api/v1/videos/upload/status/{session_id} | Kemajuan unggahan |
POST | /api/v1/videos/upload/cancel/{session_id} | Batalkan sesi |
GET | /api/v1/videos | Daftar video |
GET | /api/v1/videos/{id} | Detail video |
PATCH | /api/v1/videos/{id} | Koreksi started_at |
DELETE | /api/v1/videos/{id} | Hapus video |
GET | /api/v1/videos/{id}/daily, /hourly | Distribusi untuk date picker dan scrubber |
GET / POST | /api/v1/videos/{id}/thumbnail | Ambil atau buat ulang thumbnail |
GET | /api/v1/playbacks/vod/{id} | Playback berbasis waktu |