Files
transcriber/internal/adapter/metaviewer/ffmpeg/ffmpeg.go

73 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package ffmpeg
import (
"encoding/json"
"fmt"
"os"
"os/exec"
"strconv"
"git.vakhrushev.me/av/transcriber/internal/contract"
)
const ffprobeExecutable = "ffprobe"
type FfmpegMetaViewer struct {
}
// ffprobeOutput представляет структуру JSON-ответа от ffprobe
type ffprobeOutput struct {
Format struct {
Duration string `json:"duration"`
} `json:"format"`
}
func NewFfmpegMetaViewer() *FfmpegMetaViewer {
return &FfmpegMetaViewer{}
}
func (m *FfmpegMetaViewer) GetInfo(src string) (*contract.AudioInfo, error) {
// Проверяем существование исходного файла
if _, err := os.Stat(src); os.IsNotExist(err) {
return nil, fmt.Errorf("input file does not exist: %s", src)
}
// Проверяем, что ffprobe доступен в системе
if _, err := exec.LookPath(ffprobeExecutable); err != nil {
return nil, fmt.Errorf("ffprobe not found in PATH: %w", err)
}
// Создаем команду ffprobe для получения метаданных
cmd := exec.Command(ffprobeExecutable,
"-v", "quiet", // тихий режим (без лишнего вывода)
"-print_format", "json", // вывод в формате JSON
"-show_format", // показать информацию о формате
src, // входной файл
)
// Выполняем команду и получаем вывод
output, err := cmd.Output()
if err != nil {
return nil, fmt.Errorf("ffprobe execution failed: %w", err)
}
// Парсим JSON-ответ
var probeResult ffprobeOutput
if err := json.Unmarshal(output, &probeResult); err != nil {
return nil, fmt.Errorf("failed to parse ffprobe output: %w", err)
}
// Конвертируем длительность из строки в секунды
durationFloat, err := strconv.ParseFloat(probeResult.Format.Duration, 64)
if err != nil {
return nil, fmt.Errorf("failed to parse duration: %w", err)
}
// Округляем до целых секунд
durationSeconds := int(durationFloat + 0.5) // +0.5 для правильного округления
return &contract.AudioInfo{
Seconds: durationSeconds,
}, nil
}