func (jc JobsController) ServeHTTP(w http.ResponseWriter, r *http.Request) { urlComps := strings.Split(r.URL.Path, "/") identifier := "" if len(urlComps) > 0 { identifier = urlComps[0] } if identifier == "socket" { webSocketHandler.ServeHTTP(w, r) return } if r.Method == "GET" { j := jobstatus.Job{identifier} status, err := j.GetStatus() if err != nil { w.WriteHeader(500) fmt.Fprintln(w, "Error getting status:", err) return } bytes, err := json.Marshal(status) if err != nil { w.WriteHeader(500) fmt.Fprintln(w, "Error marshaling json:", err) return } w.Header().Add("Content-Type", "application/json") fmt.Fprintln(w, string(bytes)) } else if r.Method == "POST" { var jobParams map[string]string decoder := json.NewDecoder(r.Body) err := decoder.Decode(&jobParams) if err != nil { w.WriteHeader(500) fmt.Fprintln(w, "Error deocding json:", err) return } jid, err := workers.Enqueue("guide-upload-video-job", "UploadVideoJob", jobParams) if err != nil { w.WriteHeader(500) fmt.Fprintln(w, "Error dispatching job:", err) return } fmt.Fprintln(w, jid) } }
func WebSocketServer(ws *websocket.Conn) { for { var jobParams map[string]string if err := websocket.JSON.Receive(ws, &jobParams); err != nil { ws.Close() return } jid, err := workers.Enqueue("guide-upload-video-job", "UploadVideoJob", jobParams) if err != nil { log.Println("Error queueing job") ws.Close() return } j := jobstatus.Job{jid} status, err := j.GetStatus() if err != nil { log.Println("Error getting status:", err) ws.Close() return } uc, cc := status.UpdateChannel() for jobStatus := range uc { if err := websocket.JSON.Send(ws, jobStatus); err != nil { log.Println("Error sending updated status:", err) ws.Close() return } else if jobStatus.State == "done" { cc <- 1 ws.Close() return } else { cc <- 0 } } } }
func UploadVideoJob(msg *workers.Msg) { args := msg.Args() job := jobstatus.Job{msg.Jid()} status, _ := job.GetStatus() ytl, ytErr := args.Get("youtube_link").String() s3l, s3Err := args.Get("s3_link").String() cloudId, err := args.Get("s3id").String() if err != nil { log.Println("no s3id") job.AppendLog("no s3id") status.Read() status.State = "error" status.Save() return } logJobStatus := func(newLine string, isError bool) { log.Println(newLine) job.AppendLog(newLine) status.Read() if status.State == "queued" { status.State = "started" } status.Message = newLine status.Save() } dontLogAnything := func(newLine string, isError bool) {} updateJobProgress := func(complete int, total int) { status.Read() status.Complete = int64(complete) status.Total = int64(total) if complete == total { status.State = "done" } else { status.State = "started" } status.Save() } // First let's find the video we're using as input inputVideoName := msg.Jid() + ".mp4" log.Println("S3ERR:", s3Err, "YTERR:", ytErr) if s3Err == nil { // If they provided an s3 link, download it if err := downloadFromS3(s3l, inputVideoName, logJobStatus); err != nil { job.AppendLog("Error downloading from S3:") job.AppendLog(err.Error()) status.Read() status.State = "error" status.Message = "Error downloading from S3" status.Save() log.Println("Error downloading from S3:", err) } } else if ytErr == nil { // If they provided a youtube link download it inputVideoName = "youtube.mp4" if err := downloadYoutubeVideo(ytl, "youtube", logJobStatus, updateJobProgress); err != nil { job.AppendLog("Error downloading youtube video:") job.AppendLog(err.Error()) status.Read() status.State = "error" status.Message = "Error downloading from YouTube" status.Save() log.Println("Error downloading youtube video:", err) } } else { // If they provided nothing error out job.AppendLog("no input video to upload") status.Read() status.State = "error" status.Save() return } // Split the video into segments if err := splitVideoIntoSegments(inputVideoName, "segments/", logJobStatus); err != nil { job.AppendLog("Error segmenting video") job.AppendLog(err.Error()) status.Read() status.State = "error" status.Message = "error segmenting video" status.Save() log.Println("Error segmenting video", err) } // generate some poster frames for i := 5; i < 10; i++ { posterName := fmt.Sprintf("segments/poster-%d.png", i) logMessage := fmt.Sprintf("Generating poster %d", i) if i == 5 { posterName = "segments/poster.png" } logJobStatus(logMessage, false) updateJobProgress(i-4, 6) if err := generatePoster(inputVideoName, i, posterName, dontLogAnything); err != nil { job.AppendLog("Error generating poster") job.AppendLog(err.Error()) status.Read() status.State = "error" status.Message = "error generating poster" status.Save() log.Println("Error generating poster", err) } } // and upload everything to S3 if err := uploadSegmentsToS3("segments/", cloudId, logJobStatus, updateJobProgress); err != nil { log.Println("Error uploading to S3:", err) job.AppendLog("Error uploading to S3") job.AppendLog(err.Error()) status.Read() status.State = "error" status.Message = "Error uploading to s3" status.Save() } // Clean up os.Remove(scratchPath(inputVideoName)) status.Read() status.State = "done" status.Message = "Uploaded video successfully" status.Save() }