首页 / 博客 / API·多语言·接口

微信发送语音消息接口实战

分类:API·多语言·接口 · 标签:微信语音消息接口、个人微信API、微信自动化开发

前言

在微信自动化场景中,文字消息早已是标配,但语音消息往往更能拉近与用户的距离——尤其在客服回访、语音播报提醒、教育陪伴类产品中,一条定制语音消息的打开率和回复率远高于纯文字。然而微信官方并不开放个人号语音发送接口,市面上大多数方案要么依赖模拟点击、稳定性差,要么绕不开设备信任问题。本文将围绕基于 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 即可用于接口上传

注意事项:

方式二:通过接口上传原始音频让平台处理

部分场景下,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 文字转语音后自动发送

这是语音消息接口最高频的使用场景之一。典型流程:

  1. 用百度 TTS、阿里云 TTS 或 Azure TTS 将业务文案转成 MP3
  2. 本地用 ffmpeg + silk encoder 转为 SILK 格式
  3. 调用 WechatApi 上传接口获取 mediaId
  4. 调用发送接口推送给目标用户

整个流程可以封装成一个函数,配合消息队列(如 Redis Queue 或 Celery)实现高并发的语音消息批量发送,适合客服外呼、活动通知等场景。

场景二:群内定时语音播报

在社群运营中,定时语音播报是一种提升活跃度的有效手段。例如早报、行情播报、每日任务提醒等。可以结合定时任务(cron)和 WechatApi 的群管理机器人能力,实现全自动的群内语音推送。

关键点:群消息的 toWxId 格式为 xxxxxxxx@chatroom,可以通过获取群列表接口拿到准确的群 chatroom ID,不能靠猜。

场景三:客服场景下的语音自动回复

在 SCRM 和客服机器人场景中,有些用户更习惯用语音沟通。当检测到用户发来语音消息时,可以触发一段预录制或动态生成的语音回复。WechatApi 的 Webhook 推送能力可以实时接收用户消息,业务层处理后再通过语音发送接口回复。结合 WechatApi 微信SCRM 能力,可以构建完整的对话闭环。

进阶:语音消息的幂等性处理

在高并发场景下,网络超时重试可能导致同一条语音消息被发送多次。建议:


七、注意事项与常见报错处理

1. SILK 文件损坏导致发送失败

如果上传接口返回 ret: 400msg 中提示文件格式错误,大概率是 SILK 转换步骤有问题。常见原因:忘加 -tencent 参数、PCM 采样率不是 24000、文件转码中断导致文件不完整。

排查方法:用 silk-v3-decoder 的 decoder 工具尝试将 SILK 文件解码回 PCM,如果解码失败则说明 SILK 文件本身有问题,需要重新转码。

2. duration 与实际时长偏差

如前所述,建议用 ffprobe 精确获取时长后取整(向上取整),而不是估算。偏差过大时某些微信版本会在播放时提前结束。

3. mediaId 的有效期

上传到平台的媒体资源 ID 通常有时效性(具体以文档说明为准,一般在数小时到数天之间)。如果需要复用同一段语音(如固定话术),建议在有效期内缓存 mediaId,过期后重新上传,而不是每次都上传同一个文件。

4. 账号风控问题

虽然 iPad 协议在风控上比 Web 协议安全得多,但大规模群发语音消息仍然需要注意节奏控制。建议:

5. 错误码速查

ret 值含义处理建议
200成功正常处理返回数据
400参数错误检查请求体字段是否完整、格式是否正确
401鉴权失败检查 VideosApi-token 是否正确且未过期
403权限不足确认当前套餐是否包含语音消息发送权限
410设备离线登录控制台确认设备在线状态,必要时重新扫码
429请求频率超限降低调用频率,加入请求间隔控制
500服务端异常稍后重试,持续出现可提交工单

小结

微信发送语音消息接口的核心链路并不复杂:格式转换(MP3→SILK)→ 上传获取 mediaId → 调用发送接口。难点在于 SILK 格式的正确生成、duration 参数的精确传递,以及在业务层做好幂等和频率控制。

基于 iPad 协议的 WechatApi 平台提供了完整的个人微信语音消息发送能力,云端托管无需真机,支持多账号并发,是目前个人微信自动化场景中稳定性较高的选择。如需试用,可访问 WechatApi 控制台 注册,详细接口文档见 post.wechatapi.net

想动手试试?

WechatApi 提供扫码登录、消息收发、好友与群管理等 REST 接口,注册后几分钟跑通。

立即免费注册查看开发文档

相关产品页

🔗 个人微信API(产品页)🔗 微信二次开发(产品页)🔗 微信机器人开发(产品页)

相关文章

微信API接口返回失败/收不到消息?完整排查清单微信 API 怎么对接?Python 发出第一条消息实战Node.js 微信机器人开发教程(发消息 + 收回调)个人微信API能力清单:消息/好友/群/朋友圈接口一览
© 2025 WechatApi · 企业级微信智能机器人接入平台
官网价格帮助文档博客
苏ICP备2024128799号 · 苏ICP备2023038368号