Как можно извлечь первый кадр из видео?

Как можно корректно извлечь первый кадр видео для использования в качестве превью, используя язык Go и утилиту ffmpeg? В коде есть функция, в которой реализована логика извлечения кадра. Как можно улучшить эту функцию и как ее можно использовать в контексте обработчика эндпоинта, который принимает FormData с видеофайлом?
  • 10 августа 2024 г. 15:03
Ответы на вопрос 2
Для извлечения первого кадра из видео с помощью языка Go и утилиты ffmpeg, можно использовать следующий код:

```go
package main

import (
	"bytes"
	"fmt"
	"log"
	"os/exec"
)

func extractVideoFrame(videoPath string) ([]byte, error) {
	cmd := exec.Command("ffmpeg", "-i", videoPath, "-vf", "thumbnail,scale=320:240", "-vframes", "1", "-f", "image2pipe", "-")
	var out bytes.Buffer
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		return nil, err
	}
	return out.Bytes(), nil
}

func main() {
	videoPath := "input_video.mp4"
	frameData, err := extractVideoFrame(videoPath)
	if err != nil {
		log.Fatal(err)
	}

	// сохранить кадр в файл или использовать данные кадра для отображения или других целей
	err = ioutil.WriteFile("first_frame.jpg", frameData, 0644)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Первый кадр успешно извлечен и сохранен в first_frame.jpg")
}
```

В данном коде функция `extractVideoFrame` принимает путь к видеофайлу и возвращает данные первого кадра в виде среза байтов. Функция использует утилиту ffmpeg для извлечения кадра. Важно помнить, что установленная утилита ffmpeg должна быть доступна в системном PATH для корректной работы.

Чтобы использовать эту функцию в контексте обработчика эндпоинта, принимающего FormData с видеофайлом, можно вызвать эту функцию в обработчике:

```go
func handleUploadVideo(w http.ResponseWriter, r *http.Request) {
    file, handler, err := r.FormFile("video")
    if err != nil {
        http.Error(w, "Failed to read video file", http.StatusBadRequest)
        return
    }
    defer file.Close()

    // сохранить видео на диск
    videoPath := handler.Filename
    f, err := os.OpenFile(videoPath, os.O_WRONLY|os.O_CREATE, 0666)
    if err != nil {
        http.Error(w, "Failed to save video file", http.StatusInternalServerError)
        return
    }
    defer f.Close()

    _, err = io.Copy(f, file)
    if err != nil {
        http.Error(w, "Failed to save video file", http.StatusInternalServerError)
        return
    }

    // извлечь первый кадр из видео
    frameData, err := extractVideoFrame(videoPath)
    if err != nil {
        http.Error(w, "Failed to extract video frame", http.StatusInternalServerError)
        return
    }

    // использовать данные кадра для отображения или других целей
    // например, отправить данные кадра в ответе на запрос
    w.Header().Set("Content-Type", "image/jpeg")
    w.Write(frameData)
}
```

В данном обработчике, при загрузке видеофайла, сначала файл сохраняется на диск, затем вызывается функция `extractVideoFrame` для извлечения первого кадра из видео. Полученные данные кадра можно использовать для отображения или других целей.
Похожие вопросы