all repos — guesser @ ab432ae955c70c86aea1ac6ad07c39871bc29727

merge.go (view raw)

  1package main
  2
  3import (
  4	"fmt"
  5	"io"
  6	"net/http"
  7	"os"
  8	"os/exec"
  9	"strconv"
 10	"strings"
 11)
 12
 13func saveUploadedFile(file io.Reader, path string) error {
 14	out, err := os.Create(path)
 15	if err != nil {
 16		return err
 17	}
 18	defer out.Close()
 19
 20	_, err = io.Copy(out, file)
 21	return err
 22}
 23
 24func processHandler(w http.ResponseWriter, r *http.Request) {
 25	if r.Method != http.MethodPost {
 26		http.Error(w, "Metodo non supportato", http.StatusMethodNotAllowed)
 27		return
 28	}
 29
 30	// Parse del form per ottenere i file e gli altri parametri
 31	if err := r.ParseMultipartForm(10 << 20); err != nil {
 32		http.Error(w, "Errore parsing form", http.StatusBadRequest)
 33		return
 34	}
 35
 36	// Recupera i file audio e video
 37	audioFile, _, err := r.FormFile("audioFile")
 38	if err != nil {
 39		http.Error(w, "File audio mancante", http.StatusBadRequest)
 40		return
 41	}
 42	defer audioFile.Close()
 43
 44	videoFile, _, err := r.FormFile("videoFile")
 45	if err != nil {
 46		http.Error(w, "File video mancante", http.StatusBadRequest)
 47		return
 48	}
 49	defer videoFile.Close()
 50
 51	// Salva i file temporaneamente
 52	audioPath := "temp_audio.opus"
 53	videoPath := "temp_video.mp4"
 54	outputPath := "output.mp4"
 55
 56	if err := saveUploadedFile(audioFile, audioPath); err != nil {
 57		http.Error(w, "Errore nel salvataggio del file audio", http.StatusInternalServerError)
 58		return
 59	}
 60	if err := saveUploadedFile(videoFile, videoPath); err != nil {
 61		http.Error(w, "Errore nel salvataggio del file video", http.StatusInternalServerError)
 62		return
 63	}
 64
 65	// Recupera i parametri di configurazione dal form
 66	skip, _ := strconv.ParseFloat(r.FormValue("skip"), 64)
 67	fade, _ := strconv.ParseFloat(r.FormValue("fade"), 64)
 68	delay, _ := strconv.ParseFloat(r.FormValue("delay"), 64)
 69	duration, _ := strconv.ParseFloat(r.FormValue("duration"), 64)
 70
 71	// Conversione delay in millisecondi
 72	delayMs := int(delay * 1000)
 73	fadeOutStart := duration - fade
 74
 75	// Costruzione del filtro audio
 76	audioFilter := fmt.Sprintf("afade=t=out:st=%.2f:d=%.2f", fadeOutStart, fade)
 77	if skip >= fade {
 78		audioFilter = fmt.Sprintf("afade=t=in:ss=0:d=%.2f,%s", fade, audioFilter)
 79	}
 80
 81	// Costruzione del comando ffmpeg
 82	ffmpegCommand := []string{
 83		"-i", videoPath,
 84		"-i", audioPath,
 85		"-filter_complex",
 86		fmt.Sprintf("[1:a]atrim=start=%.2f:end=%.2f,asetpts=PTS-STARTPTS,%s,adelay=%d|%d[song];[0:a][song]amix=inputs=2:duration=first[audio_mix];[0:v]copy[v]",
 87			skip, skip+duration, audioFilter, delayMs, delayMs),
 88		"-map", "[v]", "-map", "[audio_mix]",
 89		"-c:v", "libx264",
 90		"-c:a", "aac",
 91		"-shortest", outputPath,
 92		"-y",
 93	}
 94
 95	// Esecuzione del comando ffmpeg
 96	cmd := exec.Command("ffmpeg", ffmpegCommand...)
 97	println(strings.Join(ffmpegCommand, " "))
 98	cmd.Stderr = os.Stderr // Mostra eventuali errori in console
 99	cmd.Stdout = os.Stdout
100
101	if err := cmd.Run(); err != nil {
102		http.Error(w, "Errore durante l'esecuzione di ffmpeg", http.StatusInternalServerError)
103		return
104	}
105
106	// Impostazioni per scaricare il file di output
107	w.Header().Set("Content-Disposition", "attachment; filename=output.mp4")
108	w.Header().Set("Content-Type", "video/mp4")
109
110	// Restituisce il file output.mp4 in risposta
111	outputFile, err := os.Open(outputPath)
112	if err != nil {
113		http.Error(w, "Errore nell'apertura del file output", http.StatusInternalServerError)
114		return
115	}
116	defer outputFile.Close()
117
118	_, err = io.Copy(w, outputFile)
119	if err != nil {
120		http.Error(w, "Errore durante la copia del file", http.StatusInternalServerError)
121		return
122	}
123
124	// Pulizia dei file temporanei
125	os.Remove(audioPath)
126	os.Remove(videoPath)
127	os.Remove(outputPath)
128}