feat: add /render/mp4 endpoint with FFmpeg encoding

- Add MP4Request type with fps param
- Render frames in parallel, encode via ffmpeg
- Add ffmpeg to Docker image
This commit is contained in:
devilreef 2026-01-23 01:11:53 +06:00
parent 6345eb9821
commit ce511e1a85
6 changed files with 220 additions and 0 deletions

View file

@ -113,6 +113,43 @@ func (h *Handlers) HandleGIF(w http.ResponseWriter, r *http.Request) {
w.Write(gifBytes)
}
// HandleMP4 handles POST /render/mp4
func (h *Handlers) HandleMP4(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
if err != nil {
writeError(w, http.StatusBadRequest, "failed to read request body")
return
}
defer r.Body.Close()
var req MP4Request
if err := json.Unmarshal(body, &req); err != nil {
writeError(w, http.StatusBadRequest, "invalid JSON: "+err.Error())
return
}
req.ApplyDefaults()
if req.Character == nil {
writeError(w, http.StatusBadRequest, "character field is required")
return
}
result, err := h.svc.MergeFromJSON(req.Character)
if err != nil {
writeError(w, http.StatusInternalServerError, "merge failed: "+err.Error())
return
}
mp4Bytes, err := render.RenderMP4(result.GLBBytes, result.Atlas, req.Background, req.Frames, req.Width, req.Height, req.FPS)
if err != nil {
writeError(w, http.StatusInternalServerError, "render failed: "+err.Error())
return
}
w.Header().Set("Content-Type", "video/mp4")
w.Write(mp4Bytes)
}
// HandleHealth handles GET /health
func (h *Handlers) HandleHealth(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")