We need this because godot can't handle pipes
This commit is contained in:
		
							parent
							
								
									3805679ec4
								
							
						
					
					
						commit
						acd70fe70d
					
				
					 3 changed files with 236 additions and 0 deletions
				
			
		
							
								
								
									
										5
									
								
								dlserver/go.mod
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								dlserver/go.mod
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| module dlserver | ||||
| 
 | ||||
| go 1.14 | ||||
| 
 | ||||
| require github.com/gorilla/mux v1.8.0 | ||||
							
								
								
									
										2
									
								
								dlserver/go.sum
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								dlserver/go.sum
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= | ||||
| github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= | ||||
							
								
								
									
										229
									
								
								dlserver/main.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										229
									
								
								dlserver/main.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,229 @@ | |||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"regexp" | ||||
| 	"runtime" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/gorilla/mux" | ||||
| ) | ||||
| 
 | ||||
| func limitLength(s string, length int) string { | ||||
| 	if len(s) < length { | ||||
| 		return s | ||||
| 	} | ||||
| 	return s[:length] | ||||
| } | ||||
| 
 | ||||
| // globals, huh, faster than channels and oddly more appropriate, we care less about races than feedback. | ||||
| var lastPercentage float64 | ||||
| var lastFilename string | ||||
| 
 | ||||
