Skip to content

Add GIF support#141

Open
clins1994 wants to merge 9 commits into
beeper:mainfrom
clins1994:feat/gif-support
Open

Add GIF support#141
clins1994 wants to merge 9 commits into
beeper:mainfrom
clins1994:feat/gif-support

Conversation

@clins1994
Copy link
Copy Markdown
Contributor

@clins1994 clins1994 commented May 16, 2026

Fixes #90

Summary

  • advertise GIF support to Matrix/Beeper capabilities
  • send outbound Matrix/Beeper GIFs to LINE as image messages with GIF media metadata
  • receive LINE animated images as Matrix fi.mau.gif video messages and fetch original OBS media when needed
  • keep plain media uploads compatible with LINE OBS metadata without separately uploading thumbnails

Validation

  • CGO_ENABLED=0 go test ./pkg ./pkg/connector ./pkg/connector/handlers ./pkg/e2ee ./pkg/line ./pkg/line/password ./pkg/line/secret
  • docker compose build
  • docker compose up --build -d and live bridge startup/log smoke check

See comments below for a QA list

Screenshots

Screenshot 2026-05-16 at 13 32 43 Screenshot 2026-05-16 at 13 33 23 Kapture 2026-05-16 at 13 38 51

Notes

Full local go test $(go list ./... | grep -v /ltsm) and go vet require libolm headers on the host; Docker build validates with olm-dev installed in the builder image.

@clins1994 clins1994 changed the title Add GIF support Advertise GIF support May 16, 2026
@clins1994 clins1994 changed the title Advertise GIF support Add GIF support May 16, 2026
@clins1994
Copy link
Copy Markdown
Contributor Author

clins1994 commented May 16, 2026

QA matrix for GIF support

Current test status

Tested Case Status Notes
Group plain media path Passed GIF, JPG/PNG, video, text, and read receipts tested in a group that used the plain LINE media route. Logs showed Server indicates plain media flow for this chat, Sending plain text message (no E2EE), and Uploaded plain media after sending.
1:1 LSON/E2EE path Passed GIF, JPG/PNG, video tested both directions. Logs showed encrypted OBS media flow, preview uploads, and successful E2EE video decrypt.
All-E2EE-capable group functional pass Passed with caveat GIF/image/video worked functionally in the group. Logs showed group key activity, but Beeper-originated media in that group still logged Sending plain text message (no E2EE), so full LINE E2EE group media coverage is not confirmed.
PNG regression Passed PNGs tested successfully.
Basic text/read receipts Passed Basic text and read receipts tested successfully.
Large/weird aspect ratios Skipped Explicitly skipped for this QA pass.
Captions Skipped Explicitly skipped for this QA pass.

Core axes

  • Direction: Beeper -> LINE, LINE -> Beeper
  • Media: GIF, image, video
  • Encryption: LSOFF/plain, LSON/E2EE
  • Chat type: DM, group
  • Source format for Beeper GIF: pasted GIF/image, Beeper fi.mau.gif video, uploaded file if possible

GIF QA

Tested Case Chat Account/Peer Action Expected
G1 DM LSOFF/plain Send GIF from Beeper to LINE Appears in LINE, opens/animates, no “photo unavailable”
G2 Group LSOFF/plain fallback Send GIF from Beeper to LINE group Appears/animates for LINE members
G3 DM LSON/E2EE peer Send GIF from Beeper to LINE Appears/animates in LINE
G4 Group LSON/E2EE group Send GIF from Beeper to LINE group Appears/animates, no decrypt/media errors. Functional pass; logs did not confirm bridge-originated media used LINE E2EE in group.
G5 DM Any Send GIF from LINE to Beeper Appears in Beeper as animated GIF/video, not static JPG
G6 Group Any Send GIF from LINE to Beeper group Appears animated in Beeper
G7 DM Any Send Beeper GIF represented as fi.mau.gif video Converts/sends to LINE successfully
G8 DM Any Send actual image/gif from Beeper Sends to LINE successfully

Image regression

Tested Case Chat Account/Peer Action Expected
I1 DM LSOFF/plain Send JPG/PNG from Beeper to LINE Appears and opens in LINE
I2 Group LSOFF/plain fallback Send JPG/PNG from Beeper to LINE group Appears and opens
I3 DM LSON/E2EE peer Send JPG/PNG from Beeper to LINE Appears and opens
I4 Group LSON/E2EE group Send JPG/PNG from Beeper to LINE group Appears and opens. Functional pass; logs did not confirm bridge-originated media used LINE E2EE in group.
I5 DM Any Send image from LINE to Beeper Appears in Beeper as image
I6 Group Any Send image from LINE to Beeper group Appears in Beeper as image

Video regression

