Skip to content

Latest commit

Β 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Anisync β€” a cross-platform desktop app for discovering, streaming and downloading anime

Anisync

A cross-platform desktop app for discovering, streaming and downloading anime β€” with an embedded mpv player and a plugin system for sources.

Latest release Build Python 3.11+ Qt / PySide6 Platforms License: MIT Last commit

English Β· Русский

⬇ Download Β Β·Β  Features Β Β·Β  Quick start Β Β·Β  Architecture Β Β·Β  Documentation


Anisync is a desktop anime browser and player for Windows, macOS and Linux. Search a source site, open a title, pick a dub and play episodes in the built-in libmpv player β€” or queue them for offline viewing β€” while a local library keeps your lists, history and resume positions. It has an Apple TV / Crunchyroll-inspired dark UI, and every source site is a small plugin: today that is the YummyAnime provider with the Kodik player resolver.

✨ Features

🎬 In-app playback Embedded libmpv rendered into a Qt OpenGL surface: HLS/DASH, hardware decoding, custom headers, every codec. No external player needed. Honours autoplay next episode and your preferred dub.
🏠 Home Hero banner plus Continue Watching (from your local history) and Trending Now carousels; providers are queried in parallel and rows are cached for 10 minutes.
πŸ” Live search Debounced as-you-type results across providers, provider filter chips, Ctrl+F / Cmd+F from anywhere.
🎞 Details & dubs Episode tiles grouped by dub track, with play and save actions per episode.
πŸ“₯ Download manager Persistent queue (survives restarts), per-episode and per-anime progress, speed display, cancel/retry, configurable concurrency and quality. Powered by yt-dlp.
πŸ“š Library Favorites, Watching / Planning / Completed / Dropped lists and full watch history with resume positions, stored locally in SQLite.
πŸ”„ Auto-updates Checks GitHub Releases on startup, shows the changelog of every version you missed, downloads with live progress and installs in place. Full release history in Settings β†’ About β†’ What's new.
🧩 Modular by design Any anime site is a provider plugin, any embed player is a resolver plugin. Adding a source touches zero core code.
πŸ–₯ Truly cross-platform One codebase, native-feeling on Windows, macOS and Linux (X11/Wayland). Icons are drawn with QPainter, so the UI never depends on platform fonts.
πŸŒ™ Cinematic dark UI Frameless window, poster-first cards, smooth page transitions and hover animations, a single orange accent.

πŸš€ Quick start

Install

Grab the latest build from Releases β€” fully self-contained (libmpv included), nothing else to install.

Platform File Notes
Windows Anisync-X.Y.Z-win.zip Unzip anywhere, run Anisync.exe. SmartScreen: More info β†’ Run anyway (unsigned build).
macOS Anisync-X.Y.Z-mac.dmg Drag to Applications. First launch: right-click β†’ Open (ad-hoc signed).
Linux Anisync-X.Y.Z.AppImage chmod +x Anisync-*.AppImage && ./Anisync-*.AppImage

Once installed, Anisync keeps itself up to date β€” when a new version is published you'll get a prompt with the full changelog and a one-click Install update.

Run from source

# Python 3.11+
git clone https://github.com/DenisHumen/Anisync.git
cd Anisync
python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -e ".[dev]"

python -m anisync                  # launch the GUI (or just: anisync)
pytest -q                          # run the test suite (offline)

For in-app playback a native libmpv is required in dev runs (packaged builds bundle it):

OS How
macOS brew install mpv
Debian/Ubuntu sudo apt install libmpv2 (or libmpv1)
Windows put libmpv-2.dll (mpv-dev builds) on PATH

python -m anisync --selfcheck boots the plugin registries without opening the GUI and reports the version, config, loaded providers/players and whether libmpv was found.

βš™οΈ Configuration

Most options are in Settings; they are stored in config.toml inside the app data folder.

Key Default Description
downloads_dir <Videos>/Anisync Where downloaded episodes are saved
max_concurrent_downloads 2 Parallel downloads
preferred_quality best best, 2160p, 1440p, 1080p, 720p, 480p or 360p
preferred_dub (empty) Dub to start with (case-insensitive substring match); empty = first available
autoplay_next true Play the next episode automatically
check_updates_on_start true Check GitHub Releases on launch
theme dark UI theme
update_repo DenisHumen/Anisync Repository the updater checks
auth_backend_url (empty) Account backend URL β€” empty keeps the app in offline mode (see docs/AUTH.md)

App data folder (resolved with platformdirs) β€” holds config.toml, the SQLite library.db, cache/ and account.json:

OS Location
Windows %LOCALAPPDATA%\Anisync
macOS ~/Library/Application Support/Anisync
Linux ~/.local/share/Anisync
Environment variable Effect
ANISYNC_DATA_DIR Use this folder as the app data folder instead
ANISYNC_TEST_MODE Use a throwaway temp folder (used by the test suite)

🧭 Usage

The top navigation has Home, Search, Library, History, Downloads, Account and Settings. Opening a title shows its details page with episodes grouped by dub; from there you can play an episode, add the title to a list, or save episodes to the download queue. The Account page is a scaffold for future cloud accounts β€” this build runs in offline mode and keeps everything local.

⌨️ Keyboard shortcuts

