Home → Blog → How to build a Telegram bot that transcribes voice messages
How to build a Telegram bot that transcribes voice messages
Voice messages are unreadable in a meeting, on the metro, or simply when you cannot be bothered. A bot that answers a voice note with its text removes that friction, and it takes one evening to build. Here is the whole flow, from file to reply.
What the bot does
The logic fits into four steps:
- Receive an update containing a voice message and read the file id.
- Download the file from the link Telegram provides.
- Send it for recognition.
- Reply with the text in the same thread.
One nice detail: Telegram stores voice notes as ogg/opus — a format accepted with no conversion at all.
The handler
The example uses python-telegram-bot, but the logic is the same in any library:
import io
from telegram import Update
from telegram.ext import Application, MessageHandler, filters, ContextTypes
from openai import OpenAI
client = OpenAI(base_url="https://voicesscribe.com/v1", api_key="your key")
async def on_voice(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
voice = update.message.voice or update.message.audio
tg_file = await ctx.bot.get_file(voice.file_id)
buf = io.BytesIO(await tg_file.download_as_bytearray())
buf.name = "voice.ogg"
text = client.audio.transcriptions.create(model="whisper-1", file=buf).text
await update.message.reply_text(text or "could not make out any speech")
app = Application.builder().token("bot token").build()
app.add_handler(MessageHandler(filters.VOICE | filters.AUDIO, on_voice))
app.run_polling()
The critical line is setting buf.name. Without a filename the library cannot infer the format and the request fails.
Rough edges
- Slow replies. Send a typing action while recognition runs, otherwise the bot looks frozen.
- Long results. Telegram truncates messages over 4096 characters, so split long transcripts.
- Video notes. Round video messages arrive as a separate video_note type; their audio transcribes fine but you must handle the type explicitly.
- Group chats. By default a bot cannot see other people's messages — privacy mode is switched off through BotFather.
What to add after the first version
Version one replies with bare text. The usual next steps are three: a summary for long messages, a per-user quota so the bot does not become a free service for the entire internet, and storing transcripts so history becomes searchable.
Track usage in minutes of audio: that is exactly how billing works, and the same number tells you what each user costs you.
Try it on your own recordings. Sign-up takes a minute, and the free minutes are enough to judge the quality.
Get a free API keyFrequently asked questions
Do Telegram voice files need converting?
No. The messenger sends ogg/opus, which is accepted directly — just give the upload a filename ending in .ogg.
Why do very short notes fail?
They are usually empty recordings of a fraction of a second, created by an accidental tap. Check the duration before sending.
How do I see who used how much?
Sum the duration of processed messages per user: billing is per minute of audio, so the same metric is your cost.
Can it handle round video messages?
Yes, the audio inside transcribes the same way. They just arrive as a different message type in the API.
Related reading
- Voice message transcription: Telegram, WhatsApp and other messengers — How to turn voice messages into text automatically: working with ogg/opus, short clips, silent recordings and ready code for chat bots that answer in text.
- How to turn voice notes into text automatically — Turn phone and recorder voice notes into a searchable knowledge base: a synced folder, a watcher script, a note template and tips for messy field audio.
- Speech to text in Python: from one file to a working script — A working Python speech-to-text setup in ten minutes: install, the first request, response formats, error handling, and the mistakes that cost the most time.