Skip to content

Fix: Sticker Image Decoding and GIF Support#10

Open
moothz wants to merge 1 commit intoEvolutionAPI:mainfrom
moothz:fix/sticker-image-decoding
Open

Fix: Sticker Image Decoding and GIF Support#10
moothz wants to merge 1 commit intoEvolutionAPI:mainfrom
moothz:fix/sticker-image-decoding

Conversation

@moothz
Copy link
Copy Markdown

@moothz moothz commented Apr 4, 2026

Fixes the "failed to decode image: image: unknown format" error by explicitly registering image/jpeg and image/gif decoders in the Go environment. Additionally, it updates the convertToWebP logic to support GIF images by routing them through the FFmpeg conversion pipeline, enabling both static and animated GIFs to be sent as stickers.

These changes have been in effect in my codebase for 3 days now, no other conversion errors popped up while testing.

Related Issue

Closes #5

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement

Testing

  • Manual testing completed
  • Functionality verified in development environment
  • No breaking changes introduced

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have tested my changes thoroughly
  • Any dependent changes have been merged and published

Summary by Sourcery

Handle additional image formats for sticker conversion and support GIF/video-based stickers via FFmpeg.

Bug Fixes:

  • Register JPEG and GIF decoders to prevent image decoding failures when generating stickers.
  • Improve sticker conversion to correctly process JPEG, PNG, GIF, and MP4 inputs into WebP, returning an error for unsupported formats.

Enhancements:

  • Add support for animated and GIF-based stickers by routing GIF and MP4 content through an FFmpeg-based WebP conversion pipeline.
  • Extend sticker payloads with an optional transparentColor field to enable background color keying during video-to-WebP conversion.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Apr 4, 2026

Reviewer's Guide

Adds GIF and JPEG decoding support and enhances sticker conversion to handle multiple media types (including animated GIFs) via FFmpeg, with optional chroma key transparency for video-based stickers.

Sequence diagram for updated sticker sending and media conversion

sequenceDiagram
    actor Client
    participant SendService
    participant convertToWebP
    participant convertVideoToWebP
    participant imageDecode
    participant webpEncode
    participant ffmpeg
    participant HTTPServer

    Client->>SendService: SendSticker(stickerData, instance)
    SendService->>SendService: validate StickerStruct
    alt Sticker is URL (http...)
        SendService->>convertToWebP: convertToWebP(imageDataURL, transparentColor)
        convertToWebP->>HTTPServer: HTTP GET imageDataURL
        HTTPServer-->>convertToWebP: media bytes
        convertToWebP->>convertToWebP: mimetype.Detect(data)
        alt image/webp
            convertToWebP-->>SendService: return original data
        else video/mp4 or image/gif
            convertToWebP->>convertVideoToWebP: convertVideoToWebP(data, transparentColor)
            convertVideoToWebP->>convertVideoToWebP: create temp mp4 file
            convertVideoToWebP->>ffmpeg: ffmpeg -i input -vcodec libwebp -filter:v filters ...
            ffmpeg-->>convertVideoToWebP: generated webp file
            convertVideoToWebP-->>convertToWebP: webp bytes
            convertToWebP-->>SendService: webp bytes
        else image/jpeg or image/png or image/jpg
            convertToWebP->>imageDecode: image.Decode(data)
            imageDecode-->>convertToWebP: decoded image.Image
            convertToWebP->>webpEncode: webp.Encode(image, options)
            webpEncode-->>convertToWebP: webp bytes
            convertToWebP-->>SendService: webp bytes
        else unsupported format
            convertToWebP-->>SendService: error unsupported format
        end
    else Sticker not URL
        SendService->>SendService: handle existing non URL logic
    end
    SendService-->>Client: MessageSendStruct or error
Loading

Class diagram for updated sticker structures and conversion functions

classDiagram
    class StickerStruct {
        string Number
        string Sticker
        string Id
        int32 Delay
        []string MentionedJID
        bool MentionAll
        *bool FormatJid
        string TransparentColor
        QuotedStruct Quoted
    }

    class QuotedStruct {
    }

    class SendService {
        SendSticker(data *StickerStruct, instance *Instance) MessageSendStruct
    }

    class Instance {
    }

    class MessageSendStruct {
    }

    class ConversionUtils {
        <<utility>>
        convertToWebP(imageDataURL string, transparentColor string) []byte, error
        convertVideoToWebP(inputData []byte, transparentColor string) []byte, error
    }

    SendService ..> StickerStruct : uses
    SendService ..> Instance : uses
    SendService ..> MessageSendStruct : returns
    SendService ..> ConversionUtils : calls
    StickerStruct --> QuotedStruct : contains
