gui-for-ffmpeg/src/handler/convertor.go

206 lines
5.0 KiB
Go
Raw Normal View History

package handler
import (
"bufio"
"errors"
"ffmpegGui/convertor"
"ffmpegGui/helper"
"ffmpegGui/setting"
"fyne.io/fyne/v2/widget"
"io"
"regexp"
"runtime"
"strconv"
"strings"
)
type ConvertorHandler struct {
convertorService convertor.ServiceContract
convertorView convertor.ViewContract
settingView setting.ViewContract
settingRepository setting.RepositoryContract
}
func NewConvertorHandler(
convertorService convertor.ServiceContract,
convertorView convertor.ViewContract,
settingView setting.ViewContract,
settingRepository setting.RepositoryContract,
) *ConvertorHandler {
return &ConvertorHandler{
convertorService,
convertorView,
settingView,
settingRepository,
}
}
func (h ConvertorHandler) GetConvertor() {
if h.checkingFFPathUtilities() == true {
h.convertorView.Main(h.runConvert)
return
}
h.settingView.SelectFFPath(h.saveSettingFFPath)
}
func (h ConvertorHandler) runConvert(setting convertor.HandleConvertSetting, progressbar *widget.ProgressBar) error {
totalDuration, err := h.convertorService.GetTotalDuration(setting.VideoFileInput)
if err != nil {
return err
}
progress := NewProgress(totalDuration, progressbar)
return h.convertorService.RunConvert(
convertor.ConvertSetting{
VideoFileInput: setting.VideoFileInput,
VideoFileOut: &convertor.File{
Path: setting.DirectoryForSave + helper.PathSeparator() + setting.VideoFileInput.Name + ".mp4",
Name: setting.VideoFileInput.Name,
Ext: ".mp4",
},
OverwriteOutputFiles: setting.OverwriteOutputFiles,
},
progress,
)
}
func (h ConvertorHandler) checkingFFPathUtilities() bool {
if h.checkingFFPath() == true {
return true
}
var pathsToFF []convertor.FFPathUtilities
if runtime.GOOS == "windows" {
pathsToFF = []convertor.FFPathUtilities{{"ffmpeg\\bin\\ffmpeg.exe", "ffmpeg\\bin\\ffprobe.exe"}}
} else {
pathsToFF = []convertor.FFPathUtilities{{"ffmpeg/bin/ffmpeg", "ffmpeg/bin/ffprobe"}, {"ffmpeg", "ffprobe"}}
}
for _, item := range pathsToFF {
ffmpegChecking, _ := h.convertorService.ChangeFFmpegPath(item.FFmpeg)
if ffmpegChecking == false {
continue
}
ffprobeChecking, _ := h.convertorService.ChangeFFprobePath(item.FFprobe)
if ffprobeChecking == false {
continue
}
ffmpegEntity := setting.Setting{Code: "ffmpeg", Value: item.FFmpeg}
_, _ = h.settingRepository.Create(ffmpegEntity)
ffprobeEntity := setting.Setting{Code: "ffprobe", Value: item.FFprobe}
_, _ = h.settingRepository.Create(ffprobeEntity)
return true
}
return false
}
func (h ConvertorHandler) saveSettingFFPath(ffmpegPath string, ffprobePath string) error {
ffmpegChecking, _ := h.convertorService.ChangeFFmpegPath(ffmpegPath)
if ffmpegChecking == false {
return errors.New("это не FFmpeg")
}
ffprobeChecking, _ := h.convertorService.ChangeFFprobePath(ffprobePath)
if ffprobeChecking == false {
return errors.New("это не FFprobe")
}
ffmpegEntity := setting.Setting{Code: "ffmpeg", Value: ffmpegPath}
_, _ = h.settingRepository.Create(ffmpegEntity)
ffprobeEntity := setting.Setting{Code: "ffprobe", Value: ffprobePath}
_, _ = h.settingRepository.Create(ffprobeEntity)
h.GetConvertor()
return nil
}
func (h ConvertorHandler) checkingFFPath() bool {
_, err := h.convertorService.GetFFmpegVesrion()
if err != nil {
return false
}
_, err = h.convertorService.GetFFprobeVersion()
if err != nil {
return false
}
return true
}
type progress struct {
totalDuration float64
progressbar *widget.ProgressBar
protocol string
}
func NewProgress(totalDuration float64, progressbar *widget.ProgressBar) progress {
return progress{
totalDuration: totalDuration,
progressbar: progressbar,
protocol: "pipe:",
}
}
func (p progress) GetProtocole() string {
return p.protocol
}
func (p progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error {
isProcessCompleted := false
var errorText string
p.progressbar.Value = 0
p.progressbar.Max = p.totalDuration
p.progressbar.Refresh()
progress := 0.0
go func() {
scannerErr := bufio.NewScanner(stdErr)
for scannerErr.Scan() {
errorText = scannerErr.Text()
}
if err := scannerErr.Err(); err != nil {
errorText = err.Error()
}
}()
scannerOut := bufio.NewScanner(stdOut)
for scannerOut.Scan() {
if isProcessCompleted != true {
isProcessCompleted = true
}
data := scannerOut.Text()
re := regexp.MustCompile(`frame=(\d+)`)
a := re.FindAllStringSubmatch(data, -1)
if len(a) > 0 && len(a[len(a)-1]) > 0 {
c, err := strconv.Atoi(a[len(a)-1][len(a[len(a)-1])-1])
if err != nil {
continue
}
progress = float64(c)
}
if strings.Contains(data, "progress=end") {
p.progressbar.Value = p.totalDuration
p.progressbar.Refresh()
isProcessCompleted = true
}
if p.progressbar.Value != progress {
p.progressbar.Value = progress
p.progressbar.Refresh()
}
}
if isProcessCompleted == false {
if len(errorText) == 0 {
errorText = "не смогли отконвертировать видео"
}
return errors.New(errorText)
}
return nil
}