Tested Case Chat Account/Peer Action Expected
V1 DM LSOFF/plain Send MP4/WebM from Beeper to LINE Appears and plays in LINE
V2 Group LSOFF/plain fallback Send video from Beeper to LINE group Appears and plays
V3 DM LSON/E2EE peer Send video from Beeper to LINE Appears and plays
V4 Group LSON/E2EE group Send video from Beeper to LINE group Appears and plays. Functional pass; logs did not confirm bridge-originated media used LINE E2EE in group.
V5 DM Any Send video from LINE to Beeper Appears and plays in Beeper
V6 Group Any Send video from LINE to Beeper group Appears and plays

Logs to check after each send

docker compose logs --tail=300 matrix-line

Bad signs to look for:

Failed to upload plain media
Failed to upload plain media thumbnail
OBS upload failed
failed to upload GIF
failed to convert video to GIF
failed to download animated image
failed to decrypt
failed to encrypt
send status FAILED

Good signs to look for:

Uploaded plain media after sending
Converted video to GIF for LINE
Successfully sent media/message
status SUCCESS

Minimum smoke set before merge

Tested Priority Case
P0 GIF Beeper -> LINE, LSOFF/plain DM
P0 GIF Beeper -> LINE, LSON/E2EE DM
P0 GIF LINE -> Beeper DM
P1 JPG/PNG Beeper -> LINE, LSOFF/plain DM
P1 JPG/PNG LINE -> Beeper DM
P1 MP4 Beeper -> LINE, LSOFF/plain DM
P1 MP4 LINE -> Beeper DM
P2 Repeat GIF/image/video in group chat

Current risk note: the most important regression checks are plain image and plain video Beeper -> LINE, because this PR changes shared plain OBS upload behavior. Those paths were covered in group chat, but not in a plain 1:1 DM.

@clins1994 clins1994 marked this pull request as ready for review May 16, 2026 10:28
@clins1994

This comment was marked as outdated.

@clins1994
Copy link
Copy Markdown
Contributor Author

clins1994 commented May 20, 2026

QA findings and fixes

While testing the GIF/media support changes, we uncovered and fixed a few issues:

Area Finding Fix
GIF rendering in Beeper GIFs received from LINE could animate but render cropped/cramped inline until opened. Preserve Matrix image metadata for animated GIFs: mimetype, size, fi.mau.gif, fi.mau.is_animated, width, and height.
GIFs pasted/sent from LINE GIFs pasted into LINE still cropped because LINE put dimensions in MEDIA_CONTENT_INFO, while the bridge only read MEDIA_THUMB_INFO. Read width/height from MEDIA_CONTENT_INFO as well as MEDIA_THUMB_INFO.
Multi-account OBS upload Yuzu sending media failed with an OBS 401 because the encrypted OBS token cache was global and could reuse Caio's token. Key the OBS encrypted-access-token cache by LINE access token, so each account uses its own OBS token.
Static image rendering Static images could show cropped inline in Beeper even though opening them showed the full image. Always include Matrix image info metadata with mimetype, size, width, and height, not only for GIFs.
Video rendering Videos delivered and played, but Beeper inline previews could crop on receiver views. Copy LINE MEDIA_THUMB_INFO dimensions into Matrix video info.w / info.h.

Validation performed:

  • Group plain LINE media route: GIF, JPG/PNG, video, text, and read receipts passed.
  • 1:1 LSON/E2EE route: GIF, JPG/PNG, and video passed both directions.
  • PNG regression passed.
  • All-E2EE-capable group passed functionally, but logs still showed Beeper-originated group media using the plain LINE route, so that specific full-E2EE group media path is not confirmed.
  • Large/weird aspect ratio media and captions were intentionally skipped for this pass.

Relevant commits added during QA:

  • 6e0b6ad Fix bridged GIF rendering
  • 0294c7e Fix OBS token cache per account
  • d757caa Fix Matrix media dimensions

@highesttt
Copy link
Copy Markdown
Collaborator

you switched it from application/octet-stream to application/x-www-form-urlencoded. The other two OBS upload paths in client.go still use octet-stream, and there's a comment on one saying "OBS expects application/octet-stream for binary uploads." Was this intentional / required for GIFs to upload? If it's needed only for GIFs, can we keep octet-stream for the non-GIF callers?

You also removed thumbnails? Did you confirm thumbnails still render on mobile LINE for plain-account image and video sends?

@clins1994
Copy link
Copy Markdown
Contributor Author

Found a small bug while testing: GIFs sent via Beeper aren't autoplaying on LINE's end despite the settings being on for auto playing GIFs. This said ... User can still play the GIF on LINE by clicking it and the GIF is recognized as "GIF" on the UI

Here are the settings

image

It may be present on the main branch but not confirmed

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

feat: ✨ send GIFs from beeper

2 participants