基于C#实现文字转语音功能

 更新时间:2025年02月07日 11:03:07   作者:Strawberry_ahh  
这篇文章将在C#中集成一个语音对象SpeechSynthesizer,可以根据填入的文字内容自动解析成语音并使用系统扬声器进行语音播报,感兴趣的小伙伴可以了解下

好多年前自己研究的了,今天突然翻出来了,记录下

简单说明

在C#中,集成了一个语音对象SpeechSynthesizer。

SpeechSynthesizer可以根据填入的文字内容自动解析成语音并使用系统扬声器进行语音播报。

程序说明

支持手动输入文字,转换为语音。

可以调整语速。

对kv、sf6、.等关键词进行转义(kv-千伏;sf6-六氟化硫;.-点)

支持生成语音文件(这个没有对关键字进行转义)

效果图

语音试听实现

        /// <summary>
        /// 试听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnListen_Click(object sender, EventArgs e)
        {
            string text = textBox1.Text;
            rate = this.cbxRate.SelectedIndex;

            if (text.Trim().Length == 0)
            {
                MessageBox.Show("不能阅读空内容!", "错误提示");
                return;
            }

            if (btnListen.Text == "语音试听")
            {
                speech = new SpeechSynthesizer();
                new Thread(Speak).Start();
                btnListen.Text = "停止试听";
            }
            else if (btnListen.Text == "停止试听")
            {
                speech.SpeakAsyncCancelAll();//停止阅读
                btnListen.Text = "语音试听";
            }
        }

        private void Speak()
        {
            PromptBuilder builder = GetBuiltPrompt(this.textBox1.Text.ToString().Trim());
            speech.Rate = rate;
            speech.SelectVoice("Microsoft Huihui Desktop");//设置播音员(中文)
            speech.Volume = value;
            speech.SpeakAsync(builder);//语音阅读方法
            speech.SpeakCompleted += speech_SpeakCompleted;//绑定事件
        }
        
        private PromptBuilder GetBuiltPrompt(string keywords)
        {
            //from http://msdn.microsoft.com/msdnmag/issues/06/01/speechinWindowsVista/ 
            //This prompt is quite complicated
            //So I'm going to build it first, and then render it.
            PromptBuilder myPrompt = new PromptBuilder();

            //Start the main speaking style
            PromptStyle mainStyle = new PromptStyle();
            mainStyle.Rate = PromptRate.NotSet;
            mainStyle.Volume = PromptVolume.Medium;
            // mainStyle.Emphasis=PromptEmphasis.Reduced;
            myPrompt.StartStyle(mainStyle);
            convert(myPrompt, keywords);
            myPrompt.EndStyle();
            return myPrompt;
        }

 		/// <summary>
        /// 转义关键字
        /// </summary>
        private void convert(PromptBuilder myPrompt, string keywords)
        {
            //判断是否存在要转换的关键字
            Dictionary<int, string> convertCharacter = new Dictionary<int, string>();
            var kv_Index = keywords.IndexOf("kV");
            var sf6_Index = keywords.IndexOf("SF6");
            var point_index = keywords.IndexOf(".");
            if (kv_Index > -1)
            {
                convertCharacter.Add(kv_Index, "kv");
            }
            if (sf6_Index > -1)
            {
                convertCharacter.Add(sf6_Index, "sf6");
            }
            if (point_index > -1)
            {
                convertCharacter.Add(point_index, ".");
            }
            convertArray(convertCharacter, myPrompt, keywords);
        }
        
		/// <summary>
        /// 转义关键字
        /// </summary>
        private void convertArray(Dictionary<int, string> convertCharacter, PromptBuilder myPrompt, string deviceName)
        { 
            string r = @"[0-9]+";
            Regex reg = new Regex(r, RegexOptions.IgnoreCase | RegexOptions.Singleline);//2秒后超时
            MatchCollection mc = reg.Matches(deviceName);//设定要查找的字符串 

            //按关键字升序排列
            convertCharacter = convertCharacter.OrderBy(t => t.Key).ToDictionary(p => p.Key, o => o.Value);
            int hasLen = 0;//记录已经截取的长度
            int splitNum = convertCharacter.Count;//要拆分的段数

            //针对有需要转换的地方做特殊处理
            if (splitNum > 0)
            {
                for (var i = 0; i < splitNum; i++)
                {
                    var startIndex = convertCharacter.ElementAt(i).Key;//关键字开始的索引
                    var keyValue = convertCharacter.ElementAt(i).Value.ToLower();//关键字
                    var keyLen = keyValue.Length;//关键字对应的长度 

                    //先把关键字前面的追加到标题
                    myPrompt.AppendText(deviceName.Substring(hasLen, startIndex - hasLen)); 
                    hasLen = startIndex + keyLen;//留做截取不是关键字的长度 
                    //判断关键字的类型,确定转换方式
                    if (keyValue == "kv")
                    {
                        myPrompt.AppendSsmlMarkup("<say-as interpret-as = \"kV\">千伏</say-as>");
                    }
                    else if (keyValue == "sf6")
                    {
                        myPrompt.AppendTextWithAlias("SF6", "六氟化硫");
                    }
                    else if (keyValue == "-")
                    {
                        myPrompt.AppendTextWithHint("-", SayAs.NumberCardinal);
                    }
                    else if (keyValue == ".")
                    {
                        myPrompt.AppendTextWithAlias(".", "点");
                    }  
                    //如果循环到最后一个关键字,再把最后一个关键字后边的数追加上
                    if (i == splitNum - 1)
                    {
                        myPrompt.AppendText(deviceName.Substring(hasLen));
                    }
                } 
            }
            else
            {
                myPrompt.AppendText(deviceName);
            }
        }

  		/// <summary>
        /// 语音阅读完成触发此事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void speech_SpeakCompleted(object sender, SpeakCompletedEventArgs e)
        {
            //改变按钮文本值
            ChangeBtnText changeBtnText = ChangeText;
            this.btnListen.BeginInvoke(changeBtnText);
        }
        
        /// <summary>
        /// 委托方法,改变按钮值
        /// </summary>
        public void ChangeText()
        {
            btnListen.Text = "语音试听";
        }

