我不会Unity,但是看到b站一位大佬做的虚拟恋人,于是想做一下伸手党。
大佬视频:
【chatGPT+unity+Azure+VRoid】AI女友对话,源码分享,零基础手搓二次元妹子,打造专属的AI女友不是梦_哔哩哔哩_bilibili
语音合成部分,大佬已经集成了很多百度云语音api,但是因为本人很菜,设备也不太好,所以用本地大模型感觉暂时有点困难(之后想继续学习)不过百度云语音的声音有点难听,所以想接入Minimax(也就是星野的母公司,我是星野的重度用户),所以参照着大佬写的百度云语音的api试着自己写了一下调用minimax的接口。
但是Minimax返回的是json, audio是一个hex编码的mp3文件,和百度格式不同,所以还需要将返回结果解码,以及将mp3转化成AudioClip。
Minimax语音生成模型T2A v2的文档:
MiniMax-与用户共创智能
url:
string _url = "https://api.minimax.chat/v1/t2a_v2?GroupId="+你的group_id;
headers:
var headers = new Dictionary()
{
{ "accept", "application/json, text/plain, */*" },
{ "content-type", "application/json" },
{ "authorization", "Bearer " + 你的api_key }
};
group_id在账户管理-账户信息中
api_key在账户管理-接口密钥中
voice_setting: 声音设置
var voice_setting = new Dictionary()
{
{ "voice_id", SetSpeeker(m_Post_Setting.per) },
{ "speed", m_Post_Setting.speed },
{ "vol", m_Post_Setting.volume },
{ "pitch", m_Post_Setting.pitch }
};
请求体:
var postData = new Dictionary()
{
{ "model", SetModel(m_Post_Setting.model) },
{ "text", _msg },
{ "voice_setting", voice_setting },
{ "pronunciation_dict", new Dictionary> {
{ "tone", new List { "处理/(chu3)(li3)", "危险/dangerous" } }
}},
{ "audio_setting", new Dictionary()
{
{ "audio_sample_rate", 32000 },
{ "bitrate", 128000 },
{ "format", "mp3" },
{ "channel", 1 }
}
}
};
发送请求:
UnityWebRequest request = new UnityWebRequest(_url, "POST");
foreach (var header in headers)
{
request.SetRequestHeader(header.Key, header.Value);
}
// 使用 Newtonsoft.Json 序列化
string jsonPayload = JsonConvert.SerializeObject(postData);
// 设置请求体
byte[] jsonToSend = Encoding.UTF8.GetBytes(jsonPayload);
request.uploadHandler = new UploadHandlerRaw(jsonToSend);
request.downloadHandler = new DownloadHandlerBuffer();
UnityEngine.Debug.Log("Request Data: " + jsonPayload);
// 发送请求并等待响应
yield return request.SendWebRequest();
检查请求是否成功
// 检查请求是否成功
if (request.result == UnityWebRequest.Result.Success){
其他逻辑
}
获取回复内容:
string responseText = request.downloadHandler.text;
Dictionary data = JsonConvert.DeserializeObject>(responseText);
JObject jsonResponse = JObject.Parse(responseText);
回复示例:
Minimax给的回复是一个Json, 音频在"audio"中,是一个hex编码的audio。
{
"data": {
"audio": "hex编码的audio",
"status": 2,
},
"extra_info": {
"audio_length": 5746,
"audio_sample_rate": 32000,
"audio_size": 100845,
"audio_bitrate": 128000,
"word_count": 300,
"invisible_character_ratio": 0,
"audio_format": "mp3",
"usage_characters": 630
},
"trace_id": "01b8bf9bb7433cc75c18eee6cfa8fe21",
"base_resp": {
"status_code": 0,
"status_msg": ""
}
}
获取audio:
if (data.ContainsKey("data"))
{
var dataObj = data["data"];
string audioHex = jsonDataObj["audio"]?.ToString();
}elseP{
//报错
}
刚刚获取的audio是一个hex编码的audio,因此将其解码成一个byte[]
byte[] decodedHex = ConvertHexToByte(audioHex);
解码方法:
private byte[] ConvertHexToByte(string strText)
{
strText = strText.Replace(" ", "");
byte[] bText = new byte[strText.Length / 2];
for (int i = 0; i < strText.Length / 2; i++)
{
bText[i] = Convert.ToByte(Convert.ToInt32(strText.Substring(i * 2, 2), 16));
}
return bText;
}
解码完成后保存为mp3文件
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string fileName = 保存地址+timestamp+".mp3";
File.WriteAllBytes(fileName, decodedHex);
mp3文件不能在Unity中直接播放,将其转化为一个AudioClip,并播放。
// 使用 UnityWebRequest 下载音频文件
UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip("file://" + fileName, AudioType.MPEG);
yield return uwr.SendWebRequest(); // 等待音频文件下载完成
if (uwr.result != UnityWebRequest.Result.Success)
{
UnityEngine.Debug.LogError("Error downloading audio clip: " + uwr.error);
}else {
// 获取 AudioClip
AudioClip audioClip = DownloadHandlerAudioClip.GetContent(uwr);
//播放,播放逻辑在回掉函数中,此处省略
_callback(audioClip, _msg);
}