package main import ( "log" "net/http" "os/exec" "io" "strings" ) func combine(spl []string) (io.ReadCloser, error) { cmd := exec.Command("ffmpeg", "-i", spl[0], "-i", spl[1], "-c:v", "copy", "-c:a", "copy", "-f", "matroska", "-") stdout, err := cmd.StdoutPipe() if err != nil { return nil, err } if err := cmd.Start(); err != nil { return nil, err } return stdout, nil } func stream(w http.ResponseWriter, r *http.Request) { values := r.URL.Query() if !values.Has("yturl") { w.WriteHeader(http.StatusBadRequest) return } ytUrl := values.Get("yturl") cmd := exec.Command("yt-dlp", "-g", ytUrl) burls, err := cmd.Output() if err != nil { w.WriteHeader(http.StatusInternalServerError) log.Println(err) return } urls := string(burls) urls = strings.Trim(urls, "\n") log.Println(urls) spl := strings.Split(urls, "\n") log.Printf("spl: %d", len(spl)) switch len(spl) { case 1: w.WriteHeader(http.StatusNoContent) return case 2: stdout, err := combine(spl) if err != nil { w.WriteHeader(http.StatusInternalServerError) log.Println(err) return } w.Header().Set("Content-Type", "video/mp4") w.Header().Set("Connection", "keep-alive") w.Header().Set("Transfer-Encoding", "chunked") _, err = io.Copy(w, stdout) if err != nil { w.WriteHeader(http.StatusInternalServerError) log.Println(err) return } default: w.WriteHeader(http.StatusBadRequest) log.Println(err) return } } func main() { http.HandleFunc("/", stream) log.Fatal(http.ListenAndServe(":8080", nil)) }