Added the ability to automatically download FFmpeg from the site https://github.com/BtbN/FFmpeg-Builds/releases.

This commit is contained in:
Leonid Nikitin 2024-02-04 20:16:15 +06:00
parent a82d283c1a
commit d46d642e61
Signed by: kor-elf
GPG Key ID: 7DE8F80C5CEC2C0D
12 changed files with 302 additions and 19 deletions

View File

@ -22,6 +22,7 @@ type ViewContract interface {
ffprobePath string, ffprobePath string,
save func(ffmpegPath string, ffprobePath string) error, save func(ffmpegPath string, ffprobePath string) error,
cancel func(), cancel func(),
donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error,
) )
} }

View File

@ -17,6 +17,7 @@ func (v View) SelectFFPath(
currentPathFfprobe string, currentPathFfprobe string,
save func(ffmpegPath string, ffprobePath string) error, save func(ffmpegPath string, ffprobePath string) error,
cancel func(), cancel func(),
donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error,
) { ) {
errorMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255}) errorMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
errorMessage.TextSize = 16 errorMessage.TextSize = 16
@ -80,7 +81,11 @@ func (v View) SelectFFPath(
selectFFPathTitle := v.localizerService.GetMessage(&i18n.LocalizeConfig{ selectFFPathTitle := v.localizerService.GetMessage(&i18n.LocalizeConfig{
MessageID: "selectFFPathTitle", MessageID: "selectFFPathTitle",
}) })
v.w.SetContent(widget.NewCard(selectFFPathTitle, "", container.NewVBox(form)))
v.w.SetContent(widget.NewCard(selectFFPathTitle, "", container.NewVBox(
form,
v.blockDownloadFFmpeg(donwloadFFmpeg),
)))
} }
func (v View) getButtonSelectFile(path string) (filePath *string, button *widget.Button, buttonMessage *canvas.Text) { func (v View) getButtonSelectFile(path string) (filePath *string, button *widget.Button, buttonMessage *canvas.Text) {

View File

@ -0,0 +1,17 @@
//go:build !windows
// +build !windows
package convertor
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func (v View) blockDownloadFFmpeg(
donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error,
) *fyne.Container {
return container.NewVBox()
}

View File

@ -0,0 +1,63 @@
//go:build windows
// +build windows
package convertor
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/image/colornames"
"image/color"
)
func (v View) blockDownloadFFmpeg(
donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error,
) *fyne.Container {
errorDownloadFFmpegMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
errorDownloadFFmpegMessage.TextSize = 16
errorDownloadFFmpegMessage.TextStyle = fyne.TextStyle{Bold: true}
progressDownloadFFmpegMessage := canvas.NewText("", color.RGBA{R: 49, G: 127, B: 114, A: 255})
progressDownloadFFmpegMessage.TextSize = 16
progressDownloadFFmpegMessage.TextStyle = fyne.TextStyle{Bold: true}
progressBar := widget.NewProgressBar()
var buttonDownloadFFmpeg *widget.Button
buttonDownloadFFmpeg = widget.NewButton(v.localizerService.GetMessage(&i18n.LocalizeConfig{
MessageID: "download",
}), func() {
buttonDownloadFFmpeg.Disable()
err := donwloadFFmpeg(progressBar, progressDownloadFFmpegMessage)
if err != nil {
errorDownloadFFmpegMessage.Text = err.Error()
}
buttonDownloadFFmpeg.Enable()
})
downloadFFmpegFromSiteMessage := v.localizerService.GetMessage(&i18n.LocalizeConfig{
MessageID: "downloadFFmpegFromSite",
})
return container.NewVBox(
canvas.NewLine(colornames.Darkgreen),
widget.NewCard(v.localizerService.GetMessage(&i18n.LocalizeConfig{
MessageID: "buttonDownloadFFmpeg",
}), "", container.NewVBox(
widget.NewRichTextFromMarkdown(
downloadFFmpegFromSiteMessage+" [https://github.com/BtbN/FFmpeg-Builds/releases](https://github.com/BtbN/FFmpeg-Builds/releases)",
),
buttonDownloadFFmpeg,
errorDownloadFFmpegMessage,
progressDownloadFFmpegMessage,
progressBar,
)),
)
}

View File

@ -47,13 +47,13 @@ func (h ConvertorHandler) MainConvertor() {
h.convertorView.Main(h.runConvert) h.convertorView.Main(h.runConvert)
return return
} }
h.convertorView.SelectFFPath("", "", h.saveSettingFFPath, nil) h.convertorView.SelectFFPath("", "", h.saveSettingFFPath, nil, h.downloadFFmpeg)
} }
func (h ConvertorHandler) FfPathSelection() { func (h ConvertorHandler) FfPathSelection() {
ffmpeg, _ := h.convertorRepository.GetPathFfmpeg() ffmpeg, _ := h.convertorRepository.GetPathFfmpeg()
ffprobe, _ := h.convertorRepository.GetPathFfprobe() ffprobe, _ := h.convertorRepository.GetPathFfprobe()
h.convertorView.SelectFFPath(ffmpeg, ffprobe, h.saveSettingFFPath, h.MainConvertor) h.convertorView.SelectFFPath(ffmpeg, ffprobe, h.saveSettingFFPath, h.MainConvertor, h.downloadFFmpeg)
} }
func (h ConvertorHandler) GetFfmpegVersion() (string, error) { func (h ConvertorHandler) GetFfmpegVersion() (string, error) {

View File

@ -3,8 +3,16 @@
package handler package handler
import "git.kor-elf.net/kor-elf/gui-for-ffmpeg/convertor" import (
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/convertor"
)
func getPathsToFF() []convertor.FFPathUtilities { func getPathsToFF() []convertor.FFPathUtilities {
return []convertor.FFPathUtilities{{"ffmpeg/bin/ffmpeg", "ffmpeg/bin/ffprobe"}, {"ffmpeg", "ffprobe"}} return []convertor.FFPathUtilities{{"ffmpeg/bin/ffmpeg", "ffmpeg/bin/ffprobe"}, {"ffmpeg", "ffprobe"}}
} }
func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) {
return nil
}

View File

@ -3,8 +3,151 @@
package handler package handler
import "git.kor-elf.net/kor-elf/gui-for-ffmpeg/convertor" import (
"archive/zip"
"errors"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/convertor"
"github.com/nicksnyder/go-i18n/v2/i18n"
"io"
"net/http"
"os"
"path/filepath"
"strings"
)
func getPathsToFF() []convertor.FFPathUtilities { func getPathsToFF() []convertor.FFPathUtilities {
return []convertor.FFPathUtilities{{"ffmpeg\\bin\\ffmpeg.exe", "ffmpeg\\bin\\ffprobe.exe"}} return []convertor.FFPathUtilities{{"ffmpeg\\bin\\ffmpeg.exe", "ffmpeg\\bin\\ffprobe.exe"}}
} }
func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) {
isDirectoryFFmpeg := isDirectory("ffmpeg")
if isDirectoryFFmpeg == false {
err = os.Mkdir("ffmpeg", 0777)
if err != nil {
return err
}
}
progressMessage.Text = h.localizerService.GetMessage(&i18n.LocalizeConfig{
MessageID: "downloadRun",
})
progressMessage.Refresh()
err = downloadFile("ffmpeg/ffmpeg.zip", "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip", progressBar)
if err != nil {
return err
}
progressMessage.Text = h.localizerService.GetMessage(&i18n.LocalizeConfig{
MessageID: "unzipRun",
})
progressMessage.Refresh()
err = unZip("ffmpeg/ffmpeg.zip", "ffmpeg")
if err != nil {
return err
}
_ = os.Remove("ffmpeg/ffmpeg.zip")
progressMessage.Text = h.localizerService.GetMessage(&i18n.LocalizeConfig{
MessageID: "testFF",
})
progressMessage.Refresh()
err = h.saveSettingFFPath("ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffmpeg.exe", "ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffprobe.exe")
if err != nil {
return err
}
return nil
}
func downloadFile(filepath string, url string, progressBar *widget.ProgressBar) (err error) {
progressBar.Value = 0
progressBar.Max = 100
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
f, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer f.Close()
buf := make([]byte, 32*1024)
var downloaded int64
for {
n, err := resp.Body.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return err
}
if n > 0 {
f.Write(buf[:n])
downloaded += int64(n)
progressBar.Value = float64(downloaded) / float64(resp.ContentLength) * 100
progressBar.Refresh()
}
}
return nil
}
func unZip(fileZip string, directory string) error {
archive, err := zip.OpenReader(fileZip)
if err != nil {
return err
}
defer archive.Close()
for _, f := range archive.File {
filePath := filepath.Join(directory, f.Name)
if !strings.HasPrefix(filePath, filepath.Clean(directory)+string(os.PathSeparator)) {
return errors.New("invalid file path")
}
if f.FileInfo().IsDir() {
os.MkdirAll(filePath, os.ModePerm)
continue
}
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
return err
}
dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return err
}
fileInArchive, err := f.Open()
if err != nil {
return err
}
if _, err := io.Copy(dstFile, fileInArchive); err != nil {
return err
}
dstFile.Close()
fileInArchive.Close()
}
return nil
}
func isDirectory(path string) bool {
fileInfo, err := os.Stat(path)
if err != nil {
return false
}
return fileInfo.IsDir()
}

