package handlers import ( "encoding/json" "log" "net/http" "os" "aroll/store" "aroll/transcode" "aroll/ws" ) type exportRequest struct { Filename string `json:"filename"` Segments []transcode.Segment `json:"segments"` Duration float64 `json:"duration"` } type updateTimeLine struct { Type string `json:"type"` Segments []transcode.Segment `json:"segments"` Duration float64 `json:"duration"` } func ExportHandler(st *store.Store, hub *ws.Hub) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) return } var req exportRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "bad JSON: "+err.Error(), http.StatusBadRequest) return } if len(req.Segments) == 0 { http.Error(w, "no segments", http.StatusBadRequest) return } inPath, ok := st.Path(req.Filename) if !ok { http.Error(w, "file not found", http.StatusNotFound) return } go func() { /* ToDo: Make sure that other video formats gets transcoded */ outputKey := "output-" + store.NewID() + ".mp4" outPath := st.Allocate(outputKey) if err := transcode.ExportSegments(inPath, outPath, req.Segments, hub.Broadcast); err != nil { os.Remove(outPath) broadcastError(hub, err.Error()) return } doneMsg, _ := json.Marshal(map[string]string{ "type": "done", "message": outputKey, }) hub.Broadcast(doneMsg) // Build normalized segments for the exported video: timestamps start at 0 // with no gaps, so the timeline reflects the exported file's layout. var normalized []transcode.Segment cursor := 0.0 for _, seg := range req.Segments { dur := seg.End - seg.Start normalized = append(normalized, transcode.Segment{Start: cursor, End: cursor + dur}) cursor += dur } timelineMsg, _ := json.Marshal(updateTimeLine{ Type: "timeline", Segments: normalized, Duration: cursor, }) hub.Broadcast(timelineMsg) }() w.WriteHeader(http.StatusAccepted) log.Println("Export handler works") } }