最近接到一个任务,要求使用python进行语音合成,实现班级点名的功能。后来使用了pyttsx库,发现这个库合成的语音听起来不清晰,于是果断抛弃。然后就想起了使用腾讯的语音合成api,发现腾讯优图的语音合成还是比较清晰的。本来腾讯ai开放平台的api使用起来不难,但就是计算 “sign” 这个签名时有些不好理解。这里只对这个签名的算法进行讲解。
官方提供的介绍如下:
下面分步介绍:
# 在执行这一步时首先要保证parms里的所有必须参数(sign除外)都已经完整
# 我的params如下:
params = {
'app_id' : self.APP_ID,
'time_stamp' : time_stamp,
'nonce_str' : nonce_str,
'text' : self.TEXT,
'model_type' : self.model_type, # 语音 0~2。0:女。1:女英文。2:男
'speed' : self.speed, # 语速 -2:0.6,-1:0.8, 0:正常, 1:1.2倍,2:1.5倍
};
# 其中的time_stamp和nonce_str需要实时计算。方法如下:
time_stamp = int(time.time()); # 获得时间戳(秒级),防止请求重放
nonce_str = ''.join(random.sample(string.ascii_letters + string.digits, 10)); # 获得随机字符串,保证签名不被预测。
"""将<key, value>请求参数对按key进行字典升序排序,得到有序的参数对列表N
将列表N中的参数对按URL键值对的格式拼接成字符串,得到字符串T(如:key1=value1&key2=value2),URL键值拼接过程value部分需要URL编码,URL编码算法用大写字母,例如%E8,而不是小写%e8"""
# 获得sign对应的值
before_sign = '';
# 对key排序拼接
for key in sorted(params):
before_sign += f'{key}={quote(str(params[key]).encode("utf8"))}&';
# 将应用秘钥以app_key为键名,拼接到before_sign的末尾
before_sign += f"app_key={self.APP_KEY}";
# 对获得的before_sign进行MD5加密(结果大写),得到借口请求签名
sign = hashlib.md5(before_sign.encode("utf-8")).hexdigest().upper();
# 将请求签名添加进参数字典
params["sign"] = sign;
最后附上完整代码:
# 获得时间戳(秒级),防止请求重放
time_stamp = int(time.time());
# 获得随机字符串,保证签名不被预测
nonce_str = ''.join(random.sample(string.ascii_letters + string.digits, 10))
# 组合参数(缺少sign,其值要根据以下获得)
params = {
'app_id' : self.APP_ID,
'time_stamp' : time_stamp,
'nonce_str' : nonce_str,
'text' : self.TEXT,
'model_type' : self.model_type, # 语音 0~2。0:女。1:女英文。2:男
'speed' : self.speed, # 语速 -2:0.6,-1:0.8, 0:正常, 1:1.2倍,2:1.5倍
};
# 获得sign对应的值
before_sign = '';
# 对key排序拼接
for key in sorted(params):
before_sign += f'{key}={quote(str(params[key]).encode("utf8"))}&';
# 将应用秘钥以app_key为键名,拼接到before_sign的末尾
before_sign += f"app_key={self.APP_KEY}";
# 对获得的before_sign进行MD5加密(结果大写),得到借口请求签名
sign = hashlib.md5(before_sign.encode("utf-8")).hexdigest().upper();
# 将请求签名添加进参数字典
params["sign"] = sign;