Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Replace lilliput with govips #312

Merged
merged 22 commits into from
Oct 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
## Unreleased

- Breaking: Go version 1.17 is now the minimum required version to build this. (#292)
- Breaking: Thumbnail generation now requires libvips. See [docs/build.md](./docs/build.md) for prerequisite instructions. (#366, #369)
- Breaking: `enable-lilliput` config renamed to `enable-animated-thumbnails`. (#312)
- Breaking: Thumbnail generation now requires libvips. See [docs/build.md](./docs/build.md) for prerequisite instructions. (#366, #369, #312)
- Breaking: Resolver caches are now stored in PostgreSQL. See [docs/build.md](./docs/build.md) for prerequisite instructions. (#271)
- PDF: Generate customized tooltips for PDF files. (#374, #377)
- Twitter: Generate thumbnails with all images of a tweet. (#373)
Expand Down
6 changes: 3 additions & 3 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
# Max content size in bytes - requests with body bigger than this value will be skipped
#max-content-length: 5242880

# When enabled, will attempt to use lilliput library for building animated thumbnails.
# Can increase memory usage by a lot.
#enable-lilliput: true
# When enabled, will attempt to use libvips library to build animated thumbnails.
# Can increase CPU usage and cache storage by a lot. Enabled by default.
#enable-animated-thumbnails: true

# Maximum width/height pixel size count of the thumbnails sent to the clients.
#max-thumbnail-size: 300
Expand Down
2 changes: 1 addition & 1 deletion docs/chatterino-api.service
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ RestartSec=5s
;Environment="CHATTERINO_API_BASE_URL="
;Environment="CHATTERINO_API_BIND_ADDRESS=:1234"
;Environment="CHATTERINO_API_MAX_CONTENT_LENGTH=5242880"
;Environment="CHATTERINO_API_ENABLE_LILLIPUT=true"
;Environment="CHATTERINO_API_ENABLE_ANIMATED_THUMBNAILS=true"
;Environment="CHATTERINO_API_DISCORD_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
;Environment="CHATTERINO_API_CACHE_TWITCH_CLIENT_ID=XXXXXXXXXXXXXXXXXXXXXXXX"
;Environment="CHATTERINO_API_TWITCH_CLIENT_SECRET=XXXXXXXXXXXXXXXXXXXXXXXX"
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ go 1.18
require (
github.com/PuerkitoBio/goquery v1.8.0
github.com/davidbyttow/govips/v2 v2.11.0
github.com/discord/lilliput v0.0.0-20210720001558-e1547514bd5f
github.com/dyatlov/go-oembed v0.0.0-20191103150536-a57c85b3b37c
github.com/frankban/quicktest v1.14.3
github.com/go-chi/chi/v5 v5.0.7
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ 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/davidbyttow/govips/v2 v2.11.0 h1:eJY+Sgt2LRVh6TFSNMnl5rrFkDfuToG5uE5aLSV1jvM=
github.com/davidbyttow/govips/v2 v2.11.0/go.mod h1:goq38QD8XEMz2aWEeucEZqRxAWsemIN40vbUqfPfTAw=
github.com/discord/lilliput v0.0.0-20210720001558-e1547514bd5f h1:vM63WJhNbdzbgQdZv+6aNy8TUvj7y3hxuYdIWB6SGro=
github.com/discord/lilliput v0.0.0-20210720001558-e1547514bd5f/go.mod h1:0euuUBAD72MAYRm2ElLaG1h0nBR+CgpfnKc/U6y/uE8=
github.com/dyatlov/go-oembed v0.0.0-20191103150536-a57c85b3b37c h1:MEV1LrQtCBGacXajlT4CSuYWbZuLl/qaZVqwoOmwAbU=
github.com/dyatlov/go-oembed v0.0.0-20191103150536-a57c85b3b37c/go.mod h1:DjlDZiZGRRKbiJZmiEiiXozsBQAQzHmxwHKFeXifL2g=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
Expand Down
6 changes: 3 additions & 3 deletions internal/resolvers/default/link_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,9 @@ func New(ctx context.Context, cfg config.APIConfig, pool db.Pool, helixClient *h
contentTypeResolvers: contentTypeResolvers,
}
thumbnailLoader := &ThumbnailLoader{
baseURL: cfg.BaseURL,
maxContentLength: cfg.MaxContentLength,
enableLilliput: cfg.EnableLilliput,
baseURL: cfg.BaseURL,
maxContentLength: cfg.MaxContentLength,
enableAnimatedThumbnails: cfg.EnableAnimatedThumbnails,
}

thumbnailCache := cache.NewPostgreSQLCache(
Expand Down
10 changes: 5 additions & 5 deletions internal/resolvers/default/thumbnail_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import (
)

type ThumbnailLoader struct {
baseURL string
maxContentLength uint64
enableLilliput bool
baseURL string
maxContentLength uint64
enableAnimatedThumbnails bool
}

func (l *ThumbnailLoader) Load(ctx context.Context, urlString string, r *http.Request) ([]byte, *int, *string, time.Duration, error) {
Expand Down Expand Up @@ -81,11 +81,11 @@ func (l *ThumbnailLoader) Load(ctx context.Context, urlString string, r *http.Re
}

var image []byte
tryAnimatedThumb := l.enableLilliput && thumbnail.IsAnimatedThumbnailType(contentType)
tryAnimatedThumb := l.enableAnimatedThumbnails && thumbnail.IsAnimatedThumbnailType(contentType)

// attempt building an animated image
if tryAnimatedThumb {
image, err = thumbnail.BuildAnimatedThumbnail(inputBuf, resp)
image, err = thumbnail.BuildAnimatedThumbnail(ctx, inputBuf, resp)
}

// fallback to static image if animated image building failed or is disabled
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func init() {
pflag.StringP("base-url", "b", "", "Base URL to which clients will make their requests. Useful if the API is proxied through reverse proxy like nginx. Value needs to contain full URL with protocol scheme, e.g. https://braize.pajlada.com/chatterino")
pflag.StringP("bind-address", "l", ":1234", "Address to which API will bind and start listening on")
pflag.Uint64("max-content-length", 5*1024*1024, "Max content size in bytes - requests with body bigger than this value will be skipped")
pflag.Bool("enable-lilliput", true, "When enabled, will attempt to use lilliput library for building animated thumbnails. Can increase memory usage by a lot")
pflag.Bool("enable-animated-thumbnails", true, "When enabled, will attempt to use libvips library to build animated thumbnails. Can increase CPU usage and cache storage by a lot. Enabled by default")
pflag.Uint("max-thumbnail-size", 300, "Maximum width/height pixel size count of the thumbnails sent to the clients.")
pflag.String("log-level", "info", "Log level")
pflag.Bool("log-development", false, "Enable development logging for warnings and above, this includes stack traces")
Expand Down
10 changes: 5 additions & 5 deletions pkg/config/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package config
type APIConfig struct {
// Core

BaseURL string `mapstructure:"base-url" json:"base-url"`
BindAddress string `mapstructure:"bind-address" json:"bind-address"`
MaxContentLength uint64 `mapstructure:"max-content-length" json:"max-content-length"`
EnableLilliput bool `mapstructure:"enable-lilliput" json:"enable-lilliput"`
MaxThumbnailSize uint `mapstructure:"max-thumbnail-size" json:"max-thumbnail-size"`
BaseURL string `mapstructure:"base-url" json:"base-url"`
BindAddress string `mapstructure:"bind-address" json:"bind-address"`
MaxContentLength uint64 `mapstructure:"max-content-length" json:"max-content-length"`
EnableAnimatedThumbnails bool `mapstructure:"enable-animated-thumbnails" json:"enable-animated-thumbnails"`
MaxThumbnailSize uint `mapstructure:"max-thumbnail-size" json:"max-thumbnail-size"`

LogLevel string `mapstructure:"log-level" json:"log-level"`
LogDevelopment bool `mapstructure:"log-development" json:"log-development"`
Expand Down
46 changes: 45 additions & 1 deletion pkg/thumbnail/thumbnail.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package thumbnail

import (
"context"
"fmt"
"net/http"

"github.com/Chatterino/api/internal/logger"
"github.com/Chatterino/api/pkg/config"
"github.com/Chatterino/api/pkg/utils"
vips "github.com/davidbyttow/govips/v2/vips"
"github.com/davidbyttow/govips/v2/vips"
)

var (
Expand Down Expand Up @@ -84,3 +86,45 @@ func BuildStaticThumbnail(inputBuf []byte, resp *http.Response) ([]byte, error)

return outputBuf, nil
}

func BuildAnimatedThumbnail(ctx context.Context, inputBuf []byte, resp *http.Response) ([]byte, error) {
log := logger.FromContext(ctx)

image, err := vips.NewImageFromBuffer(inputBuf)

if err != nil {
log.Errorw("could not load image from url", "url", resp.Request.URL, "err", err)
return []byte{}, fmt.Errorf("could not load image from url: %s", resp.Request.URL)
}

maxThumbnailSize := int(cfg.MaxThumbnailSize)
format := image.Format()

if image.Width() <= maxThumbnailSize && image.Height() <= maxThumbnailSize {
return inputBuf, nil
pajlada marked this conversation as resolved.
Show resolved Hide resolved
}

importParams := vips.NewImportParams()

// n=-1 is used for animated images to make sure to get all frames and not just the first one.
if format == vips.ImageTypeGIF || format == vips.ImageTypeWEBP {
importParams.NumPages.Set(-1)
}

image, err = vips.LoadThumbnailFromBuffer(inputBuf, maxThumbnailSize, maxThumbnailSize, vips.InterestingAll, vips.SizeDown, importParams)

if err != nil {
log.Errorw("could not transform image from url", "url", resp.Request.URL, "err", err)
return []byte{}, fmt.Errorf("could not transform image from url: %s", resp.Request.URL)
}

exportParams := vips.NewWebpExportParams()
outputBuf, _, err := image.ExportWebp(exportParams)

if err != nil {
log.Errorw("could not export image from url", "url", resp.Request.URL, "err", err)
return []byte{}, fmt.Errorf("could not export image from url: %s", resp.Request.URL)
}

return outputBuf, nil
}
96 changes: 0 additions & 96 deletions pkg/thumbnail/thumbnail_unix.go

This file was deleted.

14 changes: 0 additions & 14 deletions pkg/thumbnail/thumbnail_windows.go

This file was deleted.