I realize this is an old question but here is an answer anyway.
This is from Microsoft and is their demo SimpleTTS.html It only runs in iExplorer and you will have to enable activeX under Tools, Internet options, Security.
The viseme images are simply little mouth images selected according to the viseme change events to make it look like the mouth is talking. Microsoft no longer has this code on MSDN as far as I can tell. Tooo bad.
You can massage this to do what you want it to do. Good luck.
<!--
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>TTS Demo</title>
<script language="JavaScript">
var VoiceObj = new ActiveXObject("Sapi.SpVoice");
function ChangeVoice() {
var i = parseInt( idsVoices.value );
VoiceObj.Voice = VoiceObj.GetVoices().Item(i);
}
function ChangeAudioOutput() {
var i = parseInt( idsAudioOutputs.value );
VoiceObj.AudioOutput = VoiceObj.GetAudioOutputs().Item(i);
}
function IncRate() {
if( VoiceObj.Rate < 10 )
{
VoiceObj.Rate = VoiceObj.Rate + 1;
}
}
function DecRate() {
if( VoiceObj.Rate > -10 )
{
VoiceObj.Rate = VoiceObj.Rate - 1;
}
}
function IncVol() {
if( VoiceObj.Volume < 100 )
{
VoiceObj.Volume = VoiceObj.Volume + 10;
}
}
function DecVol() {
if( VoiceObj.Volume > 9 )
{
VoiceObj.Volume = VoiceObj.Volume - 10;
}
}
function SpeakText() {
if( idbSpeakText.value == "SpeakText" )
{
try
{
VoiceObj.Speak( idTextBox.value, 1 );
}
catch(exception)
{
alert("Speak error");
}
}
else if( idbSpeakText.value == "Stop" )
{
VoiceObj.Speak( "", 2 );
}
}
</script>
<script for="window" event="OnQuit()" language="JavaScript">
delete VoiceObj;
</script>
</meta></head>
<body>
<h1 align="center">Simple TTS (DHTML)</h1>
<h1 align="center"><font size="3"> </font>
<img alt="" border="2" hspace="0" id="idImage" src="mouthclo.bmp"> </img></h1>
<h1 align="center">
<textarea id="idTextBox" cols="50" rows="10" wrap="VIRTUAL">Enter text you wish spoken here</textarea>
</h1>
<p align="center">
Rate
<input id="idbIncRate" name="button1" type="button" onclick="IncRate()" value=" + "></input>
<input id="idbDecRate" name="button2" type="button" onclick="DecRate()" value=" - " style="LEFT: 237px; TOP: 292px"> </input>
Volume
<input id="idbIncVol" name="button3" onclick="IncVol()" style="LEFT: 67px; TOP: 318px" type="button" value=" + ">
<input id="idbDecVol" name="button4" onclick="DecVol()" type="button" value=" - " style="LEFT: 134px; TOP: 377px">
</input></input></p>
<p align="center"><button id="idbSpeakText" onclick="SpeakText();">
style="HEIGHT: 24px; LEFT: 363px; TOP: 332px; WIDTH: 178px">SpeakText</button></p>
<p align="center">Voice
Audio Output </p>
<p align="center">
<select id="idsVoices" name="Voices" onchange="ChangeVoice()" style="FONT-FAMILY: serif; HEIGHT: 21px; WIDTH: 179px"> </select>
<select id="idsAudioOutputs" name="AudioOutputs" onchange="ChangeAudioOutput()" style="HEIGHT: 22px; WIDTH: 179px"> </select>
<script language="JavaScript">
InitializeControls();
function InitializeControls()
{
var VoicesToken = VoiceObj.GetVoices();
var AudioOutputsToken = VoiceObj.GetAudioOutputs();
for( var i=0; i<voicestoken.count;> {
var oOption = document.createElement("OPTION");
idsVoices.options.add(oOption);
oOption.innerText = VoicesToken.Item(i).GetDescription();
oOption.value = i;
}
for( var i=0; i<audiooutputstoken.count;> {
var oOption = document.createElement("OPTION");
idsAudioOutputs.options.add(oOption);
oOption.innerText = AudioOutputsToken.Item(i).GetDescription();
oOption.value = i;
}
}
function VoiceObj::StartStream() {
idbSpeakText.value = "Stop";
}
function VoiceObj::EndStream() {
idbSpeakText.value = "SpeakText";
idImage.src = "mouthclo.bmp";
}
function VoiceObj::Viseme(StreamNum, StreamPos, Duration, VisemeType, Feature, VisemeId) {
if( VisemeId == 15 || VisemeId == 17 || VisemeId == 18 || VisemeId ==21 )
{
idImage.src = "mouthop1.bmp";
}
else if( VisemeId == 14 || VisemeId == 16 || VisemeId == 19 || VisemeId == 20 )
{
idImage.src = "mouthop2.bmp";
}
else if( VisemeId == 4 || VisemeId == 6 || VisemeId == 9 || VisemeId == 12 )
{
idImage.src = "mouthop3.bmp";
}
else if( VisemeId == 1 || VisemeId == 2 || VisemeId == 3 || VisemeId == 11 )
{
idImage.src = "mouthop4.bmp";
}
else if( VisemeId == 7 || VisemeId == 8 )
{
idImage.src = "mouthnar.bmp";
}
else if( VisemeId == 5 || VisemeId == 10 || VisemeId == 13 )
{
idImage.src = "mouthmed.bmp";
}
else
{
idImage.src = "mouthclo.bmp";
}
}
</script>
<hr></hr>
<p></p>
</p></body>
</html>