Skip to content

Releases: antlis/tg-streaming-bot

v1.11.0 — Nix flake

Choose a tag to compare

@antlis antlis released this 01 Oct 17:54
65f6ffc

Added

  • Nix flake. nix run github:antlis/tg-streaming-bot; .#with-browser adds the headless-Chromium fallback; .#full also enables VA-API transcoding; nix develop gives a dev shell. It builds kurigram, tgcrypto, py-tgcalls and the native ntgcalls from PyPI wheels (none are in nixpkgs), wraps yt-dlp/ffmpeg/git onto PATH, and runs the bot from a writable state dir (~/.local/state/tg-streaming-bot) because it keeps downloads/ and search/ relative to the working directory.
  • A home-manager module (services.tg-streaming-bot) runs it as a user service.
  • CI runs nix flake check: byte-compile, lint, and import every module against the Nix-built dependencies.

Run the Docker bot or the Nix one, not both — they share the bot token and the assistant session.

Full Changelog: v1.10.0...v1.11.0

v1.10.0 — extractor plugins + headless-browser fallback

Choose a tag to compare

@antlis antlis released this 30 Sep 20:09
415d1e4

Added

  • Extractor plugins (PLUGIN_DIR, ENABLE_PLUGINS): drop .py files exposing match() + resolve() into a directory and they resolve non-YouTube pages yt-dlp can't handle, before yt-dlp runs. Same contract as tg-media-bot / tg-mpv-bot; see examples/plugin_example.py. Docker mounts ./plugins at /plugins. The referer/headers a plugin returns are passed to ffmpeg via MediaStream(headers=…); a file:// media playlist gets ffmpeg's protocol whitelist widened.
  • Headless-Chromium fallback (ENABLE_BROWSER_FALLBACK, BROWSER_FALLBACK_TIMEOUT): when yt-dlp can't extract a non-YouTube page, the page is opened in headless Chromium (Playwright), the player's media request is captured and streamed. Opt-in in the Docker image via the INSTALL_BROWSER=true build arg (~450 MB); no-ops without it.
  • New dependencies: playwright, curl_cffi, pycryptodomex (the latter two are what extractor plugins typically need).

Fixed

  • /vplay <link> failed with "couldn't build the thumbnail: InvalidUrlClientError" for pages yt-dlp has no extractor for — the metadata lookup returns no thumbnail and thumb() raised on it before the resolvers ever ran. thumb() now falls back to the bundled background image whenever the thumbnail is empty or can't be fetched.

v1.6.0 — /record clip range and duration shorthands

Choose a tag to compare

@antlis antlis released this 24 Jun 12:13

Added

  • /record START END — clip a specific time range from what's playing. Accepts HH:MM:SS, MM:SS, Nh/Nm/Ns, or plain seconds for both arguments (e.g. /record 01:30:00 02:00:00 records 30 minutes starting at 1 h 30 m). Works for local files and downloaded YouTube tracks; for live HTTP streams (radio, IPTV) the start offset is ignored and only the duration (END − START) is used, with a note in the status message.
  • Duration shorthand for /record — e.g. /record 30m or /record 1h alongside the existing plain-seconds form.
  • Ahead-of-playback warning — when the requested start time is ahead of the current playback position (meaning yt-dlp may not have downloaded that far yet), the recording starts but the status message warns that the clip may be shorter than expected.

v1.5.0 — IPTV + non-YouTube playback

Choose a tag to compare

@antlis antlis released this 24 Jun 12:13
1511dc5

Added

  • IPTV (/iptv <name>) — search 50 000+ live TV channels from the iptv-org public catalogue and stream them live; channel logo shown when playing. /iptv with no args shows links to browse channels by country/category. Works in forum groups (posts to the correct topic).
  • Non-YouTube URL support in /play and /vplay — Rutube, Vimeo, and any other yt-dlp-supported site now work by extracting the stream URL and feeding it live to ffmpeg (no multi-GB download wait). YouTube continues to download first as before.

Fixed

  • ytsearch() no longer tries to do a YouTube keyword search when given a direct URL from a non-YouTube site (was returning "no results found").
  • callback.py was missing the can_manage_vc import (undefined name, F821).
  • Unused global admins declaration removed from admins.py (F824).