以上就是基于C#实现文字转语音功能的详细内容,更多关于C#文字转语音的资料请关注脚本之家其它相关文章!

相关文章

  • C#使用List类实现动态变长数组的方法

    C#使用List类实现动态变长数组的方法

    这篇文章主要介绍了C#使用List类实现动态变长数组的方法,涉及C#中List类的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-04-04
  • C#调用js库的方法示例代码

    C#调用js库的方法示例代码

    这篇文章主要介绍了C#调用js库的方法,本文结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • C#仿QQ实现简单的截图功能

    C#仿QQ实现简单的截图功能

    这篇文章主要为大家详细介绍了如何利用C#语言模拟QQ实现屏幕选择区域截图功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-08-08
  • C#中DataSet、DataTable、DataRow数据的复制方法

    C#中DataSet、DataTable、DataRow数据的复制方法

    这篇文章介绍了C#中DataSet、DataTable、DataRow数据的复制方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • C#实现日期时间的格式化输出的示例详解

    C#实现日期时间的格式化输出的示例详解

    这篇文章主要为大家详细介绍了C#实现日期时间的格式化输出的相关资料,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2023-03-03
  • C# 基于NPOI操作Excel

    C# 基于NPOI操作Excel

    最近遇到一个数据导入的需求,语言是.net framework 4.7的C#。但是,这次主要探讨NPOI的体验,原则就是向前兼容。所以采用.xls的支持。下面就来看看实现步骤
    2021-06-06
  • c#窗体传值用法实例详解

    c#窗体传值用法实例详解

    这篇文章主要介绍了c#窗体传值用法,以实例形式较为详细的分析了C#窗体传值的各种常用技巧,需要的朋友可以参考下
    2015-06-06
  • C#完成word文档打印的方法

    C#完成word文档打印的方法

    在日常工作中,我们可能常常需要打印各种文件资料,比如word文档。对于编程员,应用程序中文档的打印是一项非常重要的功能,也一直是一个非常复杂的工。这篇文章主要介绍了C#完成word文档打印的方法,需要的朋友可以参考下
    2016-10-10
  • C#中AS和IS关键字的用法

    C#中AS和IS关键字的用法

    这篇文章主要介绍了C#中AS和IS关键字的用法的相关资料,需要的朋友可以参考下
    2016-03-03
  • C#中的串口通信SerialPort详解

    C#中的串口通信SerialPort详解

    今天这篇文章带大家学习下C#中的串口通讯。在日常的开发工作中,如果工作内容是CS方向的同学应该很容易接触到串口通讯方面的业务需求。那么也就很容易想到C#中SerialPort类,它就是专门来处理串口通讯相关的
    2022-01-01

最新评论