How to use System.Speech in .NET

Programming, error messages and sample code > ASP.NET
For .NET Framework
 
1. create a new empty "ASP.NET Web Application (.NET Framework)" template in Visual Studio
 
2. right-click the project > Add > Class... > SpeechSynthesizerControl.cs, replace the content with the following
 
using System;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Speech.Synthesis;
using System.Threading;
using System.Web.UI;
using System.Web.UI.HtmlControls;

// !! replace the namespace with your project name !!
namespace texttospeech
{
    [ConstructorNeedsTag(false)]
    public class SpeechSynthesizerControl : HtmlGenericControl, ICallbackEventHandler
    {
        private readonly System.Speech.Synthesis.SpeechSynthesizer synth = new System.Speech.Synthesis.SpeechSynthesizer();

        public SpeechSynthesizerControl() : base("audio")
        {
            this.Age = VoiceAge.NotSet;
            this.Gender = VoiceGender.NotSet;
            this.Culture = CultureInfo.CurrentCulture;
            this.VoiceName = String.Empty;
            this.Ssml = false;
        }

        [DefaultValue("")]
        public String VoiceName { get; set; }

        [DefaultValue(100)]
        public Int32 Volume { get; set; }

        [DefaultValue(0)]
        public Int32 Rate { get; set; }

        [TypeConverter(typeof(CultureInfoConverter))]
        public CultureInfo Culture { get; set; }

        [DefaultValue(VoiceGender.NotSet)]
        public VoiceGender Gender { get; set; }

        [DefaultValue(VoiceAge.NotSet)]
        public VoiceAge Age { get; set; }

        [DefaultValue(false)]
        public Boolean Ssml { get; set; }

        protected override void OnInit(EventArgs e)
        {
            AsyncOperationManager.SynchronizationContext = new SynchronizationContext();

            var sm = ScriptManager.GetCurrent(this.Page);
            var reference = this.Page.ClientScript.GetCallbackEventReference(this, "text", String.Format("function(result){{ document.getElementById('{0}').src = result; document.getElementById('{0}').play(); }}", this.ClientID), String.Empty, true);
            var script = String.Format("\ndocument.getElementById('{0}').speak = function(text){{ {1} }};\n", this.ClientID, reference);

            if (sm != null)
            {
                this.Page.ClientScript.RegisterStartupScript(this.GetType(), String.Concat("speak", this.ClientID), String.Format("Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function() {{ {0} }});\n", script), true);
            }
            else
            {
                this.Page.ClientScript.RegisterStartupScript(this.GetType(), String.Concat("speak", this.ClientID), script, true);
            }

            base.OnInit(e);
        }

        protected override void OnPreRender(EventArgs e)
        {
            this.Attributes.Remove("class");
            this.Attributes.Remove("src");
            this.Attributes.Remove("preload");
            this.Attributes.Remove("loop");
            this.Attributes.Remove("autoplay");
            this.Attributes.Remove("controls");

            this.Style[HtmlTextWriterStyle.Display] = "none";
            this.Style[HtmlTextWriterStyle.Visibility] = "hidden";

            base.OnPreRender(e);
        }

        public override void Dispose()
        {
            this.synth.Dispose();

            base.Dispose();
        }

        String ICallbackEventHandler.GetCallbackResult()
        {
            using (var stream = new MemoryStream())
            {
                this.synth.Rate = this.Rate;
                this.synth.Volume = this.Volume;
                this.synth.SetOutputToWaveStream(stream);

                if (String.IsNullOrWhiteSpace(this.VoiceName) == false)
                {
                    this.synth.SelectVoice(this.VoiceName);
                }
                else
                {
                    this.synth.SelectVoiceByHints(this.Gender, this.Age, 0, this.Culture);
                }

                if (this.Ssml == false)
                {
                    this.synth.Speak(this.Context.Items["data"] as String);
                }
                else
                {
                    this.synth.SpeakSsml(this.Context.Items["data"] as String);
                }

                return (String.Concat("data:audio/wav;base64,", Convert.ToBase64String(stream.ToArray())));
            }
        }

        void ICallbackEventHandler.RaiseCallbackEvent(String eventArgument)
        {
            this.Context.Items["data"] = eventArgument;
        }
    }
}
3. right-click the project > Add > Web Form > Default.aspx (Default.aspx.cs)
 
 Default.aspx
 
<%-- !! replace the inherits with your project name !! --%>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="texttospeech.Default" %>
<%-- !! replace the assembly and namespace with your project name !! --%>
<%@ Register Assembly="texttospeech" Namespace="texttospeech" tagPrefix="web" %>
<%@ Register Assembly="System.Speech, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Speech" TagPrefix="web" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script>

        function onSpeak(text) {
            document.getElementById('synthesizer').speak(text);
        }

    </script>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <web:SpeechSynthesizerControl runat="server" ID="synthesizer" Age="Adult" Gender="Male" Culture="en-US" Rate="0" Volume="100" />
	    <input type="text" id="text" name="text"/>
	    <input type="button" value="Speak" onclick="onSpeak(this.form.text.value)"/>
        </div>
    </form>
</body>
</html>

 
leave the Default.aspx.cs as the default one.
 
4. build the project and run, enter the text and then click the "speak" button
 
text to speach
 
 
 
 
For .NET Core
 
1. create a new ASP.NET Core Web App template in Visual Studio
 
2. right-click the project > Manage NuGet Packages... > Browse > search "System.Speech" > install
 
3. replace the content of "Index.cshtml" with the following
 
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<form method="post">
    <input asp-for="@Model.Text" />
    <button type="submit">speak</button>

    <audio controls="controls" src="@Model.AudioSource" autoplay></audio>
</form>
replace the content of "Index.cshtml.cs" with the following
 
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Speech.Synthesis;

// !! replace the namespace with your project name !!
namespace WebApplication1.Pages
{
    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;

        public IndexModel(ILogger<IndexModel> logger)
        {
            _logger = logger;
        }

        [BindProperty]
        public string? Text { get; set; }

        public string? AudioSource { get; set; }

        public void OnGet()
        {

        }

        public IActionResult OnPostAsync()
        {
            if (!string.IsNullOrWhiteSpace(Text))
            {
                using (var synth = new SpeechSynthesizer())
                {
                    using (var stream = new MemoryStream())
                    {
                        synth.SetOutputToWaveStream(stream);

                        synth.Speak(Text);

                        AudioSource = $"data:audio/wav;base64,{Convert.ToBase64String(stream.ToArray())}";
                    }
                }
            }

            return Page();
        }
    }
}
4. build the project and run, enter the text and then click the "speak" button
 
text to speach