一、创建自己的应用

百度智能云控制台网址:https://console.bce.baidu.com/

1、创建应用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、获取APIKey和SecretKey

在这里插入图片描述

3、Api调试

调试网址:https://console.bce.baidu.com/support/?timestamp=1750317430400#/api?product=AI&project=%E8%AF%AD%E9%9F%B3%E6%8A%80%E6%9C%AF&parent=%E9%89%B4%E6%9D%83%E8%AE%A4%E8%AF%81%E6%9C%BA%E5%88%B6&api=oauth%2F2.0%2Ftoken&method=post
在这里插入图片描述

二、在Unity中进行调用

1、相关参数说明

(1)短文本个性化语音生成相关参数

在这里插入图片描述

(2)长文本个性化语音生成相关参数

在这里插入图片描述

2、完整代码

using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class TTS : MonoBehaviour
{#region 相关参数[Header("鉴权相关参数")][SerializeField] private string apiKey = "LFfK6DTaswy6LLtBqvHO86w0";[SerializeField] private string secretKey = "vj6JmKd7zBylDVGW2WmTNPWl9eKxxZEL";[SerializeField] private string accessToken = null;[Space][Header("长文本语音合成参数设置")][SerializeField] private string format = "mp3-16k"; // 或者 wav[SerializeField] private int voice = 0; // 语音人:0-女,1-男等[SerializeField] private string lang = "zh";[SerializeField] private int speed = 5; // 0~15[SerializeField] private int pitch = 5; // 0~15[SerializeField] private int volume = 5; // 0~15[SerializeField] private int enable_subtitle = 0;[Space][Header("短文本语音合成参数设置")][SerializeField] private string cuid = "240a906f2b88794fd0426442c4136a5a57bf5c01";[SerializeField] private string ctp = "1";[SerializeField] private string lan = "zh";[SerializeField] private string spd = "5";[SerializeField] private string pit = "5";[SerializeField] private string vol = "10";[SerializeField] private string per = "1";[SerializeField] private string aue = "3";[Space][Header("UI界面相关")]public InputField inputFieldText;public Button buttonStartTTS;//开始合成按钮public Button buttonPlay;//播放合成的语音按钮public AudioSource audioSource;//播放音频组件#endregion// Start is called before the first frame updatevoid Start(){//一开始就进行鉴权StartCoroutine(GetAccessToken());//语音合成buttonStartTTS.onClick.AddListener(()=> {StartTTS(inputFieldText.text, audioSource);});//播放语音buttonPlay.onClick.AddListener(() =>{if (audioSource.clip != null){audioSource.Play();}});}/// <summary>/// 长短语音合成方法/// </summary>/// <param name="text">要合成的文本内容</param>/// <param name="audioSource">语音组件</param>public void StartTTS(string text,AudioSource audioSource){if (text.Length<60){print("开始短文本语音合成");//短文本语音合成StartCoroutine(ShortTTS(text, response => {audioSource.clip = response.clip;print("短文本语音合成结束,请播放");}));}else{print("开始长文本语音合成");//长文本语音合成StartCoroutine(LongTTS(text, clip=> { audioSource.clip = clip;print("长文本语音合成结束,请播放");}));}}#region 鉴权相关/// <summary>/// 鉴权方法/// </summary>/// <returns></returns>/// <summary>/// 获取百度 AccessToken(已使用 using 自动释放资源)/// </summary>public IEnumerator GetAccessToken(){string url = "https://aip.baidubce.com/oauth/2.0/token";WWWForm form = new WWWForm();form.AddField("grant_type", "client_credentials");form.AddField("client_id", apiKey);form.AddField("client_secret", secretKey);using (UnityWebRequest request = UnityWebRequest.Post(url, form)){yield return request.SendWebRequest();if (request.result == UnityWebRequest.Result.Success){try{var tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(request.downloadHandler.text);accessToken = tokenResponse.access_token;Debug.Log("✅ 获取语音合成 AccessToken 成功: " + accessToken);}catch (Exception ex){Debug.LogError("❌ 语音合成AccessToken 解析失败: " + ex.Message);}}else{Debug.LogError("❌ 获取 语音合成AccessToken 失败: " + request.error);}}}#endregion#region 短文本语音合成相关/// <summary>/// 请求短文本语音合成(MP3格式)/// </summary>/// <param name="text">需要合成的文本</param>/// <param name="callback">返回结果回调</param>public IEnumerator ShortTTS(string text, Action<TtsResponse> callback){string url = "http://tsn.baidu.com/text2audio";var param = new Dictionary<string, string>{{ "tex", text },{ "tok", accessToken },{ "cuid", cuid},{ "ctp", ctp},{ "lan", lan},{ "spd", spd},{ "pit", pit},{ "vol", vol},{ "per", per},{ "aue", aue} // 固定为 MP3 格式};// 构建请求 URLint i = 0;foreach (var p in param){url += i != 0 ? "&" : "?";url += p.Key + "=" + UnityWebRequest.EscapeURL(p.Value);i++;}using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.MPEG)){//Debug.Log("[TTS] 请求URL: " + www.url);//测试使用yield return www.SendWebRequest();if (www.result != UnityWebRequest.Result.Success){Debug.LogError("[TTS] 请求失败: " + www.error);callback?.Invoke(new TtsResponse{error_index = -1,error_msg = www.error});}else{string type = www.GetResponseHeader("Content-Type");//Debug.Log("[TTS] Content-Type: " + type);//测试使用if (!string.IsNullOrEmpty(type) && type.Contains("audio")){AudioClip clip = DownloadHandlerAudioClip.GetContent(www);callback?.Invoke(new TtsResponse { clip = clip });}else{string errorText = Encoding.UTF8.GetString(www.downloadHandler.data);Debug.LogError("[TTS] 文本响应错误: " + errorText);callback?.Invoke(new TtsResponse{error_index = -2,error_msg = errorText});}}}}/// <summary>/// 返回的语音合成结果/// </summary>public class TtsResponse{public int error_index;public string error_msg;public string sn;public int idx;public bool Success => error_index == 0;public AudioClip clip;}#endregion#region 长文本语音合成相关/// <summary>/// 按顺序执行长语音合成对应的方法/// </summary>/// <param name="text">需要合成的文本</param>/// <param name="callback">回调函数,返回合成的clip</param>/// <returns></returns>IEnumerator LongTTS(String text, Action<AudioClip> callback){string taskId = null;//语音合成任务创建成功返回的id//创建语音合成任务yield return StartCoroutine(CreateTTSTask(text,TaskId => { taskId = TaskId; },errorMsg => { Debug.LogError("❌ 合成失败: " + errorMsg); }));if (taskId != null && accessToken != null){string audioUrl = null;//语音合成任务合成成功返回的语音下载链接//查询语音合成任务yield return StartCoroutine(QueryTTSTaskStatus(accessToken, taskId,AudioAddress => { audioUrl = AudioAddress; },errorMsg => {Debug.LogError("❌ 查询失败:" + errorMsg);}));//下载语音,并赋值给指定的AudioSource组件if (audioUrl != null){yield return StartCoroutine(DownloadAudio(audioUrl, clip =>{if (clip != null){callback?.Invoke(clip);}else{Debug.LogError("下载的音频 Clip 为 null");}}));}}}/// <summary>/// 创建语音合成任务/// </summary>/// <returns>TaskId</returns>public IEnumerator CreateTTSTask(string text, Action<string> onSuccess, Action<string> onError){string url = $"https://aip.baidubce.com/rpc/2.0/tts/v1/create?access_token={accessToken}";var bodyObj = new{text = text,format = format,voice = voice,lang = lang,speed = speed,pitch = pitch,volume = volume,enable_subtitle = enable_subtitle};string jsonBody = JsonConvert.SerializeObject(bodyObj);using (UnityWebRequest request = new UnityWebRequest(url, "POST")){byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonBody);request.uploadHandler = new UploadHandlerRaw(bodyRaw);request.downloadHandler = new DownloadHandlerBuffer();request.SetRequestHeader("Content-Type", "application/json");request.SetRequestHeader("Accept", "application/json");yield return request.SendWebRequest();if (request.result == UnityWebRequest.Result.Success){string responseText = request.downloadHandler.text;Debug.Log("✅ 创建语音任务返回:" + responseText);if (responseText.Contains("task_id")){var response = JsonConvert.DeserializeObject<TTSTaskSuccessResponse>(responseText);onSuccess?.Invoke(response.TaskId);}else if (responseText.Contains("error_code")){var error = JsonConvert.DeserializeObject<TTSTaskErrorResponse>(responseText);onError?.Invoke(error.ErrorMsg);}else{onError?.Invoke("无法识别的返回内容");}}else{Debug.LogError("❌ 网络请求失败:" + request.error);onError?.Invoke(request.error);}}}/// <summary>/// 语音合成任务查询/// </summary>/// <param name="accessToken">accessToken</param>/// <param name="taskId">合成任务id</param>/// <param name="onSuccess">合成成功返回音频链接</param>/// <param name="onError">合成失败返回错误码</param>/// <returns></returns>public IEnumerator QueryTTSTaskStatus(string accessToken, string taskId, Action<string> onSuccess, Action<string> onError){string url = $"https://aip.baidubce.com/rpc/2.0/tts/v1/query?access_token={accessToken}";string jsonBody = JsonConvert.SerializeObject(new { task_ids = new string[] { taskId } });float delaySeconds = 2f;while (true){using (UnityWebRequest request = new UnityWebRequest(url, "POST")){request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(jsonBody));request.downloadHandler = new DownloadHandlerBuffer();request.SetRequestHeader("Content-Type", "application/json");request.SetRequestHeader("Accept", "application/json");yield return request.SendWebRequest();if (request.result == UnityWebRequest.Result.Success){string json = request.downloadHandler.text;var root = JsonConvert.DeserializeObject<TTSQueryResponse>(json);if (root.TasksInfo != null && root.TasksInfo.Count > 0){var task = root.TasksInfo[0];switch (task.TaskStatus){case "Success":if (!string.IsNullOrEmpty(task.TaskResult?.SpeechUrl))onSuccess?.Invoke(task.TaskResult.SpeechUrl);elseonError?.Invoke("合成成功但未返回语音地址");yield break;case "Failure":onError?.Invoke(task.TaskResult?.ErrMsg ?? "未知错误");yield break;case "Running":Debug.Log("🎙 正在合成...");yield return new WaitForSeconds(delaySeconds);continue;default:onError?.Invoke("未知状态:" + task.TaskStatus);yield break;}}else{onError?.Invoke("未找到任务信息");yield break;}}else{onError?.Invoke("网络错误:" + request.error);yield break;}}}}/// <summary>/// 下载音频,并将音频赋给指定的AudioSource/// </summary>/// <param name="url">音频下载链接</param>/// <param name="audioSource">要赋给的音频播放组件</param>/// <returns></returns>public IEnumerator DownloadAudio(string url, Action<AudioClip> onComplete){using (UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.MPEG)){yield return request.SendWebRequest();if (request.result == UnityWebRequest.Result.Success){AudioClip clip = DownloadHandlerAudioClip.GetContent(request);if (clip != null){Debug.Log("✅ 音频合成结束,等待播放");onComplete?.Invoke(clip); // ✅ 返回 clip}else{Debug.LogError("❌ 无法解析音频 Clip");onComplete?.Invoke(null);}}else{Debug.LogError("❌ 下载音频失败:" + request.error);onComplete?.Invoke(null);}}}[Serializable]public class TokenResponse{/// <summary>/// 鉴权返回的数据JSON结构/// </summary>public string access_token;public int expires_in;}[Serializable]public class TTSTaskSuccessResponse{/// <summary>/// 创建语音合成成功返回的数据JSON结构/// </summary>[JsonProperty("log_id")]public long LogId { get; set; }[JsonProperty("task_id")]public string TaskId { get; set; }[JsonProperty("task_status")]public string TaskStatus { get; set; } // "Running"}[Serializable]public class TTSTaskErrorResponse{/// <summary>/// 创建语音合成成功返回的数据JSON结构/// </summary>[JsonProperty("error_code")]public int ErrorCode { get; set; }[JsonProperty("error_msg")]public string ErrorMsg { get; set; }[JsonProperty("log_id")]public long LogId { get; set; }}[Serializable]public class TTSQueryResponse{[JsonProperty("log_id")]public long LogId { get; set; }[JsonProperty("tasks_info")]public List<TTSQueryTaskInfo> TasksInfo { get; set; }}[Serializable]public class TTSQueryTaskInfo{[JsonProperty("task_id")]public string TaskId { get; set; }[JsonProperty("task_status")]public string TaskStatus { get; set; }[JsonProperty("task_result")]public TTSQueryTaskResult TaskResult { get; set; }}[Serializable]public class TTSQueryTaskResult{[JsonProperty("speech_url")]public string SpeechUrl { get; set; }[JsonProperty("err_no")]public int ErrNo { get; set; }[JsonProperty("err_msg")]public string ErrMsg { get; set; }[JsonProperty("sn")]public string Sn { get; set; }}#endregion}

3、最终效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/84941.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/84941.shtml
英文地址,请注明出处:http://en.pswp.cn/web/84941.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

银河麒麟 | ubuntu 搭建属于自己的邮件服务器

目录 遇权不绝就转root 更新系统 安装 Postfix 配置 Postfix 重启 Postfix 安装 Dovecot 配置 Dovecot 编辑 Dovecot 的 IMAP 配置文件 编辑 Dovecot 的用户认证配置文件 编辑 Dovecot 的服务配置文件 重启 Dovecot 安装发送邮箱功能 发送邮件 测试 遇权不绝就转…

嵌入式通信协议框架的四层架构设计与实现

文章目录 一、硬件抽象层&#xff1a;数据收发的基石1.1 设计要点1.2 代码示例 二、协议管理层&#xff1a;智能路由中枢2.1 设计要点2.2 代码示例 三、协议处理层&#xff1a;协议具体实现3.1 设计要求3.2代码示例3.2.1 协议公共定义3.2.2 协议一设计3.2.3 协议二设计 四、应用…

RA信号处理

ra_snr_gui.m 作用&#xff1a;统计不同信噪比下&#xff0c;五种信号的峰值旁瓣比RA和低高频均值比RM&#xff0c;绘制结果&#xff0c;参考图3.11和3.12 DFCW_RA_SNR.m 作用&#xff1a;产生正交离散频率编码信号&#xff0c;并计算峰值旁瓣比RA和低高频均值比 RM LFM_RA_S…

【go的测试】单测之gomock包与gomonkey包

目录 使用gomock包 1. 安装mockgen 2. 定义接口 3. 生成mock文件 4. 在单测中使用mock的函数 5. gomock 包的使用问题 使用gomonkey包 1. mock 一个包函数 2. mock 一个公有成员函数 3. mock 一个私有成员函数 使用gomock包 1. 安装mockgen go get -u github.com/go…

html实现登录与注册功能案例(不写死且只使用js)

目录 案例需求 实现思路 代码参考 login.html register.html 运行效果 升级思路 案例需求 需要一个登录界面和注册页面实现一个较为完整的登录注册功能 1.登录界面没有登录限制需求&#xff08;降低难度&#xff09;&#xff0c;实现基本的登录判断需求&#xff0c;弹窗…

PHP is the best language.

PHP很好写。 众所周知Python很好写&#xff0c;Python 也能开发 Web 应用&#xff0c;但和 PHP 相比&#xff0c;在“直接处理网页”这件事上&#xff0c;PHP 更加贴近底层和原生。 想快速搭建原型或者 B 端后台工具&#xff0c;不妨用 PHP Laravel 来搞&#xff0c;真的很香…

Mybatis-Plus 在 getOne() 的时候要加上 .last(“limit 1“)

1.先写结论: 1.为了确保 SQL 查询只返回一条记录&#xff08;当查询返回多条时会报错->多为代码本身问题&#xff09;。 2.防止数据库执行全表扫描 3.参考网址&#xff1a;问题记录&#xff1a;MyBatis-Plus 中 ServiceImpl 类的 getOne_mybatis_无他&唯手熟尔-2048…

C语言:二分搜索函数

一、二分搜索基本概念 二分搜索&#xff08;Binary Search&#xff09;是一种在有序数组中查找特定元素的高效算法&#xff0c;时间复杂度为O(log n)。 基本特点&#xff1a; 仅适用于有序数组&#xff08;升序或降序&#xff09; 每次比较将搜索范围减半 比线性搜索(O(n))…

[前端AI]LangChain.js 和 Next.js LLM构建——协助博客撰写和总结助手

LangChain.js 和 Next.js LLM 后端应用于协助博客撰写和总结领域是一个非常实用的方向&#xff01;这涉及到理解和处理文本内容&#xff0c;并生成新的、有结构的信息。 根据您之前提供的代码和需求&#xff0c;我们可以在此基础上进行更具针对性的功能规划和技术实现。 博客…

用 GitHub Issues 做任务管理和任务 List,简单好用!

说实话&#xff0c;我平时也是一个人写代码&#xff0c;每次开完会整理任务最麻烦&#xff1a; 一堆事项堆在聊天里、文档里&#xff0c;或者散落在邮件里…… 为了理清这些&#xff0c;我通常会做一份 List&#xff0c;标好优先级&#xff0c;再安排到每日的工作里 虽然这个…

每日算法刷题Day35 6.22:leetcode枚举技巧枚举中间2道题,用时1h

枚举中间 对于三个或者四个变量的问题&#xff0c;枚举中间的变量往往更好算。 为什么&#xff1f;比如问题有三个下标&#xff0c;需要满足 0≤i<j<k<n&#xff0c;对比一下&#xff1a; 枚举 i&#xff0c;后续计算中还需保证 j<k。 枚举 j&#xff0c;那么 i 和…

【教学类-18-06】20250623蒙德里安黑白七款合并WORD(500张、无学号)

背景需要 客户买了蒙德里安黑白格子7种尺寸,但是不需要学号方块,并指定要WORD 设计思路 【教学类-18-05】20241118正方形手工纸(蒙德里安-风格派-红黄蓝黑白)-CSDN博客文章浏览阅读1.3k次,点赞29次,收藏18次。【教学类-18-05】20241118正方形手工纸(蒙德里安-风格派-红…

langchain--(4)

7 Embedding文本向量化 Embedding文本向量化是一种将非结构化文本转化为低维、连续数值向量的技术,旨在通过数学方式捕捉文本的语义、语法或特征信息,从而让机器更高效地处理语言任务。其核心思想源于流形假设(Manifold Hypothesis),即认为高维原始数据(如文本)实际隐含…

DMDRS部署实施手册(ORACLE=》DM)

DMDRS部署实施手册&#xff08;ORACLE》DM&#xff09; 1 同步说明2 DMDRS安装3 数据库准备3.1 源端准备3.1.1 开启归档日志和附加日志3.1.2 关闭回收站3.1.3 创建同步用户 3.2 目标准备3.2.1 创建同步用户 4 DMDRS配置4.1 源端配置4.2 目标配置 5 DMDRS启动5.1 启动源端服务5.…

十(1)作业:sqli-labs重点关卡

参考文章&#xff1a;详细sqli-labs&#xff08;1-65&#xff09;通关讲解-CSDN博客 第1关&#xff1a; 输入 &#xff1a; ?id3 输入 &#xff1a; ?id2 当输入的数字不同&#xff0c;页面的响应也不同&#xff0c;说明&#xff0c;输入的内容被带入到数据库里查询了 输…

Python 爬虫入门 Day 7 - 复盘 + 实战挑战日

Python 第二阶段 - 爬虫入门 &#x1f3af; 本周知识回顾 网络请求与网页结构基础 HTML解析入门&#xff08;使用 BeautifulSoup&#xff09; 实现爬虫多页抓取与翻页逻辑 模拟登录爬虫与 Session 维持 使用 XPath 进行网页解析&#xff08;lxml XPath&#xff09; 反爬虫应对…

WebRTC(七):媒体能力协商

目的 在 WebRTC 中&#xff0c;每个浏览器或终端支持的音视频编解码器、分辨率、码率、帧率等可能不同。媒体能力协商的目的就是&#xff1a; 确保双方能“听得懂”对方发的媒体流&#xff1b;明确谁发送、谁接收、怎么发送&#xff1b;保障连接的互操作性和兼容性。 P2P的基…

可信启动方案设计

安全之安全(security)博客目录导读 目录 一、引言 二、关键数据(Critical Data) 三、度量槽(Measurement Slot) 四、可信启动后端 1、事件日志(Event Log) 2、离散型 TPM(Discrete TPM) 3、RSE(运行时安全引擎) 五、平台接口 平台接口的职责: 1、函数:b…

✨通义万相2.1深度解析:AI视频生成引擎FLF2V-14B全流程指南(命令行参数+模型架构+数据流)

&#x1f31f; 从零详解&#xff1a;如何用AI模型生成视频&#xff1f;命令行、模型结构、数据流全解析&#xff01; 本文通过一个实际案例&#xff0c;详细解析使用AI模型生成视频的整个流程。从命令行参数解读到模型结构&#xff0c;再到数据在模型间的流动&#xff0c;一步步…

在 TypeScript 前端中使用 Umi-Request 调用 Java 接口的完整指南

下面我将详细介绍如何在基于 TypeScript 的前端项目中使用 umi-request 调用 IntelliJ IDEA 中开发的 Java 接口&#xff0c;包括完整的实现方案和代码示例。 整体方案设计 一、Java 后端接口准备 1. 创建 Spring Boot 控制器 // src/main/java/com/example/demo/controller…