Все почалося з того, що друзі скидали мені відоси з Тіктока в особисті. Ставити ще один таймкілер я принципово не хотів, але й тримати в особистих звалище лінків теж не хотілося.
Вирішили зробити окремий чат суто під контент і закинути туди бота. На той час виявилося, що готові боти доволі повільні, ще й з рекламою казино (думаю нікого не здивував). І найголовніше ніде не було механіки вогників (стріків). Це була критична умова, щоб симулювати реальний чат тіктоку.
Технічна частина: Raspberry Pi та /dev/shm
Часто використовував Python, тому і обрав його + aiogram (до речі made in Ukraine). Пощастило написати базу до появи АІ агентів, код ще читабельний :)
Бот із самого початку і досі крутиться на Raspberry Pi. Головне обмеження, яке я сам собі поставив: нуль записів на накопичувач. Вбивати SD картку малини постійними циклами перезапису не хотілося, до того ж вона і так не найшвидше сховище.
Звісно, перша думка була "ганяти все тупо через пайпи в io.BytesIO". Але на практиці з'явилися нюанси:
- yt-dlp та ffmpeg хочуть нормальні дескриптори або шляхи: деякі фрагментовані потоки, скачування частинами чи зшивання MP4 (коли треба шукати moov atom) відмовляються стабільно працювати через чисті пайпи в пам'яті.
- Рішення просте -
/dev/shm (ramdisk / tmpfs): тимчасові файли пишуться в пам'ять як звичайні файли через tempfile.NamedTemporaryFile(dir='/dev/shm'). Для апки це звичайний шлях на диску, а для малини нуль навантаження на SD картку.
З якими граблями стикнувся при роботі з RAM:
- Зомбі-файли та витік оперативки: якщо ffmpeg чи скачування відвалюється по таймауту або кидає exception, файли в
/dev/shm можуть лишитися висіти. На малині з її кількома гігабайтами пам'яті це швидко призводить до OOM. Довелося жорстко обмазувати все try...finally контекстними менеджерами для гарантованого видалення.
- Слабка система: 2-3 паралельні важкі транскодування через CPU і малина вже не вивозить. Тому довелося запровадити семафори (
asyncio.Semaphore(2)), перевірку кодеків через ffprobe (якщо відео вже h264/aac то робимо stream copy без перекодування) та жорсткий ліміт на розмір файлу.
- Кешування
file_id: щоб не ганяти однаковий трафік, успішно завантажені медіа кешуються в SQLite за хешем/канонічним URL. Якщо відео вже є в базі - бот віддає його через Telegram file_id буквально за 100 мс.
Фічі для груп та особистих:
- Підтримка платформ: починалося все з TikTok, але згодом додав підтримку Reels, Shorts, Pinterest, Reddit, X та аудіо зі Spotify.
- Inline-режим: якщо треба скинути тікток (чи будь що інше) людині в ПП, у якої немає додатку можна прямо в діалозі з нею ввести @ tik_boss_bot <лінк>. Бот відрендерить прев'ю і відправить відео прямо в приватний чат. Можна бути впевненим що співрозмовник гляне відео, а не полінується відкрити його
- Стріки (вогники): якщо в групу щодня скидають контент, бот рахує дні поспіль і сам міняє назву чату в Telegram (додає | 🔥 5).
- Clean Mode: видаляє повідомлення з сирим посиланням після того, як скинув чисте відео, щоб не засмічувати чат
Навіщо цей пост
Хочу перевірити, як малина та логіка витримують навантаження, коли посилання летять не тільки від 2-3 користувачів одночасно. Особливо цікаво відловити нестандартні кейси: довгі відео YouTube, Spotify, TikTok-каруселі фото тощо.
Бот у Telegram: @tik_boss_bot
(Якщо не важко, надішліть йому команду /start reddit_dev, додав цей параметр як мітку в логи щоб бачити сплеск навантаження саме з Reddit)
Буду вдячний, якщо протестуєте на своїх лінках і напишете, де впало або що можна докрутити по швидкодії.