Skip to content

feat: add video and gif wallpaper support#1512

Open
sumerchoudhary78 wants to merge 2 commits into
caelestia-dots:mainfrom
sumerchoudhary78:feat/video-wallpaper
Open

feat: add video and gif wallpaper support#1512
sumerchoudhary78 wants to merge 2 commits into
caelestia-dots:mainfrom
sumerchoudhary78:feat/video-wallpaper

Conversation

@sumerchoudhary78

Copy link
Copy Markdown

Adds support for videos and animated GIFs as wallpapers, alongside the existing static images. They appear in the wallpaper picker and launcher, cross-fade in the same way images do, and drive the Material colour scheme.

Usage

Drop a video (.mp4, .webm, .mkv, .mov, .avi, .m4v) or a .gif into your wallpapers directory, or pick one from the wallpaper picker / launcher (>wallpaper). Nothing to configure.

Two optional runtime dependencies, only needed for video (gifs need neither):

  • qt6-multimedia — plays the video. If missing, the wallpaper falls back to a static extracted frame instead of failing.
  • ffmpeg — extracts a frame from the video for the colour scheme and picker thumbnails.

How it works

  • modules/background/Wallpaper.qml used to hold two CachingImage slots that cross-fade. They're now generic slots that load the right renderer per file type: WallpaperVideo (VideoOutput + MediaPlayer), WallpaperAnimated (AnimatedImage for gifs), or WallpaperImage (the existing CachingImage, unchanged). The fade/scale transition is identical.
  • The caelestia CLI generates the colour scheme but can't read videos, so for a video a representative frame is extracted with ffmpeg (1s in, to skip fade-from-black intros, falling back to the first frame), cached under ~/.cache/caelestia/wallpapers/frames/, and the CLI / colour analysis runs on that frame. Picker and launcher thumbnails reuse it; the launcher shows a movie icon for videos.
  • FileSystemModel's Images filter dropped any file QImageReader couldn't read, which excluded videos. It now treats an explicit nameFilters match as authoritative, so the wallpaper scan can include video files (separate commit).

Performance / GPU

A playing video decodes continuously, so to keep idle cost down:

  • Only one video/gif decodes at a time — the hidden cross-fade slot is unloaded once it finishes fading out.
  • Playback pauses automatically when nothing can see it: a fullscreen window on that monitor, the monitor's DPMS off (screen asleep), game mode on, or the session locked. It resumes when the wallpaper is visible again.
  • Static image wallpapers are unaffected — same code path as before.
  • gifs decode on CPU via AnimatedImage and pause under the same conditions.

Breaking changes / side effects

  • None for existing image users; static wallpapers behave exactly as before.
  • The new deps are optional; without qt6-multimedia, videos degrade to a static frame.
  • Adds a small frame cache under ~/.cache/caelestia/wallpapers/frames/.

Testing

Built the plugin and ran the shell on Hyprland. Verified:

  • mp4 and webm videos set as wallpaper (via both the picker and the launcher) play and loop.
  • Animated gifs play.
  • The Material colour scheme is generated correctly from the auto-extracted video frame.
  • Playback pauses on fullscreen, lock, DPMS-off and game mode, and falls back to a static frame when QtMultimedia isn't available.

qmlformat, qml-lint-conventions.py, clang-format and qmllint all pass.

Sumer Jakhar added 2 commits June 4, 2026 13:33
The Images filter skipped any file QImageReader couldn't read, which dropped non-image files even when they were explicitly requested via nameFilters. Treat an explicit nameFilters match as authoritative so callers can let extra file types (e.g. videos) through the Images filter.
Allow videos (mp4/webm/mkv/mov/avi/m4v) and animated gifs to be used as wallpapers alongside static images, with cross-fade, per-frame colour scheme extraction, and automatic pausing when not visible.
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.

1 participant