convert-to-h264/convert.go

72 lines
1.5 KiB
Go
Raw Normal View History

2026-08-05 14:39:15 +03:00
package main
import (
"bytes"
"context"
"fmt"
"io"
"log"
"net/http"
"os/exec"
"time"
)
func compressRAMHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Только POST метод", http.StatusMethodNotAllowed)
return
}
w.Header().Set("Content-Type", "video/mp4")
w.Header().Set("Transfer-Encoding", "chunked")
ctx, cancel := context.WithTimeout(r.Context(), 60*time.Second)
defer cancel()
args := []string{
"-y",
"-analyzeduration", "10M",
"-probesize", "10M",
"-i", "pipe:0",
"-c:v", "libx264",
"-preset", "veryfast",
"-crf", "28",
"-threads", "4",
"-movflags", "frag_keyframe+empty_moov",
"-f", "mp4",
"pipe:1",
}
cmd := exec.CommandContext(ctx, "ffmpeg", args...)
cmd.Stdin = r.Body
// Буфер для сбора ошибок FFmpeg
var stderrBuf bytes.Buffer
cmd.Stderr = &stderrBuf
stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
http.Error(w, fmt.Sprintf("Ошибка pipe stdout: %v", err), http.StatusInternalServerError)
return
}
if err := cmd.Start(); err != nil {
http.Error(w, fmt.Sprintf("Ошибка запуска FFmpeg: %v", err), http.StatusInternalServerError)
return
}
_, _ = io.Copy(w, stdoutPipe)
if waitErr := cmd.Wait(); waitErr != nil {
log.Printf("FFmpeg завершился с ошибкой (%v):\n%s", waitErr, stderrBuf.String())
}
}
func main() {
http.HandleFunc("/compress", compressRAMHandler)
log.Println("RAM Converter запущен на :1554...")
log.Fatal(http.ListenAndServe("127.0.0.1:1554", nil))
}