ThinkPHP 的 think-captcha 仅支持图形验证码,不支持语音生成,因其底层仅依赖 GD 库绘图,无 TTS 或音频处理逻辑;需自行实现语音接口,通过调用云 TTS、本地 espeak 或数字音频拼接生成 MP3,并将验证码字符串存入 Session 供后端验证。
ThinkPHP 本身不提供语音验证码能力,必须靠外部 TTS 服务或本地命令行工具生成音频文件,再由 PHP 输出路径或流。直接调用
类只能出图,不能出声。
为什么不能用 think-captcha 直接生成语音
是纯图形验证码组件,底层依赖 GD 库绘图,所有方法(如
、
)只返回图像响应(
)。它没有音频生成逻辑,也不处理语音合成、文件拼接或 TTS 请求封装。
试图给
传
或类似参数——会静默忽略,仍输出图片
在控制器里调用
验证语音输入?该函数只比对 Session 中的图形码明文,和语音内容无关
混淆点:有些文档把“语音验证码”和“图形验证码+语音播报按钮”混为一谈,后者是前端 JS 播放预录提示音,不是真 TTS
推荐做法:PHP 后端生成语音文件 URL,前端播放
核心思路是绕过
,自己写一个语音生成接口,返回可直接被
加载的 MP3/WAV 路径。有三种落地方式:
调用百度/腾讯云 TTS API
:需注册平台、获取
,POST 到
,注意
参数要
,且必须带
、
等参数,否则返回错误码
本地执行 espeak
:Ubuntu 上
,PHP 中用
,但要注意
用户是否有权限写入
和执行二进制
数字片段拼接(最稳)
:提前录好
~
和
,PHP 用
读取并合并(可用
命令或
库),生成完整语音文件
Session 存什么、前端怎么传、后端怎么验
图形码靠 Session 存原始字符串,语音码也得存——但不能存语音文件内容,而要存**本次生成的验证码数字本身**(比如
),和图形码完全一样。区别只在呈现方式。
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
立即学习
“
PHP免费学习笔记(深入)
”;
生成语音接口时,先用
把数字写入 Session,再调 TTS 或拼接音频
前端提交表单时,用户听到语音后手动输入,把文本值(如
)发到后端
验证逻辑就是:
,不需要任何额外扩展
务必在验证后立即
清除,避免重放
容易被忽略的兼容性与安全细节
语音验证码不是“加个 audio 标签”就完事,几个硬伤常被跳过:
MP3 文件路径必须能被 Web 服务器直接访问(比如放在
下),不能藏在
里;否则前端
会 404
如果用
输出音频流,记得设 header:
,否则浏览器无法识别
验证码数字若含前导零(如
),PHP 默认转成整数会丢掉,必须全程当字符串处理:
或用
别让同一个语音 URL 被反复请求——每次生成都要用
或时间戳命名文件,否则 CDN 或浏览器缓存会导致用户听到旧码
Captchathink-captchaentry()create()Content-Type: image/pngCaptchatype => 'mp3'captcha_check()think-captchaaccess_tokenhttps://tsn.baidu.com/text2audiotexurlencode()volspdsudo apt install espeakexec("espeak -v zh -w /tmp/verify_".uniqid().".mp3 '您的验证码是 3729'")www-data/tmp0.mp39.mp3prompt.mp3file_get_contents()ffmpegphp-ffmpeg3729session('voice_code', $code)input[name="voice_code"]if (session('voice_code') === input('post.voice_code')) { /* 通过 */ }session('voice_code', null)public/voice/app/readfile()header('Content-Type: audio/mpeg');0283(string)rand(1000, 9999)sprintf('%04d', $n)uniqid()