| func convertFile(sourceFileName string, destinationFilename string) error { | ||||
| 	launch := "./ffmpeg" | ||||
| 	if runtime.GOOS == "windows" { | ||||
| 		launch += ".exe" | ||||
| 	} | ||||
| 
 | ||||
| 	os.Remove(destinationFilename) | ||||
| 	DurationRe := regexp.MustCompile(`DURATION *: ([0-9]+):([0-9]+):([0-9]+)\.([0-9]+)`) | ||||
| 	FrameRe := regexp.MustCompile(`frame= ?([0-9]+) `) | ||||
| 	FPSValue := 0.0 | ||||
| 	finalFramesValue := 0.0 | ||||
| 	FPSRe := regexp.MustCompile(`, ([0-9\.]+) fps,`) | ||||
| 	fmt.Printf("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", launch, "-loglevel", "repeat+level+verbose", "-i", sourceFileName, "-c:v", "libvpx", "-crf", "10", "-b:v", "1M", "-c:a", "libvorbis", "-y", destinationFilename) | ||||
| 	cmd := exec.Command(launch, "-progress", "pipe:2", "-i", sourceFileName, "-c:v", "libvpx", "-crf", "10", "-b:v", "1M", "-c:a", "libvorbis", "-y", destinationFilename) | ||||
| 	stdout, err := cmd.StderrPipe() | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 	if err := cmd.Start(); err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	// Start reading from the file with a reader. | ||||
| 	reader := bufio.NewReader(stdout) | ||||
| 	var line string | ||||
| 	for { | ||||
| 		line, err = reader.ReadString('\n') | ||||
| 		if err != nil && err != io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 		fpses := FPSRe.FindAllStringSubmatch(line, 1) | ||||
| 		if len(fpses) > 0 { | ||||
| 			fmt.Printf("FPS' is %v\n", fpses) | ||||
| 			FPSValue, _ = strconv.ParseFloat(fpses[0][1], 64) | ||||
| 		} | ||||
| 		durations := DurationRe.FindAllStringSubmatch(line, 1) | ||||
| 		if len(durations) > 0 { | ||||
| 			fmt.Printf("Durations is %v\n", durations) | ||||
| 			if FPSValue != 0.0 { | ||||
| 				// we have an fps, we can work out max frames! | ||||
| 				hrs, _ := strconv.ParseFloat(durations[0][1], 64) | ||||
| 				mins, _ := strconv.ParseFloat(durations[0][2], 64) | ||||
| 				secs, _ := strconv.ParseFloat(durations[0][3], 64) | ||||
| 				aaand, _ := strconv.ParseFloat("0."+durations[0][4], 64) | ||||
| 				total := (hrs * 60 * 60) + (mins * 60) + secs + aaand | ||||
| 				finalFramesValue = total * FPSValue | ||||
| 				fmt.Printf("%0f:%0f:%0f%0.4f * %0.2f = %0.2f seconds = %0.2f frames\n", hrs, mins, secs, aaand, FPSValue, total, finalFramesValue) | ||||
| 			} | ||||
| 		} | ||||
| 		currentFrames := FrameRe.FindAllStringSubmatch(line, 1) | ||||
| 		if len(currentFrames) > 0 { | ||||
| 			currentFrame, _ := strconv.ParseFloat(currentFrames[0][1], 64) | ||||
| 			percentage := currentFrame / finalFramesValue * 100 | ||||
| 			lastPercentage = (percentage / 2) + 50 | ||||
| 			fmt.Printf("Frame %0f / %0f = Percent : %0.2f\n", currentFrame, finalFramesValue, lastPercentage) | ||||
| 		} | ||||
| 
 | ||||
| 		if len(fpses) == 0 && len(durations) == 0 && len(currentFrames) == 0 { | ||||
| 			//fmt.Printf("X: %s", line) | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	if err != io.EOF { | ||||
| 		fmt.Printf(" > Failed with error: %v\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	lastPercentage = 100 | ||||
| 	fmt.Printf("Setting to %0f percent.\n", lastPercentage) | ||||
| 	os.Remove(sourceFileName) | ||||
| 	go func() { | ||||
| 		time.Sleep(10 * time.Second) | ||||
| 		lastPercentage = 0 | ||||
| 	}() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func downloadFile(sourceURL string, outputFile string, statusChannel chan float64, nameChannel chan string) error { | ||||
| 	progressBackwards := false | ||||
| 	lastLastPercentage := 0.0 | ||||
| 	launch := "./youtube-dl" | ||||
| 	if runtime.GOOS == "windows" { | ||||
| 		launch += ".exe" | ||||
| 	} | ||||
| 	fmt.Printf("%s %s %s %s %s\n", launch, sourceURL, "-o", outputFile, "--newline") | ||||
| 	cmd := exec.Command(launch, sourceURL, "-o", outputFile, "--newline") | ||||
| 	stdout, err := cmd.StdoutPipe() | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 	if err := cmd.Start(); err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 	re := regexp.MustCompile(`([0-9.]+)%`) | ||||
| 	reName := regexp.MustCompile(`Merging formats into "([^"]+)"`) | ||||
| 
 | ||||
| 	// Start reading from the file with a reader. | ||||
| 	reader := bufio.NewReader(stdout) | ||||
| 	var line string | ||||
| 	for { | ||||
| 		line, err = reader.ReadString('\n') | ||||
| 		if err != nil && err != io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 		percentages := re.FindAllStringSubmatch(line, 1) | ||||
| 		if len(percentages) > 0 { | ||||
| 			p, err := strconv.ParseFloat(string(percentages[0][1]), 64) | ||||
| 			if err != nil { | ||||
| 				fmt.Printf("What kind of number is %v", percentages[0][1]) | ||||
| 			} else { | ||||
| 				if lastLastPercentage > p { | ||||
| 					progressBackwards = true | ||||
| 				} | ||||
| 				lastLastPercentage = p | ||||
| 				if progressBackwards { | ||||
| 					// youtube-dl does video, then audio - it's not really half but an estimation | ||||
| 					lastPercentage = float64(25) + p/4 | ||||
| 				} else { | ||||
| 					lastPercentage = p / 4 | ||||
| 				} | ||||
| 				statusChannel <- lastPercentage | ||||
| 			} | ||||
| 		} | ||||
| 		fmt.Printf("%s\n", line) | ||||
| 		if err != nil { | ||||
| 			break | ||||
| 		} | ||||
| 		filenames := reName.FindAllStringSubmatch(line, 1) | ||||
| 		if len(filenames) > 0 { | ||||
| 			fmt.Printf("Filename: %v", filenames) | ||||
| 			lastFilename = filenames[0][1] | ||||
| 			nameChannel <- filenames[0][1] | ||||
| 		} | ||||
| 	} | ||||
| 	if err := cmd.Wait(); err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 	if err != io.EOF { | ||||
| 		fmt.Printf(" > Failed with error: %v\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return convertFile(lastFilename, "converted.webm") | ||||
| } | ||||
| 
 | ||||
| func HomeHandler(w http.ResponseWriter, r *http.Request) { | ||||
| 	w.WriteHeader(http.StatusOK) | ||||
| 	fmt.Fprintf(w, "Hello %s\n", "world") | ||||
| } | ||||
| 
 | ||||
| var c chan float64 | ||||
| var n chan string | ||||
| 
 | ||||
| func FetchHandler(w http.ResponseWriter, r *http.Request) { | ||||
| 	//vars := mux.Vars(r) | ||||
| 	w.WriteHeader(http.StatusOK) | ||||
| 	if lastFilename != "" { | ||||
| 		os.Remove(lastFilename) | ||||
| 	} | ||||
| 	go downloadFile(r.FormValue("url"), "test", c, n) | ||||
| 	fmt.Fprint(w, "OK\n") | ||||
| } | ||||
| 
 | ||||
| func StatusHandler(w http.ResponseWriter, r *http.Request) { | ||||
| 	w.Header().Set("Content-type", "application/json") | ||||
| 	w.WriteHeader(http.StatusOK) | ||||
| 	// Oddly, using channels here is slower and we don't actually care if there's a race condition. | ||||
| 	/*	if len(c) > 0 { | ||||
| 			lastPercentage = <-c | ||||
| 		} | ||||
| 		if len(n) > 0 { | ||||
| 			lastFilename = <-n | ||||
| 		} */ | ||||
| 	fmt.Printf("Returning %0.2f for %s\n", lastPercentage, lastFilename) | ||||
| 	fmt.Fprintf(w, `{"filename": "%s","percentage":%0.2f}`+"\n", lastFilename, lastPercentage) | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
| 	if len(os.Args) > 0 { | ||||
| 		os.Chdir(os.Args[1]) | ||||
| 	} | ||||
| 	r := mux.NewRouter() | ||||
| 	r.SkipClean(true) | ||||
| 	r.Path("/get").Queries("url", "{.*}").HandlerFunc(FetchHandler) | ||||
| 	r.HandleFunc("/status/", StatusHandler) | ||||
| 	r.HandleFunc("/", HomeHandler) | ||||
| 	http.Handle("/", r) | ||||
| 	c = make(chan float64, 999) | ||||
| 	n = make(chan string, 999) | ||||
| 	srv := &http.Server{ | ||||
| 		Handler: r, | ||||
| 		Addr:    "127.0.0.1:10435", | ||||
| 		// Good practice: enforce timeouts for servers you create! | ||||
| 		WriteTimeout: 15 * time.Second, | ||||
| 		ReadTimeout:  15 * time.Second, | ||||
| 	} | ||||
| 
 | ||||
| 	log.Fatal(srv.ListenAndServe()) | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	Add table
		
		Reference in a new issue