View File

@ -10,6 +10,10 @@ other = "About"
hash = "sha1-8bd565814118ba8b90c40eb5b62acf8d2676e7d6" hash = "sha1-8bd565814118ba8b90c40eb5b62acf8d2676e7d6"
other = "A simple interface for the FFmpeg console utility. \nBut I am not the author of the FFmpeg utility itself." other = "A simple interface for the FFmpeg console utility. \nBut I am not the author of the FFmpeg utility itself."
[buttonDownloadFFmpeg]
hash = "sha1-c223c2e15171156192bc3146aee91e6094bb475b"
other = "Download FFmpeg automatically"
[buttonForSelectedDirTitle] [buttonForSelectedDirTitle]
hash = "sha1-52b13f1b13e82d22e8c4102332db5d4ec551247b" hash = "sha1-52b13f1b13e82d22e8c4102332db5d4ec551247b"
other = "Folder where it will be saved:" other = "Folder where it will be saved:"
@ -42,6 +46,18 @@ other = "Convert"
hash = "sha1-4d972809e4c7f9c9ff2c110a126bbc183c9429ce" hash = "sha1-4d972809e4c7f9c9ff2c110a126bbc183c9429ce"
other = "Converter video files to mp4" other = "Converter video files to mp4"
[download]
hash = "sha1-fe8f79f29da457de2f6bc9531de6e536e0c426ad"
other = "Download"
[downloadFFmpegFromSite]
hash = "sha1-0889c95aa3a8659d8d903b4dab7097699c4d8aa4"
other = "Will be downloaded from the site:"
[downloadRun]
hash = "sha1-55f87f114628fa2d5d8e67d1e1cda22c0e4f9271"
other = "Downloading..."
[error] [error]
hash = "sha1-a7df8f8b5d754f226ac4cb320577fe692b33e483" hash = "sha1-a7df8f8b5d754f226ac4cb320577fe692b33e483"
other = "An error has occurred!" other = "An error has occurred!"
@ -138,6 +154,14 @@ other = "Specify the path to FFmpeg and FFprobe"
hash = "sha1-7f17c7c62a7fd8d1a508481f4778688927734c2f" hash = "sha1-7f17c7c62a7fd8d1a508481f4778688927734c2f"
other = "Settings" other = "Settings"
[testFF]
hash = "sha1-f5b8ed88e9609963035d2235be0a79bbec619976"
other = "Checking FFmpeg for serviceability..."
[titleDownloadLink] [titleDownloadLink]
hash = "sha1-92df86371f6c3a06ca1e4754f113142776a32d49" hash = "sha1-92df86371f6c3a06ca1e4754f113142776a32d49"
other = "You can download it from here" other = "You can download it from here"
[unzipRun]
hash = "sha1-c554dad13026668a1f6adf3171837c5d51bbac36"
other = "Unpacked..."

