- 后端
- 即时通讯
- API设计
【免费下载链接】aiogram
aiogram is a modern and fully asynchronous framework for Telegram Bot API written in Python using asyncio
语音消息(Voice Note)是 Telegram Bot API 中一类高频使用的媒体消息。在 aiogram 中,Voice对象承载了语音消息的全部元数据(文件标识、时长、大小等),是理解"收到语音 → 解析 → 回复/转发"这条完整链路的关键类型。本指南以 docs/api/types/voice.rst 为骨架,结合 aiogram 源码中Voice类型定义、sendVoice方法实现、Message对象集成方式以及对应测试用例,系统讲解语音消息的字段含义、接收识别、发送方法与底层原理,读完即可在真实 bot 中正确处理与收发语音消息。
一、Voice 类型概述:一个表示语音消息的 Pydantic 模型
在 aiogram 中,Voice是TelegramObject的子类,定义于 aiogram/types/voice.py,其 docstring 明确指出:
This object represents a voice note.
它对应 Telegram Bot API 官方文档中的Voice对象,用于描述一条语音消息(voice note)的静态信息,例如文件 ID、时长、MIME 类型与文件大小。与Audio(音乐文件,见 aiogram/types/audio.py)不同,Voice专指用户在聊天中按住麦克风录制的"语音条",在 Telegram 客户端中呈现为可播放的语音气泡。
从代码结构看,Voice的所有字段都由 Pydantic 驱动(继承自TelegramObject),并额外通过butcher自动生成了TYPE_CHECKING块下的__init__签名,用于在无插件环境下提供完整的 IDE 类型提示支持。
二、字段详解:五个核心属性的语义与默认值
根据 aiogram/types/voice.py 的类定义,Voice共有 5 个字段,其中 3 个为必填、2 个为可选:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
file_id | str | 必填 | 文件标识符,可用于下载或复用该文件 |
file_unique_id | str | 必填 | 文件的唯一标识,跨时间、跨 bot 保持不变;不能用于下载或复用文件 |
duration | int | 必填 | 音频时长(秒),由发送方定义 |
mime_type | str | None | None | 可选。文件的 MIME 类型,由发送方定义 |
file_size | int | None | None | 可选。文件大小(字节) |
2.1 file_id 与 file_unique_id:最容易混淆的一对字段
这两个字段是 Telegram 媒体对象的通用设计(Animation、Audio、Document、Video、VideoNote等类型均遵循同一模式,见 aiogram/types/audio.py 中的对照实现):
file_id:是"可用"的标识符。你可以直接把它作为sendVoice等方法的voice参数传入,Telegram 服务器会依据它复用已存在的文件,而无需再次上传;也可以在getFile中用来换取下载路径。它的稳定性只局限于"同一个 bot + 当前时间窗口"内,长时间后可能失效。file_unique_id:是"可识别"的标识符。它在任意 bot、任意时间段内都唯一且稳定,适合作为数据库主键或去重依据,但 Telegram 明确禁止用它下载或复用文件。
aiogram 进一步将"可下载"这一能力抽象为Downloadable协议,见 aiogram/types/downloadable.py:任何实现了file_id属性的类型都可以被通用下载逻辑处理。
2.2 duration:语音条的核心业务字段
duration表示语音秒数。在实现"语音时长限制""自动转写""超长语音提示"等业务逻辑时,这是最常用的字段。发送方定义后由 Telegram 服务器透传,aiogram 不做任何加工,直接映射为int。
2.3 mime_type 与 file_size:可选的扩展信息
mime_type由发送方声明,常见取值如audio/ogg、audio/mpeg等,可用于在播放前判断编码格式;file_size以字节为单位。源码 docstring 特别提示:该值可能大于 2³¹,部分编程语言在解释它时可能出现困难或静默缺陷,但其最多只有 52 个有效位,因此有符号 64 位整数或双精度浮点类型都能安全存储。在 Python 中int无此顾虑,但若将该值经 JSON 或数据库传输到其他语言环境,应留意此限制。
三、如何接收语音消息:Message.voice 与 ContentType 判定
语音消息在 aiogram 中通过Message对象的voice字段暴露。在 aiogram/types/message.py 中可以看到:
voice: Voice | None = None """*Optional*. Message is a voice message, information about the file"""即:只有消息是语音消息时,message.voice才非空;其余媒体类型(audio、document、photo等)各自拥有独立字段,互不冲突。
与之配套的是ContentType判定。在 aiogram/types/message.py 的content_type属性实现中:
if self.voice: return ContentType.VOICE因此在实际开发中,识别语音消息有两种等价方式:
from aiogram import F from aiogram.types import Message, ContentType # 方式一:基于 content_type @router.message(F.content_type == ContentType.VOICE) async def handle_voice_ct(message: Message): await message.answer(f"收到语音:时长 {message.voice.duration} 秒") # 方式二:直接基于 voice 字段 @router.message(F.voice) async def handle_voice_field(message: Message): voice: Voice = message.voice await message.answer( f"file_id={voice.file_id}\n" f"unique_id={voice.file_unique_id}\n" f"duration={voice.duration}s\n" f"mime={voice.mime_type}\n" f"size={voice.file_size} bytes" )在测试层面,仓库的 tests/test_api/test_types/test_message.py 构造了一个典型的语音消息测试样例:
voice=Voice(file_id="file id", file_unique_id="file id", duration=0),这印证了三个必填字段(file_id、file_unique_id、duration)即可构造出合法的Voice对象,两个可选字段在未提供时自动为None。
四、如何发送语音消息:bot.send_voice 与 sendVoice 方法
发送语音消息对应 Telegram API 的sendVoice方法。aiogram 在 aiogram/methods/send_voice.py 中将其封装为SendVoice请求对象(__api_method__ = "sendVoice",成功时返回Message),并在 aiogram/client/bot.py 提供了异步快捷方法bot.send_voice。
4.1 三种传文件方式
voice参数的类型为InputFileUnion,其定义见 aiogram/types/input_file_union.py:
InputFileUnion: TypeAlias = str | InputFile即支持三种传法:
- 传 file_id(推荐):直接传
str类型的file_id,复用 Telegram 服务器上已存在的文件,无需重新上传; - 传 HTTP URL:传一个以
http开头的字符串,Telegram 会自行从互联网抓取该文件; - 上传新文件:传
InputFile实例(如本地文件路径、BufferedInputFile包装的字节流等),aiogram 会通过 multipart/form-data 完成上传。
4.2 格式要求与大小限制
SendVoice的 docstring(aiogram/methods/send_voice.py)明确指出:
要让 Telegram 客户端将音频显示为可播放的语音消息,音频必须是.OGG(OPUS 编码)、.MP3或.M4A格式;其他格式将作为
Audio或Document发送。Bot 当前可发送的语音消息上限为50 MB。
这一限制同时出现在 aiogram/client/bot.py 与Message.reply_voice的 docstring 中,是官方 API 的硬性约束。
4.3 常用参数一览
bot.send_voice(签名见 aiogram/client/bot.py)支持丰富的可选参数,常用如下:
| 参数 | 类型 | 说明 |
|---|---|---|
chat_id | ChatIdUnion | 目标聊天 ID,或@username格式的群组/频道/机器人用户名 |
voice | InputFileUnion | 语音文件(file_id / URL / InputFile) |
caption | str | None | 语音消息的说明文字,实体解析后 0–1024 字符 |
parse_mode | str | Default | None | 标题实体解析模式(HTML / MarkdownV2 等),默认Default("parse_mode"),即跟随全局默认配置 |
caption_entities | list[MessageEntity] | None | 显式指定的实体列表,可用于替代parse_mode |
duration | int | None | 语音时长(秒),由发送方填写 |
disable_notification | bool | None | 静默发送 |
protect_content | bool | Default | None | 禁止转发与保存消息内容 |
reply_parameters | ReplyParameters | None | 回复的目标消息描述 |
reply_markup | ReplyMarkupUnion | None | 内联键盘、自定义键盘等附加界面选项 |
从源码结构看,parse_mode与protect_content的默认值均使用Default(...)占位符(见 aiogram/methods/send_voice.py 与 aiogram/methods/send_voice.py),这表示它们会继承Bot实例上配置的全局默认值,而不是固定为None——这是 aiogram 3.x 的Default机制的典型用法。
4.4 完整示例:上传本地文件发送语音
from aiogram import Bot, Dispatcher from aiogram.client.default import DefaultBotProperties from aiogram.enums import ParseMode from aiogram.types import BufferedInputFile TOKEN = "YOUR_BOT_TOKEN" bot = Bot( TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML), ) dp = Dispatcher() @dp.message() async def send_voice_to_user(message): # 方式一:复用 file_id(收到的语音直接转给用户) if message.voice: await message.answer_voice(message.voice.file_id, caption="转发你的语音") # 方式二:上传本地 OGG/OPUS 文件 with open("note.ogg", "rb") as f: data = f.read() await bot.send_voice( chat_id=message.chat.id, voice=BufferedInputFile(data, filename="note.ogg"), duration=12, # 发送方声明的时长 caption="<b>语音播报</b>", )4.5 方法级测试验证
仓库为send_voice提供了完整的单元测试 tests/test_api/test_methods/test_send_voice.py:
prepare_result = bot.add_result_for( SendVoice, ok=True, result=Message( message_id=42, date=datetime.datetime.now(), voice=Voice(file_id="file id", duration=0, file_unique_id="file id"), chat=Chat(id=42, type="private"), ), ) response: Message = await bot.send_voice(chat_id=42, voice="file id")该测试验证了两个关键事实:bot.send_voice接受裸字符串file_id作为voice参数;调用成功后返回的Message中voice字段即为Voice实例,与测试预期完全相等。
五、配套能力:回复、复制与聊天动作
5.1 Message.reply_voice / answer_voice 快捷方法
在收到消息后,若想"就地回复"语音,可使用Message上的reply_voice快捷方法。其实现位于 aiogram/types/message.py,docstring 明确说明它会自动填充以下属性:
chat_idmessage_thread_id(论坛主题场景)business_connection_idreply_parameters(基于当前消息构造)ephemeral_message_parameters
answer_voice是语义等价的方法(同样映射到SendVoice,见 aiogram/types/message.py 的对应生成代码),在测试 tests/test_api/test_types/test_message.py 中以["voice", {"voice": "voice"}, SendVoice]形式验证了其返回SendVoice请求对象的行为。二者区别仅在于命名习惯:answer_*强调"作为回应发出",实现上等价。
5.2 复制语音消息:send_copy 链路
当需要"复制"(而非转发)一条语音消息时,Message.send_copy会在 aiogram/types/message.py 中命中以下分支:
if self.voice: return SendVoice( voice=self.voice.file_id, **kwargs, ).as_(self._bot)即自动提取voice.file_id构造SendVoice,实现无上传的复用发送。这也从侧面说明file_id在"下载或复用"场景中的核心价值。
5.3 发送前的聊天动作:record_voice 与 upload_voice
Telegram 要求上传大文件前先发送对应的 Chat Action,让用户看到"正在录音 / 正在上传"的状态提示。aiogram 在 aiogram/utils/chat_action.py 提供了两个现成构造器:
ChatActionSender.record_voice(chat_id, bot):对应record_voice动作;ChatActionSender.upload_voice(chat_id, bot):对应upload_voice动作。
两者均支持message_thread_id、interval(默认DEFAULT_INTERVAL)与initial_sleep参数,可通过async with上下文或在后台任务中使用,典型搭配如下:
from aiogram.utils.chat_action import ChatActionSender async def send_voice_with_action(bot, chat_id): action = ChatActionSender.record_voice(chat_id=chat_id, bot=bot) async with action: # 在此执行耗时较长的语音生成 / 上传逻辑 await bot.send_voice(chat_id=chat_id, voice="file_id")六、Voice 与相邻类型的关系边界
在 Telegram 媒体体系中,语音相关类型容易混淆,明确边界有助于正确建模:
| 类型 | 定位 | 关键差异 |
|---|---|---|
Voice | 语音消息(voice note) | 仅含duration、mime_type、file_size等基础元数据,无缩略图 |
Audio(见 aiogram/types/audio.py) | 音乐文件 | 额外含performer、title、file_name、thumbnail字段 |
VideoNote | 圆形视频消息 | 额外含thumbnail、file_size等,带画面 |
Document | 普通文件 | 任意格式均可,不保证可播放 |
从Voice缺少performer、title、thumbnail字段这一源码事实(对照 aiogram/types/audio.py)可以看出:语音消息面向的是"即录即发"场景,Telegram 不为其附加音乐标签或封面图。
七、总结:Voice 类型在 aiogram 中的完整生命周期
回顾全文,Voice类型贯穿语音消息处理的完整链路:
- 接收:
Message.voice字段承载Voice实例,content_type == ContentType.VOICE或F.voice过滤器均可识别(见 aiogram/types/message.py); - 解析:
file_id用于复用/下载,file_unique_id用于稳定去重,duration用于业务判断,mime_type/file_size作为可选扩展信息; - 发送:通过
bot.send_voice(aiogram/client/bot.py)或message.reply_voice/answer_voice(aiogram/types/message.py)以 file_id、URL 或InputFile三种方式发出,注意 .OGG/OPUS、.MP3、.M4A 格式要求与 50 MB 上限; - 复制:
send_copy自动提取voice.file_id构造SendVoice(aiogram/types/message.py); - 体验优化:配合
ChatActionSender.record_voice/upload_voice(aiogram/utils/chat_action.py)提升上传过程的用户体验。
掌握这五个环节,即可在 aiogram 项目中完整、正确地实现语音消息的接收、识别、回复与转发功能。
- 后端
- 即时通讯
- API设计
【免费下载链接】aiogram
aiogram is a modern and fully asynchronous framework for Telegram Bot API written in Python using asyncio
相关推荐
OpenShift API 仓库开发指南:FeatureGate 特性门控体系、代码生成与 API 演进最佳实践
OpenShift API 仓库开发指南:FeatureGate 特性门控体系、代码生成与 API 演进最佳实践 导读 本文以 OpenShift API 仓库
后端即时通讯API设计x402 EVM 机制包深度解析:@x402/evm 参考实现与 Permit2、Up-To Scheme 的落地实践
x402 EVM 机制包深度解析:@x402/evm 参考实现与 Permit2、Up To Scheme 的落地实践 导读 @x402/evm 是 x402
后端即时通讯API设计aiogram 发送地点消息指南:SendVenue 方法全解析与实战
aiogram 发送地点消息指南:SendVenue 方法全解析与实战 sendVenue 是 Telegram Bot API 中用于向用户发送"地点卡片"(
后端即时通讯API设计
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考