Fix error in OS windows.
Changed the progressbar to the pipe protocol.
This commit is contained in:
		@@ -2,6 +2,8 @@ package convertor
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"ffmpegGui/helper"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strconv"
 | 
			
		||||
@@ -9,7 +11,7 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ServiceContract interface {
 | 
			
		||||
	RunConvert(setting ConvertSetting) error
 | 
			
		||||
	RunConvert(setting ConvertSetting, progress ProgressContract) error
 | 
			
		||||
	GetTotalDuration(file *File) (float64, error)
 | 
			
		||||
	GetFFmpegVesrion() (string, error)
 | 
			
		||||
	GetFFprobeVersion() (string, error)
 | 
			
		||||
@@ -17,6 +19,11 @@ type ServiceContract interface {
 | 
			
		||||
	ChangeFFprobePath(path string) (bool, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ProgressContract interface {
 | 
			
		||||
	GetProtocole() string
 | 
			
		||||
	Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FFPathUtilities struct {
 | 
			
		||||
	FFmpeg  string
 | 
			
		||||
	FFprobe string
 | 
			
		||||
@@ -35,7 +42,6 @@ type File struct {
 | 
			
		||||
type ConvertSetting struct {
 | 
			
		||||
	VideoFileInput       *File
 | 
			
		||||
	VideoFileOut         *File
 | 
			
		||||
	SocketPath           string
 | 
			
		||||
	OverwriteOutputFiles bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -49,20 +55,36 @@ func NewService(ffPathUtilities FFPathUtilities) *Service {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s Service) RunConvert(setting ConvertSetting) error {
 | 
			
		||||
func (s Service) RunConvert(setting ConvertSetting, progress ProgressContract) error {
 | 
			
		||||
	overwriteOutputFiles := "-n"
 | 
			
		||||
	if setting.OverwriteOutputFiles == true {
 | 
			
		||||
		overwriteOutputFiles = "-y"
 | 
			
		||||
	}
 | 
			
		||||
	args := []string{overwriteOutputFiles, "-i", setting.VideoFileInput.Path, "-c:v", "libx264", "-progress", "unix://" + setting.SocketPath, setting.VideoFileOut.Path}
 | 
			
		||||
	args := []string{overwriteOutputFiles, "-i", setting.VideoFileInput.Path, "-c:v", "libx264", "-progress", progress.GetProtocole(), setting.VideoFileOut.Path}
 | 
			
		||||
	cmd := exec.Command(s.ffPathUtilities.FFmpeg, args...)
 | 
			
		||||
	helper.PrepareBackgroundCommand(cmd)
 | 
			
		||||
 | 
			
		||||
	out, err := cmd.CombinedOutput()
 | 
			
		||||
	stdOut, err := cmd.StdoutPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		errStringArr := regexp.MustCompile("\r?\n").Split(strings.TrimSpace(string(out)), -1)
 | 
			
		||||
		if len(errStringArr) > 1 {
 | 
			
		||||
			return errors.New(errStringArr[len(errStringArr)-1])
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	stdErr, err := cmd.StderrPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = cmd.Start()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = progress.Run(stdOut, stdErr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = cmd.Wait()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -72,6 +94,7 @@ func (s Service) RunConvert(setting ConvertSetting) error {
 | 
			
		||||
func (s Service) GetTotalDuration(file *File) (duration float64, err error) {
 | 
			
		||||
	args := []string{"-v", "error", "-select_streams", "v:0", "-count_packets", "-show_entries", "stream=nb_read_packets", "-of", "csv=p=0", file.Path}
 | 
			
		||||
	cmd := exec.Command(s.ffPathUtilities.FFprobe, args...)
 | 
			
		||||
	helper.PrepareBackgroundCommand(cmd)
 | 
			
		||||
	out, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		errString := strings.TrimSpace(string(out))
 | 
			
		||||
@@ -85,6 +108,7 @@ func (s Service) GetTotalDuration(file *File) (duration float64, err error) {
 | 
			
		||||
 | 
			
		||||
func (s Service) GetFFmpegVesrion() (string, error) {
 | 
			
		||||
	cmd := exec.Command(s.ffPathUtilities.FFmpeg, "-version")
 | 
			
		||||
	helper.PrepareBackgroundCommand(cmd)
 | 
			
		||||
	out, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
@@ -95,6 +119,7 @@ func (s Service) GetFFmpegVesrion() (string, error) {
 | 
			
		||||
 | 
			
		||||
func (s Service) GetFFprobeVersion() (string, error) {
 | 
			
		||||
	cmd := exec.Command(s.ffPathUtilities.FFprobe, "-version")
 | 
			
		||||
	helper.PrepareBackgroundCommand(cmd)
 | 
			
		||||
	out, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
@@ -105,6 +130,7 @@ func (s Service) GetFFprobeVersion() (string, error) {
 | 
			
		||||
 | 
			
		||||
func (s Service) ChangeFFmpegPath(path string) (bool, error) {
 | 
			
		||||
	cmd := exec.Command(path, "-version")
 | 
			
		||||
	helper.PrepareBackgroundCommand(cmd)
 | 
			
		||||
	out, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
@@ -118,6 +144,7 @@ func (s Service) ChangeFFmpegPath(path string) (bool, error) {
 | 
			
		||||
 | 
			
		||||
func (s Service) ChangeFFprobePath(path string) (bool, error) {
 | 
			
		||||
	cmd := exec.Command(path, "-version")
 | 
			
		||||
	helper.PrepareBackgroundCommand(cmd)
 | 
			
		||||
	out, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
 
 | 
			
		||||
@@ -12,8 +12,7 @@ import (
 | 
			
		||||
 | 
			
		||||
type ViewContract interface {
 | 
			
		||||
	Main(
 | 
			
		||||
		runConvert func(setting HandleConvertSetting) error,
 | 
			
		||||
		getSocketPath func(*File, *widget.ProgressBar) (string, error),
 | 
			
		||||
		runConvert func(setting HandleConvertSetting, progressbar *widget.ProgressBar) error,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -24,7 +23,6 @@ type View struct {
 | 
			
		||||
type HandleConvertSetting struct {
 | 
			
		||||
	VideoFileInput       *File
 | 
			
		||||
	DirectoryForSave     string
 | 
			
		||||
	SocketPath           string
 | 
			
		||||
	OverwriteOutputFiles bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -39,8 +37,7 @@ func NewView(w fyne.Window) *View {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v View) Main(
 | 
			
		||||
	runConvert func(setting HandleConvertSetting) error,
 | 
			
		||||
	getSocketPath func(*File, *widget.ProgressBar) (string, error),
 | 
			
		||||
	runConvert func(setting HandleConvertSetting, progressbar *widget.ProgressBar) error,
 | 
			
		||||
) {
 | 
			
		||||
	form := &widget.Form{}
 | 
			
		||||
 | 
			
		||||
@@ -61,7 +58,7 @@ func (v View) Main(
 | 
			
		||||
	form.Items = []*widget.FormItem{
 | 
			
		||||
		{Text: "Файл для ковертации:", Widget: fileVideoForConversion},
 | 
			
		||||
		{Widget: fileVideoForConversionMessage},
 | 
			
		||||
		{Text: "Папка куда будет сохранятся:", Widget: buttonForSelectedDir},
 | 
			
		||||
		{Text: "Папка куда будет сохраняться:", Widget: buttonForSelectedDir},
 | 
			
		||||
		{Widget: buttonForSelectedDirMessage},
 | 
			
		||||
		{Widget: checkboxOverwriteOutputFiles},
 | 
			
		||||
	}
 | 
			
		||||
@@ -85,21 +82,12 @@ func (v View) Main(
 | 
			
		||||
		buttonForSelectedDir.Disable()
 | 
			
		||||
		form.Disable()
 | 
			
		||||
 | 
			
		||||
		socketPath, err := getSocketPath(fileInput, progress)
 | 
			
		||||
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			showConversionMessage(conversionMessage, err)
 | 
			
		||||
			enableFormConversion(enableFormConversionStruct)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		setting := HandleConvertSetting{
 | 
			
		||||
			VideoFileInput:       fileInput,
 | 
			
		||||
			DirectoryForSave:     *pathToSaveDirectory,
 | 
			
		||||
			SocketPath:           socketPath,
 | 
			
		||||
			OverwriteOutputFiles: isOverwriteOutputFiles,
 | 
			
		||||
		}
 | 
			
		||||
		err = runConvert(setting)
 | 
			
		||||
		err := runConvert(setting, progress)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			showConversionMessage(conversionMessage, err)
 | 
			
		||||
			enableFormConversion(enableFormConversionStruct)
 | 
			
		||||
@@ -108,8 +96,9 @@ func (v View) Main(
 | 
			
		||||
		enableFormConversion(enableFormConversionStruct)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v.w.SetContent(widget.NewCard("Конвертор видео файлов", "", container.NewVBox(form, conversionMessage, progress)))
 | 
			
		||||
	v.w.SetContent(widget.NewCard("Конвертор видео файлов в mp4", "", container.NewVBox(form, conversionMessage, progress)))
 | 
			
		||||
	form.Disable()
 | 
			
		||||
	progress.Hide()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v View) getButtonFileVideoForConversion(form *widget.Form, progress *widget.ProgressBar, conversionMessage *canvas.Text) (*widget.Button, *canvas.Text, *File) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,22 +1,17 @@
 | 
			
		||||
package handler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"ffmpegGui/convertor"
 | 
			
		||||
	"ffmpegGui/helper"
 | 
			
		||||
	"ffmpegGui/setting"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"fyne.io/fyne/v2/widget"
 | 
			
		||||
	"log"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
	"io"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ConvertorHandler struct {
 | 
			
		||||
@@ -42,67 +37,18 @@ func NewConvertorHandler(
 | 
			
		||||
 | 
			
		||||
func (h ConvertorHandler) GetConvertor() {
 | 
			
		||||
	if h.checkingFFPathUtilities() == true {
 | 
			
		||||
		h.convertorView.Main(h.runConvert, h.getSockPath)
 | 
			
		||||
		h.convertorView.Main(h.runConvert)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	h.settingView.SelectFFPath(h.saveSettingFFPath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h ConvertorHandler) getSockPath(file *convertor.File, progressbar *widget.ProgressBar) (string, error) {
 | 
			
		||||
	totalDuration, err := h.convertorService.GetTotalDuration(file)
 | 
			
		||||
 | 
			
		||||
func (h ConvertorHandler) runConvert(setting convertor.HandleConvertSetting, progressbar *widget.ProgressBar) error {
 | 
			
		||||
	totalDuration, err := h.convertorService.GetTotalDuration(setting.VideoFileInput)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	progressbar.Value = 0
 | 
			
		||||
	progressbar.Max = totalDuration
 | 
			
		||||
	progressbar.Show()
 | 
			
		||||
	progressbar.Refresh()
 | 
			
		||||
 | 
			
		||||
	rand.Seed(time.Now().Unix())
 | 
			
		||||
	sockFileName := path.Join(os.TempDir(), fmt.Sprintf("%d_sock", rand.Int()))
 | 
			
		||||
	l, err := net.Listen("unix", sockFileName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		re := regexp.MustCompile(`frame=(\d+)`)
 | 
			
		||||
		fd, err := l.Accept()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal("accept error:", err)
 | 
			
		||||
		}
 | 
			
		||||
		buf := make([]byte, 16)
 | 
			
		||||
		data := ""
 | 
			
		||||
		progress := 0.0
 | 
			
		||||
		for {
 | 
			
		||||
			_, err := fd.Read(buf)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			data += string(buf)
 | 
			
		||||
			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 {
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				progress = float64(c)
 | 
			
		||||
			}
 | 
			
		||||
			if strings.Contains(data, "progress=end") {
 | 
			
		||||
				progress = totalDuration
 | 
			
		||||
			}
 | 
			
		||||
			if progressbar.Value != progress {
 | 
			
		||||
				progressbar.Value = progress
 | 
			
		||||
				progressbar.Refresh()
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	return sockFileName, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h ConvertorHandler) runConvert(setting convertor.HandleConvertSetting) error {
 | 
			
		||||
	progress := NewProgress(totalDuration, progressbar)
 | 
			
		||||
 | 
			
		||||
	return h.convertorService.RunConvert(
 | 
			
		||||
		convertor.ConvertSetting{
 | 
			
		||||
@@ -112,9 +58,9 @@ func (h ConvertorHandler) runConvert(setting convertor.HandleConvertSetting) err
 | 
			
		||||
				Name: setting.VideoFileInput.Name,
 | 
			
		||||
				Ext:  ".mp4",
 | 
			
		||||
			},
 | 
			
		||||
			SocketPath:           setting.SocketPath,
 | 
			
		||||
			OverwriteOutputFiles: setting.OverwriteOutputFiles,
 | 
			
		||||
		},
 | 
			
		||||
		progress,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -182,3 +128,79 @@ func (h ConvertorHandler) checkingFFPath() bool {
 | 
			
		||||
 | 
			
		||||
	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.Show()
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								src/helper/prepare_background_command.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/helper/prepare_background_command.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
//go:build !windows
 | 
			
		||||
// +build !windows
 | 
			
		||||
 | 
			
		||||
package helper
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os/exec"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func PrepareBackgroundCommand(cmd *exec.Cmd) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/helper/prepare_background_command_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/helper/prepare_background_command_windows.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
//go:build windows
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package helper
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func PrepareBackgroundCommand(cmd *exec.Cmd) {
 | 
			
		||||
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
 | 
			
		||||
}
 | 
			
		||||
@@ -15,12 +15,13 @@ import (
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//const appVersion string = "0.1.0"
 | 
			
		||||
//const appVersion string = "0.1.1"
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	a := app.New()
 | 
			
		||||
	w := a.NewWindow("GUI FFMpeg!")
 | 
			
		||||
	w.Resize(fyne.Size{Width: 800, Height: 600})
 | 
			
		||||
	w.CenterOnScreen()
 | 
			
		||||
 | 
			
		||||
	errorView := myError.NewView(w)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user