C# 语音合成(TTS)示例 - 使用微软Speech库
C#语音合成(TTS)示例,使用微软的System.Speech库实现文本转语音功能。包含基本语音合成、语音设置、事件处理和异步操作。
准备工作
1. 添加必要的引用
在Visual Studio项目中,需要添加对System.Speech的引用:
- 右键点击项目 -> 添加 -> 引用
- 在"程序集"中找到并选择
System.Speech - 或者通过NuGet安装:
Install-Package System.Speech
2. 引入命名空间
using System.Speech.Synthesis;
using System.Globalization;
完整示例代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Speech.Synthesis;
using System.Globalization;
namespace TextToSpeechExample
{
public partial class MainForm : Form
{
private SpeechSynthesizer synthesizer;
private bool isSpeaking = false;
public MainForm()
{
InitializeComponent();
InitializeSynthesizer();
LoadAvailableVoices();
}
// 初始化语音合成器
private void InitializeSynthesizer()
{
synthesizer = new SpeechSynthesizer();
// 设置事件处理
synthesizer.SpeakStarted += Synthesizer_SpeakStarted;
synthesizer.SpeakCompleted += Synthesizer_SpeakCompleted;
synthesizer.SpeakProgress += Synthesizer_SpeakProgress;
synthesizer.StateChanged += Synthesizer_StateChanged;
}
// 加载可用的语音
private void LoadAvailableVoices()
{
cmbVoices.Items.Clear();
// 获取所有已安装的语音
foreach (InstalledVoice voice in synthesizer.GetInstalledVoices())
{
VoiceInfo info = voice.VoiceInfo;
cmbVoices.Items.Add($"{info.Name} - {info.Culture.Name}");
}
if (cmbVoices.Items.Count > 0)
{
cmbVoices.SelectedIndex = 0;
}
}
// 开始说话事件
private void Synthesizer_SpeakStarted(object sender, SpeakStartedEventArgs e)
{
isSpeaking = true;
UpdateUIState();
}
// 说话完成事件
private void Synthesizer_SpeakCompleted(object sender, SpeakCompletedEventArgs e)
{
isSpeaking = false;
UpdateUIState();
}
// 说话进度事件
private void Synthesizer_SpeakProgress(object sender, SpeakProgressEventArgs e)
{
// 更新进度条(如果需要)
if (txtContent.Text.Length > 0)
{
int progress = (int)((double)e.CharacterPosition / txtContent.Text.Length * 100);
progressBar.Value = Math.Min(progress, 100);
}
}
// 状态改变事件
private void Synthesizer_StateChanged(object sender, StateChangedEventArgs e)
{
lblStatus.Text = $"状态: {e.State}";
}
// 更新UI状态
private void UpdateUIState()
{
btnSpeak.Enabled = !isSpeaking && !string.IsNullOrEmpty(txtContent.Text);
btnPause.Enabled = isSpeaking;
btnResume.Enabled = synthesizer.State == SynthesizerState.Paused;
btnStop.Enabled = isSpeaking;
}
// 开始说话按钮点击事件
private void btnSpeak_Click(object sender, EventArgs e)
{
SpeakText();
}
// 暂停按钮点击事件
private void btnPause_Click(object sender, EventArgs e)
{
if (synthesizer.State == SynthesizerState.Speaking)
{
synthesizer.Pause();
btnPause.Enabled = false;
btnResume.Enabled = true;
}
}
// 恢复按钮点击事件
private void btnResume_Click(object sender, EventArgs e)
{
if (synthesizer.State == SynthesizerState.Paused)
{
synthesizer.Resume();
btnPause.Enabled = true;
btnResume.Enabled = false;
}
}
// 停止按钮点击事件
private void btnStop_Click(object sender, EventArgs e)
{
synthesizer.SpeakAsyncCancelAll();
isSpeaking = false;
UpdateUIState();
}
// 说话方法
private void SpeakText()
{
if (string.IsNullOrEmpty(txtContent.Text))
{
MessageBox.Show("请输入要朗读的文本");
return;
}
// 配置语音设置
ConfigureSpeechSettings();
try
{
// 异步朗读文本
synthesizer.SpeakAsync(txtContent.Text);
}
catch (Exception ex)
{
MessageBox.Show($"朗读出错: {ex.Message}");
}
}
// 配置语音设置
private void ConfigureSpeechSettings()
{
// 设置语音
if (cmbVoices.SelectedIndex >= 0)
{
string voiceName = cmbVoices.SelectedItem.ToString().Split('-')[0].Trim();
synthesizer.SelectVoice(voiceName);
}
// 设置语速 (-10 到 10)
synthesizer.Rate = trackBarRate.Value;
// 设置音量 (0 到 100)
synthesizer.Volume = trackBarVolume.Value;
}
// 导出为WAV文件
private void btnExport_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtContent.Text))
{
MessageBox.Show("请输入要导出的文本");
return;
}
SaveFileDialog saveDialog = new SaveFileDialog();
saveDialog.Filter = "WAV文件|*.wav";
saveDialog.Title = "保存语音文件";
if (saveDialog.ShowDialog() == DialogResult.OK)
{
try
{
ConfigureSpeechSettings();
synthesizer.SetOutputToWaveFile(saveDialog.FileName);
synthesizer.Speak(txtContent.Text);
synthesizer.SetOutputToDefaultAudioDevice(); // 恢复默认输出设备
MessageBox.Show("导出成功!");
}
catch (Exception ex)
{
MessageBox.Show($"导出失败: {ex.Message}");
}
}
}
// 窗体关闭事件
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (synthesizer != null)
{
synthesizer.Dispose();
}
}
// 文本变化事件
private void txtContent_TextChanged(object sender, EventArgs e)
{
UpdateUIState();
}
}
}
窗体设计代码 (MainForm.Designer.cs)
namespace TextToSpeechExample
{
partial class MainForm
{
private System.ComponentModel.IContainer components = null;
private TextBox txtContent;
private Button btnSpeak;
private Button btnPause;
private Button btnResume;
private Button btnStop;
private ComboBox cmbVoices;
private Label label1;
private Label label2;
private Label label3;
private TrackBar trackBarRate;
private TrackBar trackBarVolume;
private Label label4;
private Label label5;
private ProgressBar progressBar;
private Label lblStatus;
private Button btnExport;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.txtContent = new System.Windows.Forms.TextBox();
this.btnSpeak = new System.Windows.Forms.Button();
this.btnPause = new System.Windows.Forms.Button();
this.btnResume = new System.Windows.Forms.Button();
this.btnStop = new System.Windows.Forms.Button();
this.cmbVoices = new System.Windows.Forms.ComboBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.trackBarRate = new System.Windows.Forms.TrackBar();
this.trackBarVolume = new System.Windows.Forms.TrackBar();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.progressBar = new System.Windows.Forms.ProgressBar();
this.lblStatus = new System.Windows.Forms.Label();
this.btnExport = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.trackBarRate)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).BeginInit();
this.SuspendLayout();
// txtContent
this.txtContent.Location = new System.Drawing.Point(12, 29);
this.txtContent.Multiline = true;
this.txtContent.Name = "txtContent";
this.txtContent.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtContent.Size = new System.Drawing.Size(560, 150);
this.txtContent.TabIndex = 0;
this.txtContent.TextChanged += new System.EventHandler(this.txtContent_TextChanged);
// btnSpeak
this.btnSpeak.Location = new System.Drawing.Point(12, 185);
this.btnSpeak.Name = "btnSpeak";
this.btnSpeak.Size = new System.Drawing.Size(75, 23);
this.btnSpeak.TabIndex = 1;
this.btnSpeak.Text = "开始朗读";
this.btnSpeak.UseVisualStyleBackColor = true;
this.btnSpeak.Click += new System.EventHandler(this.btnSpeak_Click);
// btnPause
this.btnPause.Location = new System.Drawing.Point(93, 185);
this.btnPause.Name = "btnPause";
this.btnPause.Size = new System.Drawing.Size(75, 23);
this.btnPause.TabIndex = 2;
this.btnPause.Text = "暂停";
this.btnPause.UseVisualStyleBackColor = true;
this.btnPause.Click += new System.EventHandler(this.btnPause_Click);
// btnResume
this.btnResume.Location = new System.Drawing.Point(174, 185);
this.btnResume.Name = "btnResume";
this.btnResume.Size = new System.Drawing.Size(75, 23);
this.btnResume.TabIndex = 3;
this.btnResume.Text = "继续";
this.btnResume.UseVisualStyleBackColor = true;
this.btnResume.Click += new System.EventHandler(this.btnResume_Click);
// btnStop
this.btnStop.Location = new System.Drawing.Point(255, 185);
this.btnStop.Name = "btnStop";
this.btnStop.Size = new System.Drawing.Size(75, 23);
this.btnStop.TabIndex = 4;
this.btnStop.Text = "停止";
this.btnStop.UseVisualStyleBackColor = true;
this.btnStop.Click += new System.EventHandler(this.btnStop_Click);
// cmbVoices
this.cmbVoices.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbVoices.FormattingEnabled = true;
this.cmbVoices.Location = new System.Drawing.Point(60, 214);
this.cmbVoices.Name = "cmbVoices";
this.cmbVoices.Size = new System.Drawing.Size(270, 21);
this.cmbVoices.TabIndex = 5;
// label1
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 217);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(43, 13);
this.label1.TabIndex = 6;
this.label1.Text = "语音:";
// label2
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(12, 13);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(67, 13);
this.label2.TabIndex = 7;
this.label2.Text = "输入文本:";
// label3
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 247);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(43, 13);
this.label3.TabIndex = 8;
this.label3.Text = "语速:";
// trackBarRate
this.trackBarRate.Location = new System.Drawing.Point(60, 241);
this.trackBarRate.Minimum = -10;
this.trackBarRate.Maximum = 10;
this.trackBarRate.Name = "trackBarRate";
this.trackBarRate.Size = new System.Drawing.Size(270, 45);
this.trackBarRate.TabIndex = 9;
this.trackBarRate.TickFrequency = 2;
// trackBarVolume
this.trackBarVolume.Location = new System.Drawing.Point(60, 292);
this.trackBarVolume.Maximum = 100;
this.trackBarVolume.Name = "trackBarVolume";
this.trackBarVolume.Size = new System.Drawing.Size(270, 45);
this.trackBarVolume.TabIndex = 10;
this.trackBarVolume.TickFrequency = 10;
this.trackBarVolume.Value = 100;
// label4
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(12, 298);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(43, 13);
this.label4.TabIndex = 11;
this.label4.Text = "音量:";
// label5
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(336, 247);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(31, 13);
this.label5.TabIndex = 12;
this.label5.Text = "慢速";
// progressBar
this.progressBar.Location = new System.Drawing.Point(12, 343);
this.progressBar.Name = "progressBar";
this.progressBar.Size = new System.Drawing.Size(560, 23);
this.progressBar.TabIndex = 14;
// lblStatus
this.lblStatus.AutoSize = true;
this.lblStatus.Location = new System.Drawing.Point(12, 369);
this.lblStatus.Name = "lblStatus";
this.lblStatus.Size = new System.Drawing.Size(46, 13);
this.lblStatus.TabIndex = 15;
this.lblStatus.Text = "状态: ";
// btnExport
this.btnExport.Location = new System.Drawing.Point(336, 185);
this.btnExport.Name = "btnExport";
this.btnExport.Size = new System.Drawing.Size(75, 23);
this.btnExport.TabIndex = 16;
this.btnExport.Text = "导出WAV";
this.btnExport.UseVisualStyleBackColor = true;
this.btnExport.Click += new System.EventHandler(this.btnExport_Click);
// MainForm
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(584, 391);
this.Controls.Add(this.btnExport);
this.Controls.Add(this.lblStatus);
this.Controls.Add(this.progressBar);
this.Controls.Add(this.label5);
this.Controls.Add(this.label4);
this.Controls.Add(this.trackBarVolume);
this.Controls.Add(this.trackBarRate);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.cmbVoices);
this.Controls.Add(this.btnStop);
this.Controls.Add(this.btnResume);
this.Controls.Add(this.btnPause);
this.Controls.Add(this.btnSpeak);
this.Controls.Add(this.txtContent);
this.Name = "MainForm";
this.Text = "文本转语音(TTS)示例";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
((System.ComponentModel.ISupportInitialize)(this.trackBarRate)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
}
}
高级功能扩展
1. 使用SSML(语音合成标记语言)
SSML允许更精细地控制语音输出:
private void SpeakWithSSML()
{
string ssml = @"
<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis' xml:lang='zh-CN'>
<voice name='Microsoft Huihui Desktop'>
<prosody rate='fast' volume='loud'>
这是一段使用SSML控制的语音。
</prosody>
<break time='500ms'/>
<prosody pitch='high' rate='slow'>
现在语速变慢,音调变高。
</prosody>
</voice>
</speak>";
synthesizer.SpeakSsml(ssml);
}
2. 使用Windows.Media.SpeechSynthesis (UWP/WPF)
对于UWP或WPF应用程序,可以使用更现代的API:
using Windows.Media.SpeechSynthesis;
using Windows.Storage.Streams;
// 在UWP/WPF中的异步语音合成
private async Task SpeakTextAsync(string text)
{
using (var speechSynthesizer = new SpeechSynthesizer())
{
// 选择语音
var voices = SpeechSynthesizer.AllVoices;
var selectedVoice = voices.FirstOrDefault(v => v.Gender == VoiceGender.Female && v.Language == "zh-CN");
if (selectedVoice != null)
{
speechSynthesizer.Voice = selectedVoice;
}
// 生成语音流
SpeechSynthesisStream stream = await speechSynthesizer.SynthesizeTextToStreamAsync(text);
// 播放语音
MediaElement mediaElement = new MediaElement();
mediaElement.SetSource(stream, stream.ContentType);
mediaElement.Play();
}
}
3. 语音提示和通知
// 简单的语音提示
public static void SpeakNotification(string message)
{
using (var synth = new SpeechSynthesizer())
{
synth.Volume = 80;
synth.Rate = 1;
synth.SpeakAsync(message);
}
}
// 使用不同的语音和语调
public static void SpeakWithEmotion(string message, string emotion = "normal")
{
using (var synth = new SpeechSynthesizer())
{
// 根据情绪调整语音设置
switch (emotion.ToLower())
{
case "excited":
synth.Rate = 2;
synth.Volume = 100;
break;
case "calm":
synth.Rate = -1;
synth.Volume = 70;
break;
case "emphasis":
synth.Rate = 0;
synth.Volume = 100;
break;
default:
synth.Rate = 0;
synth.Volume = 80;
break;
}
synth.SpeakAsync(message);
}
}
参考项目 C# 语音合成例子源码(TTS微软库) www.3dddown.com/cna/57531.html
注意
-
语音可用性:不同的Windows版本和语言包可能安装不同的语音。中文语音可能需要额外安装语言包。
-
异步处理:
SpeakAsync方法是非阻塞的,适合在UI应用程序中使用。如果需要等待语音完成,可以使用Speak方法(会阻塞当前线程)。 -
资源管理:确保正确释放
SpeechSynthesizer对象,特别是在长时间运行的应用程序中。 -
异常处理:语音合成可能因为各种原因失败(如没有可用的语音),应该添加适当的异常处理。
-
性能考虑:对于大量文本,考虑使用流式输出或分块处理,以避免内存问题。

浙公网安备 33010602011771号