1.试用地址
2.开发环境
ASP.NET
3.需求
(1)需要动态将文本转化为语音
(2)实现免费的转换过程
(3)转换成语音后可以直接下载
(4)将语音加载到U3D中试用
3.实现过程
(1)新建ASP.NET空工程
(2)创建TextToSpeechController类,用于生成Wav文件
(3)添加Speech类库
(4)TextToSpeechController类代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SpeechLib;
using System.Speech;
using System.Speech.Synthesis;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace TextToSpeechServer
{
public static class TextToSpeechController
{
public static string GetSavePath(string speechText)
{
//根据录入内容生成唯一文件名
string fileName = Md5(speechText).ToUpper();
fileName += ".wav";
//获取根目录路径
string path = HttpRuntime.AppDomainAppPath.ToString();
//文件夹名称
string DirectoryName = "音频文件";
//音频文件夹路径
string DirectoryPath = path + DirectoryName;
//判断音频文件夹是否存在
if (Directory.Exists(DirectoryPath) == false)
{
Directory.CreateDirectory(path);
}
//wav文件路径
string FilePath = DirectoryPath + "\\" + fileName;
//如果已经有该文件,则直接返回文件名
if (File.Exists(FilePath))
{
return fileName;
}
//否则生成音频文件
else
{
SpeechSynthesizer synth = new SpeechSynthesizer();
synth.Volume = 100;
//设置文件保存位置
synth.SetOutputToWaveFile(FilePath);
//电脑中需要安装Huihui的语音包
synth.SelectVoice("Microsoft Huihui Desktop");//能读中英文
synth.Speak(speechText);
synth.SetOutputToNull();
}
return fileName;
}
/// <summary>
/// MD5加密,主要根据输入的文字来生成唯一的音频文件名
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string Md5(string value)
{
var result = string.Empty;
if (string.IsNullOrEmpty(value)) return result;
using (var md5 = MD5.Create())
{
result = GetMd5Hash(md5, value);
}
return result;
}
/// <summary>
/// MD5生成
/// </summary>
/// <param name="md5Hash"></param>
/// <param name="input"></param>
/// <returns></returns>
static string GetMd5Hash(MD5 md5Hash, string input)
{
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
var sBuilder = new StringBuilder();
foreach (byte t in data)
{
sBuilder.Append(t.ToString("x2"));
}
return sBuilder.ToString();
}
}
}
(5)创建一般处理程序GetAudioStreamHandler.ashx
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace TextToSpeechServer
{
/// <summary>
/// GetAudioStreamHandler 的摘要说明
/// </summary>
public class GetAudioStreamHandler : HttpTaskAsyncHandler
{
/// <summary>
/// 获取音频文件所在路径
/// </summary>
public string ServerRequestAddress = "http://" + HttpContext.Current.Request.Url.Authority + "/音频文件/{0}";
/// <summary>
/// 异步生成音频文件
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override async Task ProcessRequestAsync(HttpContext context)
{
await Task.Run(() =>
{
string speechText = context.Request.Params["SpeechText"].ToString().Trim();
//将|!|!|转换为换行符
speechText = speechText.Replace("|!|!|", "\n");
string fileName = TextToSpeechController.GetSavePath(speechText);
string requestURL = string.Format(ServerRequestAddress, fileName);
//直接打开生成的音频文件
context.Response.Redirect(requestURL);
});
}
}
}
(6)创建前端aspx界面
前端页面代码如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TextToSpeechPage.aspx.cs" Inherits="TextToSpeechServer.TextToSpeechPage" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>文字转语音</title>
</head>
<body background="文字转语音.png" style="background-size:100%,100%;background-repeat:no-repeat;background-attachment:fixed">
<form id="form1" runat="server">
<table style="width:100%">
<tr style="height:100px">
<th>
<label style="font-size:50px;color:white;">文字语音转换器</label>
</th>
</tr>
<tr style="height:600px">
<th>
<%--<textarea style="width:800px;height:500px;margin:100px,100px,100px,100px;font-size:20px"></textarea>--%>
<asp:TextBox ID="ConvertTextBox" runat="server" Height="500px" Width="800px" Font-Size="20px" TextMode="MultiLine"></asp:TextBox>
</th>
</tr>
<tr style="height:100px">
<th>
<%--<button style="font-size:20px;width:150px;height:50px">开始转换</button>--%>
<asp:Button ID="ConvertButton" runat="server" OnClick="ConvertButton_Click" Text="开始转换" style="font-size:20px;width:150px;height:50px"/>
</th>
</tr>
</table>
</form>
</body>
</html>
后端处理程序代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace TextToSpeechServer
{
public partial class TextToSpeechPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
/// <summary>
/// 获取当前部署的服务器IP地址,生成HTTP请求链接
/// </summary>
public string RequestURL = "http://" + HttpContext.Current.Request.Url.Authority + "//GetAudioStreamHandler.ashx?SpeechText={0}";
/// <summary>
/// 生成按钮点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void ConvertButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(ConvertTextBox.Text))
{
ConvertTextBox.Text = "请输入信息";
}
else
{
//替换换行符,纺织报错
string CheckedURL = string.Format(RequestURL, ConvertTextBox.Text).Replace("\n", "|!|!|");
Response.Redirect(CheckedURL);
}
}
}
}
(7)测试、发布、部署到IIS
均为常规操作流程,这里不再详细介绍。
(8)注意事项
1)部署到IIS所在的服务器时,需要确保服务器上已经安装了Speech所需的环境
·安装 Microsoft Speech Platform - Server Runtime
·安装Microsoft Speech Platform - Software Development Kit (SDK)
·安装Microsoft Speech Platform - Server Runtime Languages【语言包,其中包含文本转语音功能包(TTS)和语音识别功能包(SR),这里我们主要用TTS包】
2)部署后无法访问
·使用云产品的需要在控制台配置安全组规则,允许相关端口被其他电脑访问
·在部署的IIS所在文件夹进行权限设置,可参考这里。除了IIS_IUSRS和IUSRS外,还可以设置Everyone用户。
·可能上述设置了还会报错,如下图
这个与IIS中的应用程序池内权限有关
在高级设置中,将“标识”从默认的ApplicationPoolIdentity改为LocalSystem即可。
欲知详情,可点击这里。
【该部分设置private key部分,打开方式是Win+R运行,输入MMC,打开Microsoft管理控制台,但是该方法笔者没试成功~~】
(9)源码
(10)参考文章
·IIS ApplicationPoolIdentity
·利用C#开发web应用程序时,对注册表进行操作提示没有权限的解决办法
·Microsoft Speech Platform 自学笔记2 环境要求与安装过程
(11)补充U3D中下载并播放语音
创建PlayAudioController脚本
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using System.Security.Cryptography;
using System.Text;
public class PlayAudioController : MonoBehaviour
{
/// <summary>
/// 转换文字输入框
/// </summary>
public InputField TextToAudioInputField;
/// <summary>
/// 音频
/// </summary>
public AudioSource audioSource;
/// <summary>
/// 请求地址
/// </summary>
private string RequestURL = "http://39.104.127.80:8082/GetAudioStreamHandler.ashx?SpeechText={0}";
/// <summary>
/// 文件名
/// </summary>
string FileName = "";
/// <summary>
/// 是否在StreamingAssets/AudioFile中存在
/// </summary>
bool alreadyExit = false;
/// <summary>
/// 将Text转化为Speech
/// </summary>
public void ConvertTextToSpeech()
{
if (string.IsNullOrEmpty(TextToAudioInputField.text))
{
return;
}
FileName = Md5(TextToAudioInputField.text).ToUpper() + ".wav";
string FilePath = Application.streamingAssetsPath + "/AudioFile/" + FileName;
alreadyExit = false;
StartCoroutine(GetWavFileAndPlay(FilePath));
}
/// <summary>
/// 从StreamingAssets/AudioFile文件中加载音频文件并播放
/// </summary>
/// <param name="FilePath"></param>
/// <returns></returns>
IEnumerator GetWavFileAndPlay(string FilePath)
{
UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(FilePath, AudioType.WAV);
yield return uwr.SendWebRequest();
if (uwr.isDone)
{
if (uwr.isNetworkError || uwr.isHttpError)
{
alreadyExit = false;
Debug.Log(uwr.error);
}
else
{
AudioClip audioClip = DownloadHandlerAudioClip.GetContent(uwr);
audioSource.clip = audioClip;
audioSource.Play();
alreadyExit = true;
}
}
//判断当前音频文件是否存在
if (!alreadyExit)
{
string text = TextToAudioInputField.text.Replace("\n", "|!|!|");
StartCoroutine(SaveWavFile(text));
}
}
/// <summary>
/// 当StreamingAssets/AudioFile文件夹下不存在指定Wav文件时,下载该音频文件并播放
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
IEnumerator SaveWavFile(string text)
{
UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(string.Format(RequestURL, text),AudioType.WAV);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError || uwr.isHttpError)
{
Debug.Log(uwr.error);
}
else
{
//播放下载的Wav音频
AudioClip audioClip = DownloadHandlerAudioClip.GetContent(uwr);
audioSource.clip = audioClip;
audioSource.Play();
//保存下载的Wav音频文件
byte[] data = uwr.downloadHandler.data;
//这里的FileMode.create是创建这个文件,如果文件名存在则覆盖重新创建
FileStream fs = new FileStream(Application.streamingAssetsPath + "/AudioFile/" + FileName, FileMode.Create);
fs.Write(data, 0, data.Length);
//每次读取文件后都要记得关闭文件
fs.Close();
}
}
/// <summary>
/// MD5加密,主要根据输入的文字来生成唯一的音频文件名
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string Md5(string value)
{
var result = string.Empty;
if (string.IsNullOrEmpty(value)) return result;
using (var md5 = MD5.Create())
{
result = GetMd5Hash(md5, value);
}
return result;
}
/// <summary>
/// MD5生成
/// </summary>
/// <param name="md5Hash"></param>
/// <param name="input"></param>
/// <returns></returns>
static string GetMd5Hash(MD5 md5Hash, string input)
{
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
var sBuilder = new StringBuilder();
foreach (byte t in data)
{
sBuilder.Append(t.ToString("x2"));
}
return sBuilder.ToString();
}
}