View File

@ -10,6 +10,10 @@ other = "Бағдарлама туралы"
hash = "sha1-8bd565814118ba8b90c40eb5b62acf8d2676e7d6" hash = "sha1-8bd565814118ba8b90c40eb5b62acf8d2676e7d6"
other = "FFmpeg консоль утилитасы үшін қарапайым интерфейс. \nБірақ мен FFmpeg утилитасының авторы емеспін." other = "FFmpeg консоль утилитасы үшін қарапайым интерфейс. \nБірақ мен FFmpeg утилитасының авторы емеспін."
[buttonDownloadFFmpeg]
hash = "sha1-c223c2e15171156192bc3146aee91e6094bb475b"
other = "FFmpeg автоматты түрде жүктеп алыңыз"
[buttonForSelectedDirTitle] [buttonForSelectedDirTitle]
hash = "sha1-52b13f1b13e82d22e8c4102332db5d4ec551247b" hash = "sha1-52b13f1b13e82d22e8c4102332db5d4ec551247b"
other = "Файлды сақтауға арналған каталог:" other = "Файлды сақтауға арналған каталог:"
@ -42,6 +46,18 @@ other = "Файлды түрлендіру"
hash = "sha1-4d972809e4c7f9c9ff2c110a126bbc183c9429ce" hash = "sha1-4d972809e4c7f9c9ff2c110a126bbc183c9429ce"
other = "Бейне файлдарын mp4 форматына түрлендіру" other = "Бейне файлдарын mp4 форматына түрлендіру"
[download]
hash = "sha1-fe8f79f29da457de2f6bc9531de6e536e0c426ad"
other = "Жүктеп алу"
[downloadFFmpegFromSite]
hash = "sha1-0889c95aa3a8659d8d903b4dab7097699c4d8aa4"
other = "Сайттан жүктеледі:"
[downloadRun]
hash = "sha1-55f87f114628fa2d5d8e67d1e1cda22c0e4f9271"
other = "Жүктеп алынуда..."
[error] [error]
hash = "sha1-a7df8f8b5d754f226ac4cb320577fe692b33e483" hash = "sha1-a7df8f8b5d754f226ac4cb320577fe692b33e483"
other = "Қате орын алды!" other = "Қате орын алды!"
@ -138,6 +154,14 @@ other = "FFmpeg және FFprobe жолын көрсетіңіз"
hash = "sha1-7f17c7c62a7fd8d1a508481f4778688927734c2f" hash = "sha1-7f17c7c62a7fd8d1a508481f4778688927734c2f"
other = "Параметрлер" other = "Параметрлер"
[testFF]
hash = "sha1-f5b8ed88e9609963035d2235be0a79bbec619976"
other = "FFmpeg функционалдығы тексерілуде..."
[titleDownloadLink] [titleDownloadLink]
hash = "sha1-92df86371f6c3a06ca1e4754f113142776a32d49" hash = "sha1-92df86371f6c3a06ca1e4754f113142776a32d49"
other = "Сіз оны осы жерден жүктей аласыз" other = "Сіз оны осы жерден жүктей аласыз"
[unzipRun]
hash = "sha1-c554dad13026668a1f6adf3171837c5d51bbac36"
other = "Орамнан шығарылуда..."

