跳至主要內容
Skip to content

檔案上傳系統設計 (9) —— 多媒體處理流水線

在上一篇中,我們成功地將大檔案切片並「流」進了伺服器。但是,如果使用者上傳的是一段 4K 影片,或者是一個 100MB 的 PDF,後端的工作才剛剛開始。

你不能在同一個 HTTP 請求中進行影片轉碼,因為那可能需要幾分鐘甚至幾小時,瀏覽器會直接超時 (Timeout)。這就是 多媒體處理流水線 (Media Pipeline) 登場的時候。


一、 不要阻塞你的 API:非同步架構

處理大型檔案(縮圖、轉碼、語音轉文字)的核心原則是:解耦 (Decoupling)

  1. API Server:只負責接收檔案,存好後立即回傳「上傳成功,處理中」。
  2. Worker Server:專門負責運算的背景服務,從隊列中領取任務執行。
  3. Message Queue:中間的調度中心。

二、 任務隊列:以 BullMQ 為例 (Redis-based)

在 Node.js 生態中,BullMQ 是處理這類背景任務的首選。

工作流程:

  • Producer (API):當檔案合併完成,將「處理任務」丟進 Redis 隊列。
  • Consumer (Worker):Worker 閒置時自動從隊列抓取任務。
javascript
// Producer: API 段
await imageQueue.add("process-thumbnail", {
  fileId: "abc-123",
  path: "/uploads/raw/me.mp4",
});

三、 FFmpeg 實戰:轉碼與封面擷取

FFmpeg 是多媒體處理界的瑞士刀。透過它,你可以自動化產生展示所需的素材。

1. 擷取影片第一秒作為封面

bash
ffmpeg -i input.mp4 -ss 00:00:01 -vframes 1 thumbnail.jpg

2. 在 Node.js 中調用 (使用 fluent-ffmpeg)

javascript
const ffmpeg = require("fluent-ffmpeg");

ffmpeg("/path/to/video.mp4").screenshots({
  timestamps: ["00:01"],
  filename: "thumb.png",
  folder: "/uploads/thumbs",
  size: "320x240",
});

四、 狀態追蹤:處理完了怎麼辦?

當背景任務完成(或失敗)時,系統必須有機制告訴使用者。

  1. 輪詢 (Polling):前端每隔 3 秒問一次 API:「好了嗎?」。簡單但浪費資源。
  2. WebSocket:Worker 處理完後,透過 Socket.io 直接推送通知給對應的 User。
  3. Webhook:如果處理是交給外部雲端服務(如 AWS Elastic Transcoder),它們會發送一個 HTTP 請求到你的專用 URL 告知結果。

總結

一個專業的多媒體系統,其強大之處在於「上傳後的自動化」:

  • 解耦:保護 API Server 不被重型任務壓垮。
  • 持久化:隊列確保任務即使在重啟後也不會遺失。
  • 標準化:利用 FFmpeg 統一所有使用者上傳的混亂格式。

下一篇,我們將討論檔案系統的最後一道關卡:私有檔案的訪問控制。


️ 進階挑戰

如果有多個 Worker 同時在處理轉碼,你該如何防止兩個 Worker 同時處理同一個檔案?任務隊列中的「原子性 (Atomicity)」在此起到了什麼作用?


延伸閱讀與資源

← 上一章:分片上傳的前端排程 | 返回專案首頁 | 下一章:私有檔案的訪問控制