конвертация в webp проходит

main
parent e2c49422fb
commit 7b4776a1dc

@ -4,6 +4,7 @@ pic - работа с картинками
## История
- 29-07-2023 Первый коммит.
Сделал новый релиз для проверки - v0.0.2
- 30-07-2023 Начинаю использовать ffmpeg.
## Комментарии

@ -11,6 +11,7 @@ require (
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/estebangarcia21/subprocess v0.0.0-20230526204252-a1a6de4773be // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

@ -1,6 +1,8 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/estebangarcia21/subprocess v0.0.0-20230526204252-a1a6de4773be h1:Mf6Xc0DgENbsDgKn10KNCNmW9FYSTcMr2bFsJ9uzvX0=
github.com/estebangarcia21/subprocess v0.0.0-20230526204252-a1a6de4773be/go.mod h1:PlHe6+WP6t7m4ghYrX6GBzB0KZLdOKWz2Ih3h0nusAY=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
@ -15,11 +17,7 @@ github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

@ -2,7 +2,11 @@ package pic
import (
"fmt"
"io/ioutil"
"regexp"
"strings"
"github.com/estebangarcia21/subprocess"
//"github.com/jmoiron/sqlx"
)
@ -30,6 +34,7 @@ func NewPicture(album string) Picture {
}
// возвращает имя файла без расширения
// т.е. из test/filename.jpg получаем filename
func baseName(filename string) string {
// на всякий случай заменим обратный слэш
filename = strings.ReplaceAll(filename, "\\", "/")
@ -44,3 +49,84 @@ func baseName(filename string) string {
return fn[0]
}
// cmdFfmpeg формирует команду ffmpeg для последующего исполнения
// ffmpeg - увеличивает gif в 2 раза и сразу преобразует в .webp
// filename - сам файл gif
// Возвращает команду ffmpeg и выходной файл webp
func cmdFfmpeg(src string) (string, string, error) {
if !strings.HasSuffix(src, ".gif") {
return "", "", fmt.Errorf("файл не .gif")
}
webp := strings.ReplaceAll(src, ".gif", "-2x.webp")
cmd := fmt.Sprintf("ffmpeg -i \"%s\" -vf scale=iw*2:ih*2 -loop 0 \"%s\"", src, webp)
return cmd, webp, nil
}
type WebpFile struct {
filename string
width string
height string
}
// конвертация из .gif в .webp с изменением размеров файла
// filename - исходный файл gif
func convert(filename string) (WebpFile, error) {
webpfile := WebpFile{}
cmd, webp, err := cmdFfmpeg(filename)
if err != nil {
return webpfile, err
}
s := subprocess.New(cmd, subprocess.HideStderr)
if err := s.Exec(); err != nil {
return webpfile, fmt.Errorf("(%s) ffmpeg: %v", filename, err)
}
if s.ExitCode() != 0 {
return webpfile, fmt.Errorf("(%s): ffmpeg exit code: %d", filename, s.ExitCode())
}
// из вывода команды ffmpeg получим новый размер файла webp
w, h := getSize(s.StderrText())
webpfile = WebpFile{
filename: webp,
width: w,
height: h,
}
// fid := upload(newname)
// println(fid)
return webpfile, nil
}
// получает размер файла из вывода команды ffmpeg
// если пустая строка - бросаем панику
func getSize(out string) (string, string) {
if out == "" {
panic("пустая строка вывода ffmpeg")
}
lines := strings.Split(out, "\n")
for _, s := range lines {
if strings.Contains(s, "Stream #0:0: Video: webp") {
// fmt.Printf("== %s\n", s)
re := regexp.MustCompile(`(\d*)x(\d*)`)
matches := re.FindAllStringSubmatch(s, -1)
// fmt.Printf("matches: %v\n", matches)
return matches[0][1], matches[0][2]
}
}
return "0", "0"
}
func copyFile(src, dst string) error {
input, err := ioutil.ReadFile(src)
if err != nil {
return err
}
err = ioutil.WriteFile(dst, input, 0644)
if err != nil {
return err
}
return nil
}

@ -2,15 +2,18 @@ package pic
import (
//"log"
"log"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewPicture(t *testing.T) {
// для тестирования базу данных не учитываем
p := NewPicture("проверка")
assert.Equal(t, p.Album, "проверка", "должны быть одинаковыми")
p := NewPicture("альбом")
assert.Equal(t, p.Album, "альбом", "должны быть одинаковыми")
}
func TestBaseName(t *testing.T) {
@ -29,3 +32,48 @@ func TestBaseName(t *testing.T) {
base = baseName("test.jpg")
assert.NotEqual(t, base, "неверное имя", "должны быть разными")
}
func TestCmdFfmpeg(t *testing.T) {
// правильный файл
cmd, out, err := cmdFfmpeg("testdir\\test.gif")
log.Printf("cmd: %s\n", cmd)
assert.Nil(t, err)
assert.Equal(t, out, "testdir\\test-2x.webp", "должны быть одинаковыми")
assert.Contains(t, cmd, "ffmpeg", "команда должна сформироваться")
// не верный файл
cmd, out, err = cmdFfmpeg("test.jpg")
assert.Error(t, err, "должна быть ошибка")
assert.Equal(t, out, "", "должен быть пустой строкой")
assert.Equal(t, cmd, "", "должен быть пустой строкой")
}
func TestGetSize(t *testing.T) {
out := `
Stream #0:0: Video: webp <какой-то текст> 1200x1980 <еще какой-то текст>
`
w, h := getSize(out)
assert.Equal(t, w, "1200", "должны быть 1200")
assert.Equal(t, h, "1980", "должны быть 1980")
}
func TestConvert(t *testing.T) {
// предварительно скопируем тестовый файл во временный каталог
tmpgif := "test.gif"
require.FileExists(t, tmpgif)
tmpdir := t.TempDir()
filename := filepath.Join(tmpdir, tmpgif)
err := copyFile(tmpgif, filename)
require.NoError(t, err)
require.FileExists(t, filename)
webp, err := convert(filename)
assert.NoError(t, err)
require.FileExists(t, webp.filename)
// скопируем обратно, что бы посмотреть, что получилось
err = copyFile(webp.filename, "d:/projects/pic/test.webp")
assert.NoError(t, err)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 KiB

Loading…
Cancel
Save