СЕРГЕЙ

This commit is contained in:
hhu67 2026-08-05 15:17:02 +03:00
parent f84bef5ffa
commit 12586c1260
5 changed files with 61 additions and 13 deletions

6
.idea/vcs.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

0
compressed.mp4 Normal file
View file

View file

@ -3,34 +3,66 @@ package main
import (
"bytes"
"context"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"time"
)
func compressRAMHandler(w http.ResponseWriter, r *http.Request) {
start := time.Now()
log.Printf("[+] Новый запрос от %s", r.RemoteAddr)
if r.Method != http.MethodPost {
http.Error(w, "Только POST метод", http.StatusMethodNotAllowed)
return
}
// 1. Создаем временный файл в RAM (/tmp работает на tmpfs)
tmpFile, err := os.CreateTemp("", "input-video-*.mp4")
if err != nil {
log.Printf("[-] Ошибка создания tmp-файла: %v", err)
http.Error(w, "Ошибка выpoint буфера RAM", http.StatusInternalServerError)
return
}
tmpFilePath := tmpFile.Name()
defer os.Remove(tmpFilePath) // Удаляем файл после завершения работы
// 2. Копируем тело запроса во временный файл
copiedBytes, err := io.Copy(tmpFile, r.Body)
_ = tmpFile.Close() // Обязательно закрываем файл перед чтением в FFmpeg!
if err != nil {
log.Printf("[-] Ошибка вычитывания Body: %v (получено %d байт)", err, copiedBytes)
http.Error(w, "Ошибка загрузки файла", http.StatusBadRequest)
return
}
log.Printf("[+] Файл полностью загружен в RAM: %d байт (%.2f MB) за %v",
copiedBytes, float64(copiedBytes)/(1024*1024), time.Since(start))
if copiedBytes == 0 {
log.Printf("[-] Ошибка: Прилетело 0 байт!")
http.Error(w, "Пустой файл", http.StatusBadRequest)
return
}
// 3. Заголовки ответа
w.Header().Set("Content-Type", "video/mp4")
w.Header().Set("Transfer-Encoding", "chunked")
ctx, cancel := context.WithTimeout(r.Context(), 60*time.Second)
ctx, cancel := context.WithTimeout(r.Context(), 120*time.Second)
defer cancel()
// 4. Запуск FFmpeg
args := []string{
"-y",
"-analyzeduration", "10M",
"-probesize", "10M",
"-i", "pipe:0",
"-i", tmpFilePath,
"-c:v", "libx264",
"-preset", "veryfast",
"-crf", "28",
"-crf", "26",
"-threads", "4",
"-movflags", "frag_keyframe+empty_moov",
"-f", "mp4",
@ -39,27 +71,32 @@ func compressRAMHandler(w http.ResponseWriter, r *http.Request) {
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)
log.Printf("[-] Ошибка stdout pipe: %v", err)
http.Error(w, "Ошибка FFmpeg", http.StatusInternalServerError)
return
}
if err := cmd.Start(); err != nil {
http.Error(w, fmt.Sprintf("Ошибка запуска FFmpeg: %v", err), http.StatusInternalServerError)
log.Printf("[-] Ошибка старта FFmpeg: %v", err)
http.Error(w, "Ошибка старта FFmpeg", http.StatusInternalServerError)
return
}
_, _ = io.Copy(w, stdoutPipe)
log.Printf("[+] FFmpeg успешно запущен, начинаем стримить ответ...")
// 5. Потоково отдаем сжатый ответ
written, _ := io.Copy(w, stdoutPipe)
if waitErr := cmd.Wait(); waitErr != nil {
log.Printf("FFmpeg завершился с ошибкой (%v):\n%s", waitErr, stderrBuf.String())
log.Printf("[-] FFmpeg завершился с ошибкой: %v\nЛог FFmpeg:\n%s", waitErr, stderrBuf.String())
} else {
log.Printf("[+] Обработка завершена успешно! Отправлено клиенту: %d байт (%.2f MB). Общее время: %v",
written, float64(written)/(1024*1024), time.Since(start))
}
}

Binary file not shown.

5
main.zsh Normal file
View file

@ -0,0 +1,5 @@
curl -X POST \
-H "Content-Type: video/mp4" \
--data-binary "@/home/hhu67/Downloads/fff" \
https://api.convert.hhu67.pw/compress \
-o compressed.mp4