v1.4.1 — gapless Auto-DJ

Choose a tag to compare

@antlis antlis released this 09 Jun 17:18

Changed

  • Gapless Auto-DJ — the next related track is now prefetched in the background while the current one is still playing, so it starts seamlessly instead of after a short fetch pause at the end of each track.

See CHANGELOG.md.

v1.4.0 — Auto-DJ + SponsorBlock

Choose a tag to compare

@antlis antlis released this 09 Jun 17:03

Added

  • Auto-DJ (/autoplay) — when the queue runs out, keep playing related YouTube tracks (the song's Mix), endless-radio style. Off by default; stops on its own when the voice chat empties. Non-YouTube sources end normally.
  • SponsorBlock — set SPONSORBLOCK_REMOVE (e.g. sponsor,selfpromo,music_offtopic) to cut sponsor reads / non-music intros & outros from YouTube downloads.

Rollback point for this round was v1.3.0. See CHANGELOG.md.

v1.3.0 — screenshot, seek-%, synced recordings

Choose a tag to compare

@antlis antlis released this 09 Jun 16:32

Added

  • /screenshot + a 📸 panel button — grab the current video frame.
  • Seek-to-% buttons (0/25/50/75%) on the now-playing panel.
  • Record toggle — the ⏺ panel button starts/stops recording; recorder reachable from /info.

Fixed

  • Recording A/V sync (drop B-frames + resample audio).
  • Empty/0:00 video recordings (seek clamp, E-AC3→AAC, HEVC→H.264, faststart remux).
  • Volume/mute no longer restarts the video from the start.
  • Friendlier /radio error when no VC is open; logging cleanup.

See CHANGELOG.md. This is the rollback point before the next round of streaming-smoothness work.

v1.2.0 — GPU-accelerated recording

Choose a tag to compare

@antlis antlis released this 09 Jun 12:50

Added

  • GPU (VAAPI) encoding for recordings. With TRANSCODE_HWACCEL=vaapi, a recording that needs re-encoding (HEVC/other → H.264) is now encoded on the GPU (h264_vaapi) instead of the CPU, so recording no longer stutters the live stream. Falls back to CPU libx264 when no GPU is configured; H.264 sources are copied with no re-encode.

See CHANGELOG.md for the full history.

v1.1.0 — working volume/mute + recording

Choose a tag to compare

@antlis antlis released this 09 Jun 11:39

Stable checkpoint: master volume, mute (no video blur), record toggle, and
working audio and video recording.

Since v1.0.0

  • Master volume via ffmpeg gain (/volume, 🔉/🔊) — affects the whole room, with correct position tracking across re-feeds.
  • Mute = volume 0 (🔇 / /vmute) so muting a video no longer makes it blurry.
  • Record button is a toggle (⏺ Rec / Stop) on the control panel.
  • Video recording now works: clamps the seek into the file, re-encodes audio to AAC (for E-AC3 MKVs), and re-encodes HEVC/non-H.264 video to H.264 720p so Telegram renders it. Audio recordings unchanged.
  • Friendlier /radio error when no voice chat is open and the assistant can't start one.

Note: recording an HEVC title re-encodes on the CPU and can briefly stutter the live stream on modest hardware — GPU (VAAPI) offload is the next step.

v1.0.0 — first public release

Choose a tag to compare

@antlis antlis released this 09 Jun 11:09

First public release of tg-streaming-bot — a self-hosted Telegram bot that streams music & video into group voice chats.

Features

  • 🎵 Music & video from YouTube (search or URL) or any audio/video file posted in chat
  • 🔎 /search results picker — pick a hit to play as audio or video
  • 📻 Internet radio with the live now-playing track shown on the video card
  • 📼 Recording — capture radio or video to a voice/video message (toggle on/off, tracklist)
  • 📁 Local media library — browse & play your own folders, with audio-track & subtitle selection
  • 🎛 Full controls — pause/resume/skip/seek/volume/loop/shuffle/queue + an inline panel
  • ⚡ Hardware transcoding (VAAPI/CPU) for HEVC/MKV
  • 🔁 Self-healing — auto-reconnect on drops, resume after restart, idle auto-leave
  • 🐳 One-command Docker deploy, fully env-configured

Built with Pyrogram and py-tgcalls. See the README for setup.