ToshaMusic: Hi-Res music downloads with quality verification
in-house Telegram bot: FLAC 24-bit / 192 kHz from Qobuz, Deezer and Tidal
A Telegram bot that downloads Hi-Res music from a Qobuz, Deezer or Tidal link, up to FLAC 24-bit / 192 kHz, and verifies that the FLAC is genuine: ffprobe, mutagen and spectral analysis instead of the streaming API's promises.
The task
Streaming services promise Hi-Res but do not always deliver it. A release is labelled "24-bit / 192 kHz" while inside it is an ordinary CD master stretched to those numbers. Catalogues also contain "pseudo-lossless": FLAC assembled from MP3, with a truncated spectrum. Ordinary downloaders trust the tags and the API response and put into your library something that is not Hi-Res by ear or by spectrum.
What was needed was a downloader that solves three problems. Get the maximum: automatically pick the highest format the source offers. Refuse to be fooled: measure bit depth, sample rate and spectral cut-off, compare them with the claim and report any mismatch honestly in the chat. Handle the load: a queue with limited concurrency so the streaming account does not get banned, and delivery of files up to 2 GB.
The solution
ToshaMusic is an in-house asynchronous Telegram bot, version 1.1.2. Implemented:
- Link intake. Qobuz, Deezer and Tidal: tracks, albums, playlists and artists; short links are expanded through their redirect.
- Release card. Cover art, artist, title, album, track count, duration, date, label, genre, explicit flag, claimed quality and the list of available formats. A "Maximum" button plus buttons for specific levels: FLAC 24/192, 24/96, 16/44.1, MP3 320.
- Graceful degradation. If the source API does not respond, the card is still shown and the quality is determined from the file itself.
- Verification. ffprobe, mutagen and spectral analysis; the file name, tags and verification line come only from measurements.
- Queue. A worker pool with a limit on parallel downloads, a global queue limit and a per-user limit; cancellation while queued or running; clear messages for geo-blocking, expired tokens, rate limits, missing releases and timeouts.
- Delivery. Local Bot API, files up to 2000 MB, cover thumbnail, uncompressed ZIP for long releases, retries on flood control.
- Admin panel. Statistics including the number of fakes caught and the distribution by real quality, users with bans and history, broadcasts, streaming tokens replaceable from the chat without a restart, settings,
/versionand/sysinfo. - Headless mode. The same engine as a separate service with an internal HTTP API for embedding into another bot.
How it works
ffprobe and mutagen: verifying bit depth
After download, ffprobe (a utility from FFmpeg) reads the codec, sample rate, bit depth, bitrate, channel count and duration. For FLAC, ffprobe often reports the container's 32 bits instead of the real 24, so the bit depth is refined by mutagen, an audio tag library. If 24/192 was requested but 16/44.1 arrived, the chat gets a warning that the release is available at most in CD quality.
Lossless cut-off spectrum: how a fake is caught
A fragment from the middle of the track is decoded to PCM (uncompressed audio samples), and an averaged FFT (fast Fourier transform, which breaks a signal down by frequency) finds the frequency above which the spectrum is empty. A drop in the 14 to 20.6 kHz range flags the file as re-encoded from a lossy source. Nothing above 24 kHz on a release claiming 96 or 192 kHz reveals a stretched CD master. A cut-off at 19 to 20.6 kHz also occurs in honest, dark masterings, so that warning is worded softly, and an unambiguous verdict is given only for a drop below 19.5 kHz. The analysis can be switched off in settings.
Name and tags from measurements only
The file name is built from actual parameters: Artist - Title [24bit-192kHz].flac. A verification line with bit depth, sample rate, bitrate, cut-off frequency and the ToshaMusic version is written into the tags, along with a QUALITY_VERIFIED field. No file in the library ends up with numbers in its name that contradict its contents.
Queue with limited concurrency
Downloads are performed by streamrip, launched as a child process with a config the bot generates itself. A worker pool on top of asyncio.Queue enforces a limit on simultaneous downloads (2 by default), a global queue limit and a per-user task limit: this protects the streaming account from a ban for downloading too aggressively. The status in the chat updates by stage: download, verify, tag, send. Each task has an isolated working directory, abandoned directories are cleaned at startup, and tasks left hanging after a crash are marked as interrupted.
Local Bot API: files up to 2 GB
The cloud Bot API caps file uploads at 50 MB. A local telegram-bot-api runs next to the bot in Docker in local mode: the file is passed as a reference to a path on disk without copying, with a 2000 MB limit. The data directory is mounted at the same path in both containers; otherwise the server would not see the file.
Headless mode for embedding
Since version 1.1.0 the project has two entry points. The regular one starts the aiogram bot. The second creates no bot at all: the same database, queue and engine sit behind an internal HTTP API with routes for the card, jobs, cancellation and acknowledgement. Finished files are handed over through a shared volume, and business errors are returned in a typed form so the consumer does not have to parse text. An engine crash cannot affect the consuming bot: they run in separate containers. This is how the Hi-Res music section works inside Downloader Bot.
Results
- The best available quality: up to FLAC 24-bit / 192 kHz.
- Fake Hi-Res is exposed by spectrum, any mismatch with the claimed quality is visible in the chat, and file names and tags match the contents.
- Files up to 2 GB go straight to Telegram with no size-limit errors.
- Source failures do not break the flow: the card is still shown and errors are explained in plain language.
- Streaming tokens are changed from the admin panel without restarting the container.
- The engine embeds into another bot over HTTP.
Technologies and why
- Python 3.13 and aiogram 3: an asynchronous bot, FSM for admin scenarios, inline keyboards only.
- pydantic-settings: type-checked configuration.
- SQLAlchemy 2.0 async and Alembic: models for users, tasks, tracks, settings and broadcasts; migrations checked against the models.
- streamrip: the download engine for Qobuz, Deezer and Tidal, run as a child process.
- aiohttp: metadata clients (Qobuz JSON API, Deezer public API, Tidal API v1), the headless-mode HTTP server, proxy support.
- FFmpeg, ffprobe, mutagen, numpy: measuring parameters, decoding a fragment, FFT for the cut-off search.
- loguru: rotated logs with a separate error file.
- Local Bot API: delivery of files up to 2000 MB.
- Docker Compose: the bot and telegram-bot-api with a shared data directory, Moscow time zone.
Status
In-house product, in production. The current version is 1.1.2 from 8 September 2026: dependency pins were cleaned up, and streamrip is installed separately because of incompatible aiofiles ranges. Version 1.1.0 (3 September 2026) added the headless mode; 1.0.0 (19 August 2026) was the first working release.
Limitations: the bot works from the owner's active subscription and does not bypass service protection; Tidal tokens are obtained through an external OAuth flow and are not refreshed automatically; admin scenario state lives in memory and resets on restart. Planned: automatic Tidal token refresh, FSM storage in Redis, CSV export of statistics, catalogue search inside the bot, ALAC/AAC conversion, saving a spectrogram as proof, pytest coverage.
Questions about this project
How do you check that a FLAC is real Hi-Res and not an MP3?
What is Hi-Res and why not take the streaming service's word for it?
Which services are supported?
How does the bot deliver files over 50 MB?
What happens if the requested quality is not available?
Can the downloader be embedded into another bot?
More in this area
Finance Assistant: PDF bank statements to a Telegram budget
our own product: a bot and web dashboard, four banks' statements, Gemini
Telegram ticketing system for an IT department
for a museum complex in Moscow: tickets, asset tracking, knowledge base and analytics
Tech Poly VPN: VPN subscription billing in Telegram
our own product: SBP payments, key issuing in Marzban, a backup VKontakte bot
Need something similar?
Tell us about the task β we'll show how we solved it and estimate the scope.