800 字
4 分钟
PHP 实现金额语音播报接口
PHP 实现金额语音播报接口
在收银系统、收款提醒、桌面播报等场景中,经常需要将数字金额转为语音播报。本文使用 PHP 编写一套金额语音合成接口,通过拆分数字、匹配对应读音音频,将多段 MP3 按顺序拼接并以流的形式返回,实现完整的语音播报能力。
一、功能简介
- 接收
GET方式传递的金额数字,支持整数、小数格式。 - 严格校验参数格式,非法参数直接返回错误状态码。
- 根据数字位数、单位(个、十、百、千、万、亿、小数点)匹配对应音频文件。
- 自动拼接「叮、到账、金额、元」等多段音频,流式输出 MP3。
- 增加文件存在性检测,音频缺失时返回服务端错误。
- 自带跨域响应头,可直接被前端页面调用。
二、完整接口代码与逻辑说明
新建 PHP 文件,粘贴以下全部代码:
<?php// 允许跨域请求header("Access-Control-Allow-Origin: *");
// 音频文件存放目录(与当前php文件同级的 mp3 文件夹)$voiceDir = __DIR__ . '/mp3/';// 获取 GET 传递的 money 参数$num = trim($_GET['money'] ?? '');
// 正则校验:仅允许纯数字 + 小数格式if (!preg_match('/^\d+(\.\d+)?$/', $num)) { http_response_code(400); exit;}
// 数字读音映射$AA = ["0","1","2","3","4","5","6","7","8","9"];// 数位、小数点读音映射$BB = ["","shi","bai","qian","wan","yi","dian",""];
// 将数字按小数点拆分为 整数部分、小数部分$a = explode(".", $num);// 去除整数部分前面多余的 0$intStr = ltrim($a[0], '0');if ($intStr === '') { $intStr = '0';}
$re = [];
// 处理整数部分为 0 的场景if ($intStr === '0') { $re[] = '0'; // 存在小数部分 if (isset($a[1]) && $a[1] !== '') { $re[] = 'dian'; for ($i = 0; $i < strlen($a[1]); $i++) { $re[] = $AA[(int)$a[1][$i]]; } }} else { $intLen = strlen($intStr); $k = 0;
// 从后往前遍历整数,组合数位与读音 for ($i = $intLen - 1; $i >= 0; $i--) { switch ($k) { case 0: array_unshift($re, $BB[7]); break; case 4: $reg = "/0{4}\d{" . ($intLen - $i - 1) . "}$/"; if (!preg_match($reg, $intStr)) { array_unshift($re, $BB[4]); } break; case 8: array_unshift($re, $BB[5]); $BB[7] = $BB[5]; $k = 0; break; }
// 处理中间零的读音 if ($k % 4 == 2 && isset($intStr[$i+2]) && $intStr[$i+2] != '0' && isset($intStr[$i+1]) && $intStr[$i+1] == '0') { array_unshift($re, $AA[0]); }
$currChar = $intStr[$i]; if ($currChar != '0') { array_unshift($re, $BB[$k % 4]); array_unshift($re, $AA[(int)$currChar]); } $k++; }
// 拼接小数部分读音 if (isset($a[1]) && $a[1] !== '') { $re[] = $BB[6]; for ($i = 0; $i < strlen($a[1]); $i++) { $re[] = $AA[(int)$a[1][$i]]; } }}
// 过滤空值,重新整理数组下标$re = array_values(array_filter($re, fn($v) => $v !== ''));
// 组装完整音频列表:开头音效 + 金额读音 + 结尾单位$fileList = [];$fileList[] = $voiceDir . 'ding.mp3';$fileList[] = $voiceDir . 'daozhang.mp3';
foreach ($re as $val) { $fileList[] = $voiceDir . $val . '.mp3';}
$fileList[] = $voiceDir . 'yuan.mp3';
// 遍历检测所有音频文件是否存在、可读foreach ($fileList as $file) { if (!file_exists($file) || !is_readable($file)) { http_response_code(500); exit; }}
// 设置响应头为音频类型header("Content-Type: audio/mpeg");header("Content-Disposition: inline; filename=alipay.mp3");
// 清空缓冲区,准备流式输出ob_clean();flush();
// 分段读取音频并输出,实现无缝播放foreach ($fileList as $file) { $handle = fopen($file, 'rb'); while (!feof($handle)) { echo fread($handle, 8192); flush(); } fclose($handle);}
exit;?>具体MP3文件可进QQ群516128569见群文件