Fix error in OS windows.

Changed the progressbar to the pipe protocol.
This commit is contained in:
Leonid Nikitin 2024-01-20 01:53:25 +06:00
parent ebc8832d4d
commit 77b847dde6
Signed by: kor-elf
GPG Key ID: 7DE8F80C5CEC2C0D
6 changed files with 153 additions and 89 deletions

View File

@ -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

View File

@ -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) {

View 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
}

View File

@ -0,0 +1,12 @@
//go:build !windows
// +build !windows
package helper
import (
"os/exec"
)
func PrepareBackgroundCommand(cmd *exec.Cmd) {
}

View 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}
}

View File

@ -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)