If you've ever tried to set a video as your Telegram profile picture and watched nothing happen, you're not alone. Telegram has a narrow, undocumented media spec.
The spec
- Dimensions: exactly 800x800 pixels
- Codec: H.264 only
- Duration: at most 10.0 seconds
- File size: at most 2 MB
- Audio: no audio track
- Pixel format: yuv420p
- Container: MP4 with faststart
Any violation = silent rejection.
The iPhone problem
iPhone records in HEVC by default. HEVC is unusable as a Telegram avatar.
The ffmpeg command
ffmpeg -i input.mov \
-t 10 \
-vf "crop=min(iw\,ih):min(iw\,ih),scale=800:800,fps=30" \
-c:v libx264 \
-preset medium \
-pix_fmt yuv420p \
-b:v 900k \
-an \
-movflags +faststart \
output.mp4
Wrapping it in a bot
from aiogram import Router, F
from aiogram.types import Message, FSInputFile
import asyncio, tempfile
from pathlib import Path
router = Router()
@router.message(F.video | F.animation | F.document)
async def handle_video(message: Message):
file = message.video or message.animation or message.document
with tempfile.TemporaryDirectory() as td:
inp = Path(td) / "in.bin"
out = Path(td) / "out.mp4"
await message.bot.download(file, destination=inp)
# ffmpeg subprocess here
await message.answer_video(FSInputFile(out))
Try it
Skip writing ffmpeg yourself: https://t.me/LiveAvaBot?start=devto_article_20260418
Top comments (0)