View File

@ -1,6 +1,7 @@
AlsoUsedProgram = "Также в программе используется:" AlsoUsedProgram = "Также в программе используется:"
about = "О программе" about = "О программе"
aboutText = "Простенький интерфейс для консольной утилиты FFmpeg. \nНо я не являюсь автором самой утилиты FFmpeg." aboutText = "Простенький интерфейс для консольной утилиты FFmpeg. \nНо я не являюсь автором самой утилиты FFmpeg."
buttonDownloadFFmpeg = "Скачать автоматически FFmpeg"
buttonForSelectedDirTitle = "Папка куда будет сохраняться:" buttonForSelectedDirTitle = "Папка куда будет сохраняться:"
cancel = "Отмена" cancel = "Отмена"
changeFFPath = "FFmpeg и FFprobe" changeFFPath = "FFmpeg и FFprobe"
@ -9,6 +10,9 @@ checkboxOverwriteOutputFilesTitle = "Разрешить перезаписать
choose = "выбрать" choose = "выбрать"
converterVideoFilesSubmitTitle = "Конвертировать" converterVideoFilesSubmitTitle = "Конвертировать"
converterVideoFilesTitle = "Конвертор видео файлов в mp4" converterVideoFilesTitle = "Конвертор видео файлов в mp4"
download = "Скачать"
downloadFFmpegFromSite = "Будет скачано с сайта:"
downloadRun = "Скачивается..."
error = "Произошла ошибка!" error = "Произошла ошибка!"
errorConverter = "не смогли отконвертировать видео" errorConverter = "не смогли отконвертировать видео"
errorDatabase = "не смогли создать файл 'database' в папке 'data'" errorDatabase = "не смогли создать файл 'database' в папке 'data'"
@ -33,4 +37,6 @@ programmVersion = "**Версия программы:** {{.Version}}"
save = "Сохранить" save = "Сохранить"
selectFFPathTitle = "Укажите путь к FFmpeg и к FFprobe" selectFFPathTitle = "Укажите путь к FFmpeg и к FFprobe"
settings = "Настройки" settings = "Настройки"
testFF = "Проверка FFmpeg на работоспособность..."
titleDownloadLink = "Скачать можно от сюда" titleDownloadLink = "Скачать можно от сюда"
unzipRun = "Распаковывается..."

View File

@ -1,7 +1,3 @@
[AlsoUsedProgram] [testFF]
hash = "sha1-a72be72e7808bb8a0144ed7a93acb29c568b1ed4" hash = "sha1-f5b8ed88e9609963035d2235be0a79bbec619976"
other = "The program also uses:" other = "Checking FFmpeg for serviceability..."
[licenseLinkOther]
hash = "sha1-359fff328717c05104e51a2d29f05bf1875d26b7"
other = "Licenses from other products used in the program"

View File

@ -1,7 +1,3 @@
[AlsoUsedProgram] [testFF]
hash = "sha1-a72be72e7808bb8a0144ed7a93acb29c568b1ed4" hash = "sha1-f5b8ed88e9609963035d2235be0a79bbec619976"
other = "Бағдарлама сонымен қатар пайдаланады:" other = "FFmpeg функционалдығы тексерілуде..."
[licenseLinkOther]
hash = "sha1-359fff328717c05104e51a2d29f05bf1875d26b7"
other = "Бағдарламада пайдаланылатын басқа өнімдердің лицензиялары"