Key Action
Space Play / pause
← / β†’ Seek βˆ’10 s / +10 s
Shift+← / Shift+β†’ Seek βˆ’60 s / +60 s
↑ / ↓ Volume
M Mute
F Toggle fullscreen
Esc Exit fullscreen
Ctrl+F / Cmd+F Jump to search

🧱 Architecture

Stack: Python 3.11+ Β· PySide6 (Qt 6) Β· python-mpv / libmpv Β· httpx Β· selectolax Β· yt-dlp Β· platformdirs Β· SQLite Β· PyInstaller (packaging).

Three rules hold everything together:

  1. Plain dataclasses cross layers (core/models.py) β€” no Qt or httpx objects leak between UI, providers and the downloader.
  2. Plugins self-register β€” dropping a file into providers/ or players/ is the whole integration (@register_provider / @register_player).
  3. The UI never blocks β€” all I/O runs on a persistent asyncio loop in a worker thread (utils/async_runner.run_async), results come back through Qt signals.

Adding a provider

# anisync/providers/mysource.py
from anisync.core.registry import register_provider
from anisync.providers.base import BaseProvider

@register_provider
class MySourceProvider(BaseProvider):
    id = "mysource"
    display_name = "MySource"
    base_url = "https://example.com"

    async def search(self, query, *, limit=20): ...
    async def get_anime(self, anime_url): ...
    async def list_episodes(self, anime): ...

That's it β€” search, details, playback and downloads pick it up automatically. See docs/PROVIDERS.md and docs/PLAYERS.md for the full contracts, and docs/CONTRIBUTING.md for the 5-step checklist (import, fixtures, tests).

πŸ”„ How updates work

  1. On startup (and on demand from Settings β†’ About) Anisync queries the GitHub Releases API.
  2. If a newer version exists you get a dialog with the combined release notes of every version you missed β€” dates and notes come straight from the release descriptions on GitHub.
  3. Install update downloads the platform asset with live progress, then a tiny helper swaps the build and relaunches the app. Dev runs get an Open installer fallback instead.
  4. Releases are produced by CI on every v* tag β€” per-version notes live in .github/releases/. See docs/UPDATER.md and docs/RELEASES.md.

πŸ“ Project structure

anisync/
β”œβ”€β”€ core/        # models, plugin registries, SQLite library, config,
β”‚                # download manager, auth scaffold, GitHub updater + self-update
β”œβ”€β”€ providers/   # site scrapers β€” one module per source (yummyanime, …)
β”œβ”€β”€ players/     # embed resolvers β€” one module per player (kodik, …)
β”œβ”€β”€ ui/          # PySide6 pages, widgets, dialogs, QPainter icons, theme
└── utils/       # async runner, http client factory, paths, mpv loader
tests/           # pytest suite β€” fully offline by default (fixtures in tests/fixtures/)
packaging/       # PyInstaller spec, app icons, logo generator
docs/            # design docs for humans & agents

πŸ“š Documentation

Document Purpose
docs/ARCHITECTURE.md High-level design, layers, data flow
docs/PROVIDERS.md How to add a new anime source
docs/PLAYERS.md How to add a new embed resolver
docs/DOWNLOADER.md Download manager design
docs/UI.md UI structure, theming, cross-platform rules
docs/AUTH.md Account system (offline mode today)
docs/UPDATER.md Auto-update system
docs/RELEASES.md Release engineering / CI pipeline
docs/ROADMAP.md Phased plan and progress
docs/CONTRIBUTING.md Developer / agent workflow

πŸ›  Development

pip install -e ".[dev]"
pytest -q                       # offline suite
pytest -m live                  # live network tests (optional)
python -m compileall anisync    # quick syntax gate

Ground rules (the longer list lives in docs/CONTRIBUTING.md):

  • style via theme tokens β€” no hardcoded colors in widgets;
  • icons are QPainter-drawn (ui/widgets/icons.py) β€” never unicode glyphs/emoji, they break on Linux fonts;
  • every page must stay responsive from 1024 px up;
  • all I/O through run_async β€” never block the Qt event loop.

Releasing: bump the version in anisync/__init__.py and pyproject.toml, write the notes to .github/releases/vX.Y.Z.md, then push a vX.Y.Z tag. CI builds the PyInstaller bundles (packaging/Anisync.spec) on macOS, Windows and Linux, smoke-tests each with --selfcheck, and attaches the DMG, zip and AppImage to the release. Details in docs/RELEASES.md.

πŸ—Ί Roadmap

Open items from docs/ROADMAP.md:

  • Subtitle picker
  • More providers (Anilibria, Animevost) and player resolvers (Aniboom, Sibnet)
  • Pre-download the next episode automatically
  • A real registration backend for accounts
  • Stretch: airing schedule view, Discord rich presence, plugin store / hot-reload providers

🀝 Contributing

Issues and pull requests are welcome. New sources belong in anisync/providers/ and new embed hosts in anisync/players/ β€” never in the UI. Tests must stay offline (fixtures + httpx.MockTransport), and docs are updated in the same change. See docs/CONTRIBUTING.md.

πŸ“„ License & disclaimer

MIT. Anisync is a personal/educational project: it ships no content and hosts nothing β€” it only embeds what source sites publicly serve. Respect the Terms of Service of the sources you use and support official releases where available.

About

🍿 Cross-platform desktop anime browser & player β€” live search, embedded mpv playback, download queue, local library & watch history, plugin-based sources. Python + PySide6 (Qt 6).

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages