MrZyb Always in fear of one's own ignorance

科大讯飞语音合成

  • 将文字信息转化为声音信息,给应用配上“嘴巴”。

  • 接入示例: 其中 TTS_APP_ID 为你在科大讯飞添加服务后获得的APPID, TTS_API_KEY 为你在科大讯飞添加服务后获得的APIKey, TTS_API_URL 为请求语音在线合成的api接口地址(http://api.xfyun.cn/v1/service/v1/tts), TTS_SAVE_PATH 为你服务器下的一个可读写的目录,用来保存合成的语音文件。

function ttsOnline($text, $aue='lame', $volume="50") {
    if (in_array($aue, ['raw', 'lame']) === false) return false;
    $paramArr = [
        "aue" => $aue,
        "pitch" => "50",
        "speed" => "50",
        "volume" => $volume,
        "text_type" => "text",
        "engine_type" => "intp65",
        "voice_name" => "xiaoyan",
        "auf" => "audio/L16;rate=16000",
    ];
    $paramJson = json_encode($paramArr, JSON_UNESCAPED_SLASHES);
    $paramString = base64_encode($paramJson);
    $curTime = time();
    $checkSum = md5(TTS_API_KEY . $curTime . $paramString);
    $header = [
        'X-Appid:' . TTS_APP_ID,
        'X-CurTime:' . $curTime,
        'X-Param:' . $paramString,
        'X-CheckSum:' . $checkSum,
        'Content-Type:' . 'application/x-www-form-urlencoded; charset=utf-8',
    ];
    $text = utf8_encode(urlencode($text));
    $body = 'text=' . $text;
    $res = curl(TTS_API_URL, $header, $body);
    if ($res) {
        $resArr = json_decode($res, true);
        if (json_last_error() === JSON_ERROR_NONE) {
            saveLog($res);
            return false;
        } else {
            $saveFilePath = TTS_SAVE_PATH . date('Ymd');
            if (!is_dir($saveFilePath)) {
                mkdir($saveFilePath);
                chmod($saveFilePath, 0775);
            }
            if ($aue == 'raw') {
                $saveFileTo = $saveFilePath . DS . mt_rand(10000000, 99999999) . '.wav';
            } else {
                $saveFileTo = $saveFilePath . DS . mt_rand(10000000, 99999999) . '.mp3';
            }
            $ret = file_put_contents($saveFileTo, $res);
            if ($ret === false) {
                saveLog('save audio file failed:path'.$saveFileTo);
                return false;
            } else {
                $url = 'https://www.zzzyb.top' . $saveFileTo;
                return ['code' => 1, 'url' => $url];
            }
        }
    } else {
        return false;
    }
}

function curl($url,$header=null, $data=null){
    // 初始化curl
    $curl = curl_init();

    // 设置curl传输选项
    if(isset($header) && !empty($header)){
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    }

    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_URL, $url);

    if (!empty($data)){// post方式
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    }

    $output = curl_exec($curl);
    curl_close($curl);
    return $output;
}

在合成成功时接口会返回

header:
    Content-Type:audio/mpeg
    Connection:keep-alive
    Cache-Control:no-cache
    sid:hts0000bb3f@ch3d5c059d83b3477200
body:
    音频数据(二进制数组)

而合成失败的情况下接口会返回

header:
    Content-Type:text/plain
body:
    {
        "code": "10106",
        "desc": "invalid parameter|invalid speed",
        "data": "",
        "sid": "hts0000bb3f@ch3d5c059d83b3477200"
    }

这里我是使用判断内容时候为json来判断是否合成成功的,理论上应该改成判断header的内容更加合理。

传送门:

0.002418s