Monday, April 6, 2009

Adding speech to your web page

demo is here: http://www.slowseattle.com/samvoice.aspx

I was up last night and am preparing for interviews. I find the best way to brush up on technologies is to write something fun... I've been interested in the .NET Speech API, but hadn't played with it. I decided that I wanted a way for the page to dynamic speak with the end user. So, I looked around and coded up this .ashx handler.

The front-end code is simple enough. On your web page, use an Ajax call to dynamically create a Windows Media Player object, recreating the url every time with the querystring sending up what you want to tell the service. In this case, I just have the service send back the audio of the text that is in the querystring. You could, of course, capture the querystring, intelligently parse the request and then, say whatever you want. 

I'm using the 5.1 version of the SAPI. 



The js looks something like this:



if((document.getElementById)
{document.getElementById('mediaplayer').innerHTML =
'<object id="Player" type="application/x-ms-wmp"
width="300" height="200">'

'<param name="URL" value="" txt="'">
'"/></object>;'


And here is the code for the web service:




using System;
using System.Collections;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;

using System.Speech.Synthesis;

namespace WebApplication1
{
    ///
    /// Summary description for $codebehindclassname$
    ///
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Sound : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            System.Threading.Thread t = new System.Threading.Thread(Sound.SpeechThread);
            t.Start(HttpContext.Current);
            while (t.IsAlive)
            {
                System.Threading.Thread.Sleep(1);
            }

            HttpContext.Current.Response.ContentType = "audio/x-msdownload";
        }

        public static void SpeechThread(object context)
        {
            HttpContext c = (HttpContext)context;
            string sound = c.Request.QueryString["txt"].ToString();

            using (SpeechSynthesizer synth = new SpeechSynthesizer())
            {
                using (System.IO.MemoryStream spMemStream = new System.IO.MemoryStream())
                {
                    synth.SetOutputToWaveStream(spMemStream);
                    synth.SelectVoiceByHints(VoiceGender.Female, VoiceAge.Child);
                    synth.Speak(sound);
                    spMemStream.WriteTo(c.Response.OutputStream);
                }
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

---------

A demo of this can be seen at http://www.slowseattle.com/samvoice.aspx

1 comment:

  1. Updated: This may not work in your browser because of Windows Media Player peculiarities. I spent a few hours trying to fix this, but if I mess with this any longer, I'll just cutover to a Flash player. I promise it works though. ;-)

    ReplyDelete