A fast, minimalist image and video viewer for Linux.
Built with Rust and GTK4/libadwaita for native Wayland/X11 support.
- Opens images and videos from the command line, a file chooser, or drag and drop
- Browses the current directory's supported media in natural filename order
- Navigates with the keyboard, arrow keys, or trackpad gestures
- Shows a slide transition between items when the next frame is ready
- Decodes images on worker threads and prefetches neighboring images
- Fits media to the window with aspect-ratio preservation
- Zooms with the keyboard, Ctrl+ mouse wheel, pinch, or double-click
- Anchors double-click zoom at the pointer and lets you pan while zoomed
- Applies EXIF orientation when displaying images
- Rotates left/right and mirrors images horizontally
- Plays videos with play/pause, seek, volume, mute, elapsed time, and duration controls
- Starts videos muted, plays them automatically, and loops playback
- Moves the current item to Trash, with direct deletion when no Trash is available
- Offers persistent slide-animation and two-finger-swipe preferences
- Auto-hides the header and video controls for distraction-free viewing
- Shows in-app messages for load, save, Trash, and video errors
- Supports fullscreen mode
Supported media is recognized case-insensitively by extension. Actual image decoding is based on the file contents, while video playback depends on the codecs provided by the installed GStreamer plugins.
Carosello is not available through the AUR, so install it by building the
upstream source locally. A per-user Meson install is recommended because it
does not overwrite files managed by Pacman and does not require sudo for the
install step.
Install the build and runtime dependencies:
sudo pacman -S --needed \
base-devel git meson rust gtk4 libadwaita \
hicolor-icon-theme desktop-file-utilsFor broad video-codec support, also install GStreamer's common plugin sets:
sudo pacman -S --needed \
gstreamer gst-plugins-good gst-plugins-bad \
gst-plugins-ugly gst-libavClone, build, and install under ~/.local:
git clone https://github.com/grigio/carosello.git
cd carosello
meson setup builddir --prefix="$HOME/.local"
meson compile -C builddir
meson install -C builddirMake sure ~/.local/bin is in your PATH, then launch Carosello from the
application menu or run:
caroselloThe Meson install places the binary, desktop entry, AppStream metadata, and
icon under ~/.local. To rebuild after pulling new changes, run:
meson compile -C builddir
meson install -C builddirDownload the latest .flatpak file from
GitHub Releases and install it:
flatpak install --user ./carosello.flatpak
flatpak run io.github.grigio.caroselloThe release artifact produced by CI is currently for x86_64.
The manifest targets the GNOME 50 runtime and its freedesktop 25.08 Rust extension:
sudo pacman -S --needed flatpak flatpak-builder
flatpak install --user flathub \
org.gnome.Platform//50 org.gnome.Sdk//50 \
org.freedesktop.Sdk.Extension.rust-stable//25.08The manifest also expects the ignored cargo-sources.json file. Generate it
from Cargo.lock using the Generate Cargo sources for Flatpak command in
.github/workflows/ci.yml, then build and install:
flatpak-builder --user --install --force-clean \
build-dir io.github.grigio.carosello.ymlThe Flatpak has read/write host and GVfs access so it can browse remote folders, edit images in place, and use Trash where supported. A single file opened through the document portal contains only that file; use Open Folder… to export a directory and browse its siblings.
To compile without installing desktop integration:
cargo build --release
./target/release/carosello# View supported media in the current directory
carosello
# View supported media in a specific directory
carosello /path/to/directory
# View a specific local file and its supported siblings
carosello /path/to/image.jpgDirectory listings are shallow rather than recursive and include supported
media files only. Filenames are naturally sorted, so names such as IMG2.jpg
come before IMG10.jpg. Carosello uses one positional path; launching it
again while a window is open presents the existing window.
Use Open… (Ctrl+O) to choose a file or Open Folder… (Ctrl+Shift+O)
to choose a directory. With the Flatpak document portal, choosing a folder is
also the reliable way to browse siblings and obtain a writable export.
The header buttons rotate the current image left or right and mirror it horizontally. Each operation is saved in place over the original file, and the view refreshes after saving. JPEG EXIF orientation is normalized to prevent a reload from rotating the image a second time.
Image edits are destructive and there is currently no undo button. JPEG files are re-encoded at quality 95, so their bytes can change even when an operation is later reversed. Animated GIF and WebP files can be viewed but are rejected by the editing tools; video files cannot be transformed.
Open Preferences… from the application menu to configure:
- Slide animation — enabled by default. If a prefetched frame is not ready, Carosello switches immediately rather than delaying navigation.
- Two-finger swipe — disabled by default. When enabled, two-finger gestures navigate instead of the default three-finger gestures.
Both settings persist in settings.conf under the user's configuration
directory (~/.config/carosello by default).
After installation, Carosello's desktop entry registers it for JPEG, PNG,
WebP, GIF, BMP, TIFF, MP4, WebM, and Matroska MIME types. The canonical types
are mirrored in the AppStream <provides> block; the desktop entry also
registers legacy BMP and TIFF aliases.
To make it the default for all supported types:
xdg-mime default io.github.grigio.carosello.desktop \
image/jpeg image/png image/webp image/gif image/bmp \
image/x-bmp image/x-ms-bmp image/tiff image/x-tiff \
video/mp4 video/webm video/x-matroskaOr set one type through GIO:
gio mime image/jpeg io.github.grigio.carosello.desktopWhen Two-finger swipe is enabled in Preferences, two-finger gestures replace the default three-finger gestures.
- Fast — Decode images off the UI thread and prefetch nearby frames; an unavailable frame causes an immediate switch rather than blocking the UI
- Minimal — No built-in file browser, thumbnail grid, or metadata viewer; use the system file chooser when needed
- Keyboard-first — Navigate with the keyboard and zoom with Ctrl+ scroll, pinch, or keyboard shortcuts
- Language: Rust
- UI Toolkit: GTK4 + libadwaita
- Image Decoding: Rust imagecrate on worker threads
- Display Texture: GDK MemoryTexture
- Video Playback: GTK MediaFilebacked by GStreamer
- EXIF Parsing: kamadak-exif
GPL-3.0-or-later
If you find this project helpful, please consider making a donation to support its development.
- Monero: 88LyqYXn4LdCVDtPWKuton9hJwbo8ZduNEGuARHGdeSJ79BBYWGpMQR8VGWxGDKtTLLM6E9MJm8RvW9VMUgCcSXu19L9FSv
- Bitcoin: bc1q6mh77hfv8x8pa0clzskw6ndysujmr78j6se025