Loading

Flow diagram for media-type based WebP conversion with GIF and transparency support

flowchart TD
    A[Start convertToWebP] --> B[Fetch URL via HTTP GET]
    B --> C[Read response body into bytes]
    C --> D[Detect MIME type]

    D -->|image_webp| E[Return original data]
    D -->|video_mp4 or image_gif| F[Call convertVideoToWebP]
    D -->|image_jpeg or image_png or image_jpg| G[Decode image with image.Decode]
    D -->|other| Z[Return error unsupported format]

    F --> H[Create temp mp4 input file]
    H --> I[Build ffmpeg filters
fps=15, scale, pad]
    I --> J{TransparentColor set?}
    J -->|yes| K[Add colorkey filter with TransparentColor]
    J -->|no| L[Use base filters]
    K --> M[Run ffmpeg to generate webp]
    L --> M[Run ffmpeg to generate webp]
    M --> N[Read webp file bytes]
    N --> O[Return webp data]

    G --> P[Encode to webp with webp.Encode]
    P --> Q[Return webp data]
Loading

File-Level Changes

Change Details Files
Register additional image decoders to avoid unknown format errors when decoding stickers.
  • Import image/gif and image/jpeg packages for side-effect registration of decoders
  • Ensure Go image.Decode can handle GIF and JPEG inputs used in sticker conversion
pkg/sendMessage/service/send_service.go
Extend StickerStruct to allow specifying a transparent color for video-based stickers.
  • Add TransparentColor string field with json tag transparentColor,omitempty to StickerStruct
  • Propagate the new field usage into sticker conversion calls
pkg/sendMessage/service/send_service.go
Refactor WebP conversion to support multiple input formats, including animated GIFs and MP4, by routing video-like formats through an FFmpeg pipeline.
  • Introduce convertVideoToWebP helper that writes input bytes to a temp MP4 file, runs ffmpeg with WebP output and configurable filters, and reads back the generated WebP
  • Use mimetype detection on downloaded media to branch behavior: return WebP as-is, send video/gif through convertVideoToWebP, and decode/encode still images (JPEG/PNG/JPG) via Go image and webp libraries
  • Enhance FFmpeg filters to support scaling, padding, frame rate control, looping, and optional colorkey-based transparency derived from TransparentColor
  • Update convertToWebP signature to accept URL and transparentColor and adjust SendSticker to pass the new parameter
pkg/sendMessage/service/send_service.go

Assessment against linked issues

Issue Objective Addressed Explanation
#5 Ensure that incoming sticker (webp) media can be stored in S3/MinIO without requiring successful image decoding, so that upload is not aborted and mediaUrl is correctly returned in the webhook. The PR only modifies the sticker sending logic in send_service.go (adding JPEG/GIF decoders and enhancing convertToWebP for outgoing stickers). The issue concerns failures when receiving stickers and uploading them to S3/MinIO due to webp decode errors. No code related to the S3/MinIO upload pipeline or bypassing image.Decode for incoming media was changed.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • The new convertToWebP helper uses http.Get without checking resp.StatusCode or applying any timeout/context, which can hide upstream errors or hang indefinitely on slow/bad endpoints; consider using an http.Client with timeouts and validating non-2xx responses before reading the body.
  • Both convertToWebP and convertVideoToWebP read arbitrary remote data into memory and pass it to ffmpeg without any size or duration limits; consider enforcing maximum content length and using exec.CommandContext with a timeout to avoid resource exhaustion or long-running ffmpeg processes.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `convertToWebP` helper uses `http.Get` without checking `resp.StatusCode` or applying any timeout/context, which can hide upstream errors or hang indefinitely on slow/bad endpoints; consider using an `http.Client` with timeouts and validating non-2xx responses before reading the body.
- Both `convertToWebP` and `convertVideoToWebP` read arbitrary remote data into memory and pass it to `ffmpeg` without any size or duration limits; consider enforcing maximum content length and using `exec.CommandContext` with a timeout to avoid resource exhaustion or long-running `ffmpeg` processes.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Falha no upload de stickers para S3/MinIO devido a erro de decodificação webp (webp: invalid format)

1 participant