前言
在微信自动化场景中,文字消息早已是标配,但语音消息往往更能拉近与用户的距离——尤其在客服回访、语音播报提醒、教育陪伴类产品中,一条定制语音消息的打开率和回复率远高于纯文字。然而微信官方并不开放个人号语音发送接口,市面上大多数方案要么依赖模拟点击、稳定性差,要么绕不开设备信任问题。本文将围绕基于 iPad 协议的 WechatApi 平台,系统讲解个人微信语音消息接口的接入原理、调用步骤、参数规范和实战注意事项。
一、语音消息的底层格式与协议基础
在正式写代码之前,有必要先搞清楚微信语音消息在协议层面的本质,否则接口调通了也容易踩坑。
微信客户端的语音消息并不是直接发送 MP3 或 WAV 文件,而是采用 SILK 格式(Skype Internet Low Complexity Codec)进行音频编码。SILK 是一种针对语音通话优化的低比特率编解码器,相比 MP3 体积更小、在弱网下表现更好。微信在此基础上还会做一层私有封装,形成 .silk 文件,最终在服务端存储后通过 CDN 分发。
理解这一点的意义在于:当你调用接口发送语音时,不能直接扔一个 MP3 进去,需要提前将音频转换为 SILK 格式,或者使用平台提供的格式转换能力。
WechatApi 使用的是 iPad 协议实现,相比 Web 协议或 XPosed Hook 方案,iPad 协议在微信服务端视角下是一台合法登录的 iPad 设备,具有以下优势:
| 维度 | iPad 协议 | Web 协议 | Hook 方案 |
|---|---|---|---|
| 账号安全性 | 高,不触发异常设备检测 | 中,易触发 Web 端风控 | 低,需要真机且易封号 |
| 语音消息支持 | 完整支持 SILK 发送 | 不支持语音发送 | 支持但依赖真机稳定性 |
| 消息类型覆盖 | 文字、图片、语音、视频、文件等全类型 | 部分类型受限 | 全类型但有崩溃风险 |
| 多设备并发 | 支持,云端托管 | 不支持 | 受真机数量限制 |
| 掉线恢复 | 自动重连 | 需手动处理 | 依赖设备状态 |
从表中可以看出,iPad 协议方案在稳定性和功能完整性上是个人微信自动化场景的最优选择。
二、接入前准备:账号注册与设备绑定
在调用任何接口之前,需要完成以下准备工作。
第一步:注册 WechatApi 账号
访问 WechatApi 控制台 完成注册,注册后可以获得一个试用额度,用于测试接口联通性。
第二步:创建设备实例并获取 appId
登录控制台后,在设备管理页面创建一个新的设备实例。每个设备实例对应一个微信账号的托管连接,创建完成后系统会分配一个唯一的 appId(设备ID)。这个 appId 是后续所有 API 调用的核心业务参数,标识"用哪个微信账号来执行操作"。
第三步:扫码登录微信
在设备实例页面,会生成一个用于微信扫码登录的二维码。使用目标微信账号扫码确认后,设备状态变为"在线",即可开始调用接口。
第四步:获取 API Token
在控制台的 API 管理页面可以生成 VideosApi-token,这是所有接口调用的鉴权凭证,需要放在 HTTP 请求头中。Token 务必妥善保管,不要硬编码在前端代码或提交到代码仓库。
三、语音文件格式转换:从 MP3 到 SILK
如果你的业务场景是 TTS(文字转语音)后发送,通常 TTS 服务输出的是 MP3 格式,需要先做格式转换。
方式一:使用 ffmpeg + silk-v3-decoder 本地转换
这是最通用的离线转换方案,适合对延迟敏感或需要批量处理的场景。
bash# 第一步:用 ffmpeg 将 MP3 转为 PCM(采样率 24000Hz,单声道,16bit)
ffmpeg -i input.mp3 -ar 24000 -ac 1 -f s16le output.pcm
# 第二步:用 silk 编码器将 PCM 编码为 SILK
# encoder 可从开源项目 kn007/silk-v3-decoder 编译获得
./encoder output.pcm output.silk -tencent
# 转换完成后,output.silk 即可用于接口上传
注意事项:
- 采样率必须是 24000Hz,这是微信 SILK 语音的标准采样率
- 必须是单声道(mono),立体声会导致音质异常
-tencent参数是针对微信私有 SILK 格式的必选项,不加这个参数生成的文件微信无法正常播放
方式二:通过接口上传原始音频让平台处理
部分场景下,WechatApi 平台支持直接上传 MP3/WAV 文件并在服务端完成格式转换,具体能力以文档 post.wechatapi.net 中的最新说明为准。如果平台支持这一能力,则可以省去本地转码的环节,接入成本大幅降低。
四、核心接口调用:发送语音消息
完成前期准备后,进入正式的接口调用环节。发送语音消息通常分为两个步骤:上传音频文件 和 发送语音消息。
4.1 上传 SILK 音频文件
首先需要将本地的 SILK 文件上传到平台,获取一个 mediaId(媒体资源ID),后续发送时引用这个 ID。
pythonimport requests
API_BASE = "https://api.wechatapi.net" # 示意域名,以文档为准
TOKEN = "your-videos-api-token-here" # 替换为实际 token,勿上传至代码仓库
APP_ID = "your-device-app-id-here" # 控制台获取的设备 appId
def upload_voice(silk_file_path: str) -> str:
"""上传 SILK 语音文件,返回 mediaId"""
url = f"{API_BASE}/voice/upload" # 示意路径,实际以文档为准
headers = {
"VideosApi-token": TOKEN,
"Content-Type": "application/json"
}
# 读取文件并 base64 编码
import base64
with open(silk_file_path, "rb") as f:
file_b64 = base64.b64encode(f.read()).decode("utf-8")
payload = {
"appId": APP_ID,
"fileData": file_b64,
"fileType": "silk"
}
resp = requests.post(url, json=payload, headers=headers, timeout=30)
result = resp.json()
if result.get("ret") == 200:
media_id = result["data"]["mediaId"]
print(f"上传成功,mediaId: {media_id}")
return media_id
else:
raise Exception(f"上传失败: {result.get('msg')}")
上传成功的响应体格式示例:
json{
"ret": 200,
"msg": "upload success",
"data": {
"mediaId": "MEDIA_ID_EXAMPLE_abc123xyz",
"duration": 8,
"size": 12480
}
}
其中 duration 是音频时长(秒),size 是文件大小(字节)。
4.2 发送语音消息到指定联系人
拿到 mediaId 后,调用发送接口将语音消息推送给目标微信好友或群聊。
pythondef send_voice_message(to_wxid: str, media_id: str, duration: int) -> bool:
"""
发送语音消息
:param to_wxid: 接收方微信 wxid 或群 chatroom ID
:param media_id: 上传后获取的媒体资源 ID
:param duration: 音频时长(秒),需与实际文件一致
:return: 发送是否成功
"""
url = f"{API_BASE}/message/sendVoice" # 示意路径,实际以文档为准
headers = {
"VideosApi-token": TOKEN,
"Content-Type": "application/json"
}
payload = {
"appId": APP_ID,
"toWxId": to_wxid,
"mediaId": media_id,
"duration": duration
}
resp = requests.post(url, json=payload, headers=headers, timeout=15)
result = resp.json()
if result.get("ret") == 200:
print(f"语音消息发送成功,消息ID: {result['data'].get('msgId')}")
return True
else:
print(f"发送失败,错误信息: {result.get('msg')}")
return False
# 使用示例
if __name__ == "__main__":
media_id = upload_voice("output.silk")
send_voice_message("wxid_target_friend", media_id, duration=8)
发送成功的响应体示例:
json{
"ret": 200,
"msg": "send success",
"data": {
"msgId": "MSG_ID_EXAMPLE_789",
"toWxId": "wxid_target_friend",
"createTime": 1749820800
}
}
五、关键参数详解与常见字段说明
下表汇总了语音消息相关接口的核心参数,便于快速查阅。
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
VideosApi-token | 请求头 | string | 是 | 鉴权 token,从控制台获取 |
appId | 请求体 | string | 是 | 设备ID,标识使用哪个微信账号 |
toWxId | 请求体 | string | 是 | 接收方 wxid 或群 chatroom ID(如 xxx@chatroom) |
mediaId | 请求体 | string | 是 | 上传音频后获得的媒体资源 ID |
duration | 请求体 | integer | 是 | 语音时长,单位秒,须与实际文件时长匹配 |
fileData | 请求体 | string | 是(上传时) | SILK 文件的 base64 编码内容 |
fileType | 请求体 | string | 是(上传时) | 固定值 "silk" |
ret | 响应体 | integer | — | 状态码,200 表示成功 |
msg | 响应体 | string | — | 状态描述,成功或错误原因 |
data | 响应体 | object | — | 业务数据,内容因接口而异 |
关于 duration 字段:这是一个容易被忽略的细节。如果 duration 传入的值与实际音频时长不符,微信客户端在显示语音气泡时会出现时长显示错误,甚至在某些版本上影响语音播放体验。建议在转码阶段用 ffprobe 精确获取时长:
bash# 获取音频精确时长(秒)
ffprobe -v error -show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 output.silk
六、典型业务场景与进阶用法
场景一:TTS 文字转语音后自动发送
这是语音消息接口最高频的使用场景之一。典型流程:
- 用百度 TTS、阿里云 TTS 或 Azure TTS 将业务文案转成 MP3
- 本地用 ffmpeg + silk encoder 转为 SILK 格式
- 调用 WechatApi 上传接口获取 mediaId
- 调用发送接口推送给目标用户
整个流程可以封装成一个函数,配合消息队列(如 Redis Queue 或 Celery)实现高并发的语音消息批量发送,适合客服外呼、活动通知等场景。
场景二:群内定时语音播报
在社群运营中,定时语音播报是一种提升活跃度的有效手段。例如早报、行情播报、每日任务提醒等。可以结合定时任务(cron)和 WechatApi 的群管理机器人能力,实现全自动的群内语音推送。
关键点:群消息的 toWxId 格式为 xxxxxxxx@chatroom,可以通过获取群列表接口拿到准确的群 chatroom ID,不能靠猜。
场景三:客服场景下的语音自动回复
在 SCRM 和客服机器人场景中,有些用户更习惯用语音沟通。当检测到用户发来语音消息时,可以触发一段预录制或动态生成的语音回复。WechatApi 的 Webhook 推送能力可以实时接收用户消息,业务层处理后再通过语音发送接口回复。结合 WechatApi 微信SCRM 能力,可以构建完整的对话闭环。
进阶:语音消息的幂等性处理
在高并发场景下,网络超时重试可能导致同一条语音消息被发送多次。建议:
- 在业务层维护一个"已发送消息ID"的幂等记录(Redis SET 即可)
- 每次发送前先检查该业务消息是否已发送成功
- 接口返回的
msgId可作为去重的唯一标识存入记录
七、注意事项与常见报错处理
1. SILK 文件损坏导致发送失败
如果上传接口返回 ret: 400 且 msg 中提示文件格式错误,大概率是 SILK 转换步骤有问题。常见原因:忘加 -tencent 参数、PCM 采样率不是 24000、文件转码中断导致文件不完整。
排查方法:用 silk-v3-decoder 的 decoder 工具尝试将 SILK 文件解码回 PCM,如果解码失败则说明 SILK 文件本身有问题,需要重新转码。
2. duration 与实际时长偏差
如前所述,建议用 ffprobe 精确获取时长后取整(向上取整),而不是估算。偏差过大时某些微信版本会在播放时提前结束。
3. mediaId 的有效期
上传到平台的媒体资源 ID 通常有时效性(具体以文档说明为准,一般在数小时到数天之间)。如果需要复用同一段语音(如固定话术),建议在有效期内缓存 mediaId,过期后重新上传,而不是每次都上传同一个文件。
4. 账号风控问题
虽然 iPad 协议在风控上比 Web 协议安全得多,但大规模群发语音消息仍然需要注意节奏控制。建议:
- 单账号单日语音消息发送量不要过于集中在短时间内
- 避免向从未互动过的陌生账号发送语音(容易被标记为骚扰)
- 利用 WechatApi 的微信二次开发能力设计合理的发送频率限制
5. 错误码速查
| ret 值 | 含义 | 处理建议 |
|---|---|---|
| 200 | 成功 | 正常处理返回数据 |
| 400 | 参数错误 | 检查请求体字段是否完整、格式是否正确 |
| 401 | 鉴权失败 | 检查 VideosApi-token 是否正确且未过期 |
| 403 | 权限不足 | 确认当前套餐是否包含语音消息发送权限 |
| 410 | 设备离线 | 登录控制台确认设备在线状态,必要时重新扫码 |
| 429 | 请求频率超限 | 降低调用频率,加入请求间隔控制 |
| 500 | 服务端异常 | 稍后重试,持续出现可提交工单 |
小结
微信发送语音消息接口的核心链路并不复杂:格式转换(MP3→SILK)→ 上传获取 mediaId → 调用发送接口。难点在于 SILK 格式的正确生成、duration 参数的精确传递,以及在业务层做好幂等和频率控制。
基于 iPad 协议的 WechatApi 平台提供了完整的个人微信语音消息发送能力,云端托管无需真机,支持多账号并发,是目前个人微信自动化场景中稳定性较高的选择。如需试用,可访问 WechatApi 控制台 注册,详细接口文档见 post.wechatapi.net。
