|
@@ -12,6 +12,7 @@ import (
|
|
"log"
|
|
"log"
|
|
"net/http"
|
|
"net/http"
|
|
"os/exec"
|
|
"os/exec"
|
|
|
|
+ "time"
|
|
)
|
|
)
|
|
|
|
|
|
type TranscodeOutputResolution string
|
|
type TranscodeOutputResolution string
|
|
@@ -27,25 +28,30 @@ const (
|
|
func TranscodeAndStream(w http.ResponseWriter, r *http.Request, inputFile string, resolution TranscodeOutputResolution) {
|
|
func TranscodeAndStream(w http.ResponseWriter, r *http.Request, inputFile string, resolution TranscodeOutputResolution) {
|
|
// Build the FFmpeg command based on the resolution parameter
|
|
// Build the FFmpeg command based on the resolution parameter
|
|
var cmd *exec.Cmd
|
|
var cmd *exec.Cmd
|
|
|
|
+
|
|
|
|
+ transcodeFormatArgs := []string{"-f", "mp4", "-vcodec", "libx264", "-preset", "superfast", "-g", "60", "-movflags", "frag_keyframe+empty_moov+faststart", "pipe:1"}
|
|
|
|
+ var args []string
|
|
switch resolution {
|
|
switch resolution {
|
|
case "360p":
|
|
case "360p":
|
|
- cmd = exec.Command("ffmpeg", "-i", inputFile, "-vf", "scale=-1:360", "-f", "mp4", "-vcodec", "libx264", "-preset", "fast", "-movflags", "frag_keyframe+empty_moov", "pipe:1")
|
|
|
|
|
|
+ args = append([]string{"-i", inputFile, "-vf", "scale=-1:360"}, transcodeFormatArgs...)
|
|
case "720p":
|
|
case "720p":
|
|
- cmd = exec.Command("ffmpeg", "-i", inputFile, "-vf", "scale=-1:720", "-f", "mp4", "-vcodec", "libx264", "-preset", "fast", "-movflags", "frag_keyframe+empty_moov", "pipe:1")
|
|
|
|
|
|
+ args = append([]string{"-i", inputFile, "-vf", "scale=-1:720"}, transcodeFormatArgs...)
|
|
case "1080p":
|
|
case "1080p":
|
|
- cmd = exec.Command("ffmpeg", "-i", inputFile, "-vf", "scale=-1:1080", "-f", "mp4", "-vcodec", "libx264", "-preset", "fast", "-movflags", "frag_keyframe+empty_moov", "pipe:1")
|
|
|
|
|
|
+ args = append([]string{"-i", inputFile, "-vf", "scale=-1:1080"}, transcodeFormatArgs...)
|
|
case "":
|
|
case "":
|
|
// Original resolution
|
|
// Original resolution
|
|
- cmd = exec.Command("ffmpeg", "-i", inputFile, "-f", "mp4", "-vcodec", "libx264", "-preset", "fast", "-movflags", "frag_keyframe+empty_moov", "pipe:1")
|
|
|
|
|
|
+ args = append([]string{"-i", inputFile}, transcodeFormatArgs...)
|
|
default:
|
|
default:
|
|
http.Error(w, "Invalid resolution parameter", http.StatusBadRequest)
|
|
http.Error(w, "Invalid resolution parameter", http.StatusBadRequest)
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
+ cmd = exec.Command("ffmpeg", args...)
|
|
|
|
|
|
// Set response headers for streaming MP4 video
|
|
// Set response headers for streaming MP4 video
|
|
w.Header().Set("Content-Type", "video/mp4")
|
|
w.Header().Set("Content-Type", "video/mp4")
|
|
w.Header().Set("Transfer-Encoding", "chunked")
|
|
w.Header().Set("Transfer-Encoding", "chunked")
|
|
- w.Header().Set("Cache-Control", "no-cache")
|
|
|
|
|
|
+ w.Header().Set("Cache-Control", "public, max-age=3600, s-maxage=3600, must-revalidate")
|
|
|
|
+ w.Header().Set("Accept-Ranges", "bytes")
|
|
|
|
|
|
// Get the command output pipe
|
|
// Get the command output pipe
|
|
stdout, err := cmd.StdoutPipe()
|
|
stdout, err := cmd.StdoutPipe()
|
|
@@ -74,8 +80,10 @@ func TranscodeAndStream(w http.ResponseWriter, r *http.Request, inputFile string
|
|
// Monitor client connection close
|
|
// Monitor client connection close
|
|
go func() {
|
|
go func() {
|
|
<-r.Context().Done()
|
|
<-r.Context().Done()
|
|
|
|
+ time.Sleep(300 * time.Millisecond)
|
|
cmd.Process.Kill() // Kill the FFmpeg process when client disconnects
|
|
cmd.Process.Kill() // Kill the FFmpeg process when client disconnects
|
|
- close(done)
|
|
|
|
|
|
+ done <- struct{}{}
|
|
|
|
+ //close(done)
|
|
}()
|
|
}()
|
|
|
|
|
|
// Copy the command output to the HTTP response in a separate goroutine
|
|
// Copy the command output to the HTTP response in a separate goroutine
|
|
@@ -97,7 +105,7 @@ func TranscodeAndStream(w http.ResponseWriter, r *http.Request, inputFile string
|
|
|
|
|
|
go func() {
|
|
go func() {
|
|
if err := cmd.Wait(); err != nil {
|
|
if err := cmd.Wait(); err != nil {
|
|
- log.Printf("FFmpeg process failed: %v", err)
|
|
|
|
|
|
+ log.Printf("FFmpeg process exited: %v", err)
|
|
return
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
}()
|