儲存結構
Vylux 使用兩個邏輯上的 storage 角色:
- source store:透過
SOURCE_S3_*讀取SOURCE_BUCKET中的原始檔與上游來源物件 - media store:透過
MEDIA_S3_*讀寫MEDIA_BUCKET中的衍生媒體、manifests、keys、preview 與圖片輸出
這兩個角色可以落在同一個 S3-compatible 服務,也可以分開部署,但在 Vylux 內部仍是獨立設定,彼此不會自動回退。
另外還有兩塊非 bucket 狀態:
- PostgreSQL:保存 job state、workflow results、wrapped encryption keys、image cache tracking
- Redis:保存 queue state 與 rate limit 狀態
Storage 角色
source store 被視為不可變的輸入來源。media store 則是 Vylux 寫入處理結果與 cleanup 目標的位置。
媒體儲存桶結構
media-bucket/
├── images/{prefix}/{hash}/...
├── videos/{prefix}/{hash}/
│ ├── cover.jpg
│ ├── preview.webp
│ ├── preview.gif
│ ├── master.m3u8
│ ├── audio/und_aac_2ch/
│ │ ├── init.mp4
│ │ ├── playlist.m3u8
│ │ └── seg_*.m4s
│ └── video/
│ ├── r1080_av1/
│ ├── r720_av1/
│ ├── r480_av1/
│ ├── r360_av1/
│ ├── r240_av1/
│ ├── r1080_h264/
│ ├── r720_h264/
│ ├── r480_h264/
│ ├── r360_h264/
│ └── r240_h264/
└── cache/{processing_hash}.{format}
object key 命名規則
同步圖片快取
即時圖片處理結果寫入:
cache/{processing_hash}.{format}
這裡的 processing_hash 來自:
- source object key
- width / height / quality
- output format
非同步圖片 thumbnail
image:thumbnail 會寫入:
images/{hash_prefix}/{hash}/{variant}.{format}
例如:
images/ab/abcdef1234/thumb.webp
images/ab/abcdef1234/large.jpg
影片相關輸出
cover、preview、HLS artifacts 都寫入:
videos/{hash_prefix}/{hash}/{relative_path}
例如:
videos/ab/abcdef1234/cover.jpg
videos/ab/abcdef1234/preview.webp
videos/ab/abcdef1234/master.m3u8
videos/ab/abcdef1234/audio/und_aac_2ch/init.mp4
videos/ab/abcdef1234/video/r720_h264/seg_000.m4s
為什麼有 hash_prefix
圖片與影片 key 都會使用 hash 的前兩個字元作為 prefix,主要目的是避免單一路徑下聚集過多物件,讓 object key 分布更均勻:
images/{hash[0:2]}/{hash}/...
videos/{hash[0:2]}/{hash}/...
/stream path mapping
依 job 類型不同,media bucket 內可能出現:
- image cache objects
cover.jpgpreview.webppreview.gifmaster.m3u8video/...變體 playlist 與 segmentsaudio/...playlist 與 segments
/stream/{hash}/* 對外提供穩定的播放 URL,對應 media bucket 中已存在的物件。
對外 URL:
/stream/{hash}/master.m3u8
/stream/{hash}/audio/{track_id}/playlist.m3u8
/stream/{hash}/video/{variant}/playlist.m3u8
/stream/{hash}/video/{variant}/seg_1.m4s
對內 bucket key:
videos/{hash_prefix}/{hash}/{filePath}
其中 filePath 就是 /stream/{hash}/ 後面的相對路徑。
什麼不在 bucket 內
有些關鍵資料不會寫進 media bucket:
- wrapped content keys 不存成 object,而是存 PostgreSQL
- key unwrap 所需的
kek_version與wrap_nonce也在 PostgreSQL - image cache entry tracking 在 PostgreSQL 的
image_cache_entries - job status、progress、results、retry plan 都在 PostgreSQL
這樣做的原因是:
- segment 與圖片是大量靜態物件,適合 object storage
- 金鑰與工作狀態是需要查詢、更新與權限控制的 metadata,適合資料庫
source store 角色
source bucket 原則上只承載上游應用提供的原始內容,例如:
uploads/sample.jpg
uploads/sample.mp4
uploads/user-avatars/123.png
Vylux 會讀取這些物件,但不應把導出結果再寫回 source bucket。
/original 是帶簽名的 source-object proxy:它直接從 source store 讀取並串流原始物件,不會先複製到 media store。
清理影響範圍
當執行 cleanup 時,Vylux 會依 hash 清掉:
images/{prefix}/{hash}/...videos/{prefix}/{hash}/...- 相關生成圖片快取的 tracking records
- 對應的 encryption key 與 job rows