Highlight the spoken word

Your code doesn’t work, but i just wrote an example that works the way you want. Open the fiddle to see it working

var utterance = new SpeechSynthesisUtterance();
var wordIndex = 0;
var global_words = [];
utterance.lang = 'en-UK';
utterance.rate = 1;


document.getElementById('playbtn').onclick = function(){
    var text    = document.getElementById('textarea').value;
    var words   = text.split(" ");
    global_words = words;
    // Draw the text in a div
    drawTextInPanel(words);
    spokenTextArray = words;
    utterance.text = text;
    speechSynthesis.speak(utterance);
};

utterance.onboundary = function(event){
    var e = document.getElementById('textarea');
    var word = getWordAt(e.value,event.charIndex);
    // Show Speaking word : x
    document.getElementById("word").innerHTML = word;
    //Increase index of span to highlight
    console.info(global_words[wordIndex]);

    try{
        document.getElementById("word_span_"+wordIndex).style.color = "blue";
    }catch(e){}

    wordIndex++;
};

utterance.onend = function(){
        document.getElementById("word").innerHTML = "";
    wordIndex = 0;
    document.getElementById("panel").innerHTML = "";
};

// Get the word of a string given the string and the index
function getWordAt(str, pos) {
    // Perform type conversions.
    str = String(str);
    pos = Number(pos) >>> 0;

    // Search for the word's beginning and end.
    var left = str.slice(0, pos + 1).search(/S+$/),
        right = str.slice(pos).search(/s/);

    // The last word in the string is a special case.
    if (right < 0) {
        return str.slice(left);
    }
    // Return the word, using the located bounds to extract it from the string.
    return str.slice(left, right + pos);
}

function drawTextInPanel(words_array){
console.log("Dibujado");
        var panel = document.getElementById("panel");
    for(var i = 0;i < words_array.length;i++){
        var html = '<span id="word_span_'+i+'">'+words_array[i]+'</span>&nbsp;';
        panel.innerHTML += html;
    }
}

Please play with the following fiddle :

Highlight spoken word SpeechSynthesis Javascript fiddle

It highlight the spoken word in div with blue, you can customize it with bold style, but the important is the idea.

Note: remember that the onboundary event is only triggered for the native (local) voice synthesis. Changing the voice as specified in the Google Examples (i.e Google UK English Male) for a google remote voice, will make your code fail as the SpeechSynthesis API seems to only play a sound generated by the google servers.

Using a speech engine to highlight words is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Display a piece of text and produce spoken output via a speech engine.

As each word is being spoken, highlight the word on the display.

In languages where cursor control and highlighting are not possible, it is permissible to output each word as it is spoken.

Related task
  •   speech synthesis

AutoHotkey[edit]

We use the simple SAPI.SPVoice COM Object and a parsing loop.
The highlighting is done with EM_SETSEL and Notepad. Rather crude, but it works. Due to the simplistic nature of the parsing loop, the text ends with a space.

SetTitleMatchMode 2
EM_SETSEL := 0x00B1

Run notepad,,,pid
WinWaitActive ahk_pid %pid%
ControlSetText, Edit1, % text := "AutoHotkey was the first to implement this task! ", ahk_pid %pid%

pVoice := ComObjCreate("Sapi.spvoice"), i := 1 ; the spvoice COM Object ships with the OS

; parse the text
While lf := SubStr(text, i, 1)
{
   If lf = %A_Space%
   {
      SendMessage, EM_SetSel, % i-StrLen(word)-1, % i-1, Edit1, ahk_pid %pid%
      pVoice.speak(word), word := "", i++
   }
   Else word .= lf, i++
}

FreeBASIC[edit]

FreeBASIC does not have a native command for them.

We are going to invoke vbscript directly

''This works on Windows. Does anyone know how it would be done in Linux?

Sub Speak(Texto As String)
    Shell "mshta vbscript:Execute(""CreateObject(""""SAPI.SpVoice"""").Speak("""""+Texto+""""")(window.close)"")"
End Sub

Function Split(Texto As String, SplitL As String, Direcc As Byte = 0) As String
    Dim As Integer LocA = Instr(Texto, SplitL)
    Return Iif(Direcc <= 0, Left(Texto, LocA), Right(Texto, Len(Texto) - LocA))
End Function

Dim As String texto = "Actions speak louder than words"
Dim As String palabra()
Dim As Integer cont = -1
Do
    cont += 1
    Redim Preserve palabra(cont)
    palabra(cont) = Split(texto," ")
    texto = Right(texto, Len(texto)-Len(palabra(cont)))
    If Len(palabra(cont)) = 0 Then palabra(cont) = texto : Exit Do
Loop

For n As Integer = 0 To Ubound(palabra)
    Print palabra(n)
    Speak palabra(n)
Next n

Go[edit]

This uses the eSpeak speech synthesizer which is invoked for each word in the text. As the word is spoken it is printed to the terminal in capitalized form (and the previous word is uncapitalized). After a second’s delay the final word is uncapitalized.

Very robotic but it works.

package main

import (
    "fmt"
    "log"
    "os/exec"
    "strings"
    "time"
)

func main() {
    s := "Actions speak louder than words."
    prev := ""
    prevLen := 0
    bs := ""
    for _, word := range strings.Fields(s) {
        cmd := exec.Command("espeak", word)
        if err := cmd.Run(); err != nil {
            log.Fatal(err)
        }
        if prevLen > 0 {
            bs = strings.Repeat("b", prevLen)
        }
        fmt.Printf("%s%s%s ", bs, prev, strings.ToUpper(word))
        prev = word + " "
        prevLen = len(word) + 1
    }
    bs = strings.Repeat("b", prevLen)
    time.Sleep(time.Second)
    fmt.Printf("%s%sn", bs, prev)
}

Julia[edit]

Translation of: Go

function speak(sentence, cmd = "/utl/espeak.bat")
    for word in split(sentence)
        s = replace(lowercase(word), r"[^a-z]" => "")
        if length(s) > 0
            print(uppercase(s))
            run(`$cmd $s`)
            sleep(1)
            print("b"^length(s))
        end
        print(word, " ")
    end
end

speak("Are those 144 shy Eurasian footwear, cowboy chaps, or jolly earthmoving headgear?")

M2000 Interpreter[edit]

Module UsingEvents {
      Form 60, 32
      Cls 5, 0
      Pen 14
      Declare WithEvents sp "SAPI.SpVoice"
      That$="Rosetta Code is a programming chrestomathy site"
      margin=(width-Len(That$))/2
      EndStream=False
      \ this function called as sub routine - same scope as Module
      \ we can call it from event function too
      Function Localtxt {
            \ move the cursor to middle line
            Cursor 0, height/2
            \ using OVER the line erased with background color and then print text over
            \ ordinary Print using transparent printing of text
            \ $(0) set mode to non proportional text, @() move the cursor to sepecific position
            Print Over $(0),@(margin), That$
      }
      Call Local LocalTxt()
      Function sp_Word {
            Read New StreamNumber, StreamPosition, CharacterPosition, Length
            Call Local LocalTxt()
            Cursor 0, height/2
            Pen 15 {Print Part $(0), @(CharacterPosition+margin); Mid$(That$, CharacterPosition+1, Length)}
            Refresh
      }
      Function sp_EndStream {
            Refresh
            EndStream=True
      }
      Const  SVEEndInputStream = 4
      Const  SVEWordBoundary = 32
      Const SVSFlagsAsync = 1&
 
      With sp, "EventInterests", SVEWordBoundary+SVEEndInputStream
      Method sp, "Speak", That$, SVSFlagsAsync
      While Not EndStream {Wait 10}
      Call Local LocalTxt()
}
UsingEvents

Mathematica/Wolfram Language[edit]

DynamicModule[{text = "This is some text.", words, i = 0}, 
 Panel@Column@{Dynamic[
     Row[Riffle[
       If[i != 0, MapAt[Style[#, Red] &, #, i], #] &@(words = 
          StringSplit@text), " "]]], InputField[Dynamic@text, String],
     Button["Speak", 
     While[i < Length@words, i++; FinishDynamic[]; Speak[words[[i]]]; 
      Pause[Max[0.7, 0.12 StringLength[words[[i]]]]]]; i = 0]}]

Nim[edit]

Translation of: Go

Works on Linux but may also work on other platforms provided «espeak» is installed.

import os, osproc, strutils

const S = "Actions speak louder than words."

var prev, bs = ""
var prevlen = 0

for word in S.splitWhitespace():
  discard execProcess("espeak " & word)
  if prevlen > 0:
    bs = repeat('b', prevlen)
  stdout.write bs, prev, word.toUpper, ' '
  stdout.flushFile()
  prev = word & ' '
  prevlen = word.len + 1

bs = repeat('b', prevlen)
sleep(1000)
echo bs, prev

Phix[edit]

You can run this online here.

--
-- demorosettaSpeech.exw
-- =======================
--
with javascript_semantics
requires(6) -- WINDOWS or JS, not LINUX
requires(32) -- Windows 32 bit only, for now... 
-- (^ runs fine on a 64-bit OS, but needs a 32-bit p.exe)
requires("1.0.2")
include builtinsspeak.e -- (new in 1.0.2)

include pGUI.e
Ihandle t3, left, red, right, btn, hbc, dlg

-- not sure why, but a leading space really helps...
constant text = ` Highlight words as they are spoken.`

procedure speech_cb(integer pos, len)
    if pos<0 then pos += length(text)+1 end if
    IupSetStrAttribute(left,"TITLE",text[1..pos])
    IupSetStrAttribute(red,"TITLE",text[pos+1..pos+len])
    IupSetStrAttribute(right,"TITLE",text[pos+len+1..$])
    IupSetAttributes({left,red,right}, "RASTERSIZE=x0")
    IupRefresh(t3)
    IupRedraw(t3)
end procedure

function button_cb(Ihandle /*ih*/)
    atom rate = iff(platform()=WINDOWS?-5: -- -10..+10, voice dependent
                iff(platform()=JS?0.3:      -- 0.1..10, 0.5 = half speed
                                  9/0))      -- linux, anyone?...
    speak(text,rate,speech_cb)
    return IUP_CONTINUE
end function

procedure main()
    IupOpen()
    left = IupLabel()
    red = IupLabel("",`FGCOLOR="255 0 0"`)
    right = IupLabel(text)
    t3 = IupHbox({IupFill(),left,red,right,IupFill()},
                 `FONT="Verdana, 18", MARGIN=0x20`)
    btn = IupButton("Speak",Icallback("button_cb"))
    hbc = IupHbox({IupFill(),btn,IupFill()},"MARGIN=0x10")
    dlg = IupDialog(IupVbox({t3,hbc}),"TITLE=Speak")
    IupShow(dlg)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()

Raku[edit]

Translation of: Go

# 20200826 Raku programming solution

my s = "Actions speak louder than words.";
my prev = $ = "";
my prevLen = $ = 0;
my bs = $ = "";

for s.split(' ', :skip-empty) {
   run "/usr/bin/espeak", $_ or die;
   bs = "b" x prevLen if prevLen > 0;
   printf "%s%s%s ", bs, prev, $_.uc;
   prev = "$_ ";
   prevLen = $_.chars + 1
}

printf "%s%sn", "b" x prevLen, prev;

REXX[edit]

Programming note:   This REXX program uses a freeware program   NIRCMD   to interface with the Microsoft Windows speech synthesizer program   SAM,   a text to speech using a male voice.   SAM can possibly be configured to use other voices with later releases of Windows.   More recent Microsoft Windows have another speech synthesizer program:   ANNA.

Each word of the text is highlighted (by showing the word in uppercase).   the terminal screen is cleared before showing the text that is being spoken;   the repeated calls to the (Windows) speech engine makes for a slower speech rate.

/*REXX program uses a command line interface to invoke Windows SAM for speech synthesis.*/
parse arg t                                      /*get the (optional) text from the C.L.*/
#= words(t)
if #==0  then exit                               /*Nothing to say?    Then exit program.*/
dq= '"'                                          /*needed to enclose text in dbl quotes.*/
rate= 1                                          /*talk:   -10 (slow)   to   10 (fast). */
                                                 /* [↓]  where the rubber meets the road*/
   do j=1  for #
   x= word(t, j);          upper x               /*extract 1 word, capitalize it for HL.*/
   if j==1  then LHS=                            /*obtain text before the spoken word.  */
            else LHS= subword(t, 1, j-1)
   if j==#  then RHS=                            /*obtain text  after the spoken word.  */
            else RHS= subword(t, j+1)
   'CLS'                                         /*use this command to clear the screen.*/
   say 'speaking: '   space(LHS  x  RHS)         /*show text,  one word is capitalized. */
   oneWord= dq  x  dq                            /*surround a word in double quotes (").*/
   'NIRCMD'  "speak text"    oneWord     rate    /*NIRCMD  invokes Microsoft's Sam voice*/
   end   /*j*/                                   /*stick a fork in it,  we're all done. */

Note:   The name of the above REXX program is   SPEAKHI.REX

usage   using the command:

speakhi This is an example of speech synthesis. 

Ring[edit]

load "guilib.ring"

MyApp = New qApp {

        win1 = new qWidget() {

                setwindowtitle("Hello World")
                setGeometry(100,100,370,250)

                Text = "Welcome to the Ring Programming Language"
                Text = split(Text," ")

                label1 = new qLabel(win1) {
                        settext("What is your name ?")
                        setGeometry(10,20,350,30)
                        setalignment(Qt_AlignHCenter)
                }

                btn1 = new qpushbutton(win1) {
                        setGeometry(10,200,100,30)
                        settext("Say Hello")
                        setclickevent("pHello()")
                }

                btn2 = new qpushbutton(win1) {
                        setGeometry(150,200,100,30)
                        settext("Close")
                        setclickevent("pClose()")
                }

                lineedit1 = new qlineedit(win1) {
                        setGeometry(10,100,350,30)
                }

                voice = new QTextToSpeech(win1) {                        
                }
                show()
        }
        exec()}

Func pHello
     lineedit1.settext( "Hello " + lineedit1.text())
     for n = 1 to len(Text)
         voice.Say(Text[n])
         see Text[n] + nl
     next

Func pClose
     MyApp.quit()
Welcome
to
the
Ring
Programming
Language

Ruby[edit]

I’m having difficulty figuring out how to get Shoes to update the GUI (like Tk’s update command), so the user must click the button once for each word.

Uses the Ruby code from Speech synthesis

load 'speechsynthesis.rb'

if ARGV.length == 1
  $text = "This is default text for the highlight and speak program"
else
  $text = ARGV[1..-1].join(" ")
end
$words = $text.split

Shoes.app do
  @idx = 0

  stack do
    @sentence = para(strong($words[0] + " "), $words[1..-1].map {|word| span(word + " ")})
    button "Say word" do
      say_and_highlight
    end
  end

  keypress do |key|
    case key
    when :control_q, "x11" then exit
    end
  end

  def say_and_highlight
    speak $words[@idx]
    @idx = (@idx + 1) % $words.length
    @sentence.replace($words.each_with_index.map {|word, idx| idx == @idx ? strong(word + " ") : span(word + " ")})
  end
end

Tcl[edit]

This code uses the external /usr/bin/say program (known available on Mac OS X) as its interface to the speech engine; this produces rather stilted speech because it forces the text to be spoken one word at a time instead of as a whole sentence (in order to keep the highlighting synchronized).

package require Tcl 8.5
package require Tk 8.5
proc say {text button} {
    grab $button
    $button configure -state disabled -cursor watch
    update
    set starts [$text search -all -regexp -count lengths {S+} 1.0]
    foreach start $starts length $lengths {
	lappend strings [$text get $start "$start + $length char"]
	lappend ends [$text index "$start + $length char"]
    }
    $text tag remove sel 1.0 end
    foreach from $starts str $strings to $ends {
	$text tag add sel $from $to
	update idletasks
	exec /usr/bin/say << $str
	$text tag remove sel 1.0 end
    }
    grab release $button
    $button configure -state normal -cursor {}
}

pack [text .t]
pack [button .b -text "Speak, computer!" -command {say .t .b}] -fill x
.t insert 1.0 "This is an example of speech synthesis with Tcl/Tk."

Wren[edit]

Translation of: Go

The ability to call external processes such as espeak is expected to be added to Wren-cli in the next release. In the meantime, we embed the following Wren script in a minimal C host (no error checking) to complete this task.

/* speech_engine_highlight_words.wren */

import "./str" for Str

class C {
    foreign static usleep(usec)

    foreign static espeak(s)

    foreign static flushStdout()
}

var s = "Actions speak louder than words."
var prev = ""
var prevLen = 0
var bs = ""
for (word in s.split(" ")) {
    if (prevLen > 0) bs = "b" * prevLen
    System.write("%(bs)%(prev)%(Str.upper(word)) ")
    C.flushStdout()
    C.espeak(word)
    prev= word + " "
    prevLen = word.count + 1
}
bs = "b" * prevLen
C.usleep(1000)
System.print("%(bs)%(prev)")

We now embed this in the following C program, compile and run it.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "wren.h"

void C_usleep(WrenVM* vm) {
    useconds_t usec = (useconds_t)wrenGetSlotDouble(vm, 1);
    usleep(usec);
}

void C_espeak(WrenVM* vm) {
    const char *arg = wrenGetSlotString(vm, 1);
    char command[strlen(arg) + 10];
    strcpy(command, "espeak "");
    strcat(command, arg);
    strcat(command, """);
    system(command);
}

void C_flushStdout(WrenVM* vm) {
    fflush(stdout);
}

WrenForeignMethodFn bindForeignMethod(
    WrenVM* vm,
    const char* module,
    const char* className,
    bool isStatic,
    const char* signature) {
    if (strcmp(module, "main") == 0) {
        if (strcmp(className, "C") == 0) {
            if (isStatic && strcmp(signature, "usleep(_)") == 0)     return C_usleep;
            if (isStatic && strcmp(signature, "espeak(_)") == 0)     return C_espeak;
            if (isStatic && strcmp(signature, "flushStdout()") == 0) return C_flushStdout;
        }
    }
    return NULL;
}

static void writeFn(WrenVM* vm, const char* text) {
    printf("%s", text);
}

char *readFile(const char *fileName) {
    FILE *f = fopen(fileName, "r");
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    rewind(f);
    char *script = malloc(fsize + 1);
    fread(script, 1, fsize, f);
    fclose(f);
    script[fsize] = 0;
    return script;
}

static void loadModuleComplete(WrenVM* vm, const char* module, WrenLoadModuleResult result) {
    if( result.source) free((void*)result.source);
}

WrenLoadModuleResult loadModule(WrenVM* vm, const char* name) {
    WrenLoadModuleResult result = {0};
    if (strcmp(name, "random") != 0 && strcmp(name, "meta") != 0) {
        result.onComplete = loadModuleComplete;
        char fullName[strlen(name) + 6];
        strcpy(fullName, name);
        strcat(fullName, ".wren");
        result.source = readFile(fullName);
    }
    return result;
}

int main(int argc, char **argv) {
    WrenConfiguration config;
    wrenInitConfiguration(&config);
    config.writeFn = &writeFn;
    config.bindForeignMethodFn = &bindForeignMethod;
    config.loadModuleFn = &loadModule;
    WrenVM* vm = wrenNewVM(&config);
    const char* module = "main";
    const char* fileName = "speech_engine_highlight_words.wren";
    char *script = readFile(fileName);
    wrenInterpret(vm, module, script);
    wrenFreeVM(vm);
    free(script);
    return 0;
}

You can hear full pages read aloud with Chromebook’s built-in screen reader. You can hear parts of a page, including specific words, read aloud with Select-to-speak.

Listen to all text

To have pages read aloud to you, turn on your Chromebook’s built-in screen reader:

  1. At the bottom right, select the time.

    • Or press Alt + Shift + s.

  2. Select Settings and then Accessibility.
  3. Under «Text-to-Speech,» turn on ChromeVox.

Tip: When you press Ctrl + Alt + z, you can turn ChromeVox on or off from any page. Learn how to use the built-in screen reader.

Listen to part of a page

To select specific text on a page to be read to you, turn on Select-to-speak.

Step 1: Turn on Select-to-speak

  1. At the bottom right, select the time.
    • Or press Alt + Shift + s.
  2. Select Settings and then Accessibility.
  3. Under «Text-to-Speech,» turn on Select-to-speak.

Step 2: Select & hear text

Important: Depending on your keyboard, you can press the Search key or the Launcher key for some shortcuts. Both keys work the same.

Option 1

  1. Press and hold the Search key .
  2. Drag the pointer over an area of text.

Option 2

  1. Highlight the text to be read.
  2. Press the Search key + s.

Option 3

  1. At the bottom right, near the time, select Select-to-Speak .
  2. Drag the pointer over an area of text.

Tip: If you’re on a touchscreen, tap a line of text or drag your finger over an area of the screen.

Your Chromebook reads the section aloud and each word is highlighted.

To stop Select-to-Speak while it’s reading, press Ctrl or the Search key . You can also select Stop .

Tip: With navigation controls, you can pause and play, adjust speed, and skip lines of text.

Tap here to see an interactive tutorial

Highlight or shade background text

If you are using Select-to-speak, each word will be highlighted as it’s spoken. You can turn off highlighting, change the color of the highlighted words, or shade the screen behind selected text.

  1. At the bottom right, select the time.
    • Or press Alt + Shift + s.
  2. Select Settings and then Accessibility.
  3. Under «Text-to-Speech,» turn on Select-to-speak.
  4. Select Open select-to-speak settings.
  5. Under «Highlighting,» you can:
    • Turn on Highlight each word as it is spoken.
    • Next to «Color for word highlights,» select a color.
      • To get the strongest contrast, you may use green or pink, especially if you use high contrast mode.
    • Turn on Shade background content.
      • This allows you to shade the whole screen, except for the text being spoken.

Disable Select-to-speak navigation features

Important: When “Enable Navigation Controls” is turned off, quick access to pause and play, adjust speed, and skip lines of text is disabled.

  1. At the bottom right, select the time.
    • Or press Alt + Shift + s.
  2. Select Settings and then Accessibility.
  3. Under «Text-to-Speech,» select Open select to speech settings.
  4. Under «Highlighting,» turn off Enable navigation controls.

⚠️ Warning: This is a draft ⚠️

This means it might contain formatting issues,
incorrect code, conceptual problems, or other severe issues.

If you want to help to improve and eventually enable this page,
please fork
RosettaGit’s repository
and open a merge request on GitHub.

{{draft task}}[[Category:Speech synthesis]][[Category:Temporal media]]
Display a piece of text and produce spoken output via a speech engine.

As each word is being spoken, highlight the word on the display.

In languages where cursor control and highlighting are not possible, it is permissible to output each word as it is spoken.

;Related task:
:* [[Speech_synthesis|speech synthesis]]

AutoHotkey

We use the simple SAPI.SPVoice COM Object and a parsing loop.
The highlighting is done with [http://msdn.microsoft.com/en-us/library/bb761661 EM_SETSEL] and Notepad. Rather crude, but it works. Due to the simplistic nature of the parsing loop, the text ends with a space.

SetTitleMatchMode 2
EM_SETSEL := 0x00B1

Run notepad,,,pid
WinWaitActive ahk_pid %pid%
ControlSetText, Edit1, % text := "AutoHotkey was the first to implement this task! ", ahk_pid %pid%

pVoice := ComObjCreate("Sapi.spvoice"), i := 1 ; the spvoice COM Object ships with the OS

; parse the text
While lf := SubStr(text, i, 1)
{
   If lf = %A_Space%
   {
      SendMessage, EM_SetSel, % i-StrLen(word)-1, % i-1, Edit1, ahk_pid %pid%
      pVoice.speak(word), word := "", i++
   }
   Else word .= lf, i++
}

Go

{{works with|Ubuntu 16.04}}

This uses the eSpeak speech synthesizer which is invoked for each word in the text. As the word is spoken it is printed to the terminal in capitalized form (and the previous word is uncapitalized). After a second’s delay the final word is uncapitalized.

Very robotic but it works.

package main

import (
    "fmt"
    "log"
    "os/exec"
    "strings"
    "time"
)

func main() {
    s := "Actions speak louder than words."
    prev := ""
    prevLen := 0
    bs := ""
    for _, word := range strings.Fields(s) {
        cmd := exec.Command("espeak", word)
        if err := cmd.Run(); err != nil {
            log.Fatal(err)
        }
        if prevLen > 0 {
            bs = strings.Repeat("b", prevLen)
        }
        fmt.Printf("%s%s%s ", bs, prev, strings.ToUpper(word))
        prev = word + " "
        prevLen = len(word) + 1
    }
    bs = strings.Repeat("b", prevLen)
    time.Sleep(time.Second)
    fmt.Printf("%s%sn", bs, prev)
}

M2000 Interpreter


Module UsingEvents {
      Form 60, 32
      Cls 5, 0
      Pen 14
      Declare WithEvents sp "SAPI.SpVoice"
      That$="Rosetta Code is a programming chrestomathy site"
      margin=(width-Len(That$))/2
      EndStream=False
      \ this function called as sub routine - same scope as Module
      \ we can call it from event function too
      Function Localtxt {
            \ move the cursor to middle line
            Cursor 0, height/2
            \ using OVER the line erased with background color and then print text over
            \ ordinary Print using transparent printing of text
            \ $(0) set mode to non proportional text, @() move the cursor to sepecific position
            Print Over $(0),@(margin), That$
      }
      Call Local LocalTxt()
      Function sp_Word {
            Read New &StreamNumber, &StreamPosition, &CharacterPosition, &Length
            Call Local LocalTxt()
            Cursor 0, height/2
            Pen 15 {Print Part $(0), @(CharacterPosition+margin); Mid$(That$, CharacterPosition+1, Length)}
            Refresh
      }
      Function sp_EndStream {
            Refresh
            EndStream=True
      }
      Const  SVEEndInputStream = 4
      Const  SVEWordBoundary = 32
      Const SVSFlagsAsync = 1&
 
      With sp, "EventInterests", SVEWordBoundary+SVEEndInputStream
      Method sp, "Speak", That$, SVSFlagsAsync
      While Not EndStream {Wait 10}
      Call Local LocalTxt()
}
UsingEvents


Mathematica

DynamicModule[{text = «This is some text.», words, i = 0},
Panel@Column@{Dynamic[
Row[Riffle[
If[i != 0, MapAt[Style[#, Red] &, #, i], #] &@(words =
StringSplit@text), » «]]], InputField[Dynamic@text, String],
Button[«Speak»,
While[i < Length@words, i++; FinishDynamic[]; Speak[words[[i]]];
Pause[Max[0.7, 0.12 StringLength[words[[i]]]]]]; i = 0]}]




## REXX

{{works with|Windowx/XP or later}}
Programming note:   This REXX program uses a freeware program   NIRCMD   to interface with the Microsoft Windows speech synthesizer program   '''SAM''',   a text to speech using a male voice.   SAM can possibly be configured to use other voices with later releases of Windows.   More recent Microsoft Windows have another speech synthesizer program:   ANNA.

Each word of the text is highlighted (by showing the word in uppercase).   the terminal screen is cleared before showing the text that is being spoken;   the repeated calls to the (Windows) speech engine makes for a slower speech rate. 

```rexx
/*REXX program uses a command line interface to invoke Windows SAM for speech synthesis.*/
parse arg t                                      /*get the (optional) text from the C.L.*/
#= words(t)
if #==0  then exit                               /*Nothing to say?    Then exit program.*/
dq= '"'                                          /*needed to enclose text in dbl quotes.*/
rate= 1                                          /*talk:   -10 (slow)   to   10 (fast). */
                                                 /* [↓]  where the rubber meets the road*/
   do j=1  for #
   x= word(t, j);          upper x               /*extract 1 word, capitalize it for HL.*/
   if j==1  then LHS=                            /*obtain text before the spoken word.  */
            else LHS= subword(t, 1, j-1)
   if j==#  then RHS=                            /*obtain text  after the spoken word.  */
            else RHS= subword(t, j+1)
   'CLS'                                         /*use this command to clear the screen.*/
   say 'speaking: '   space(LHS  x  RHS)         /*show text,  one word is capitalized. */
   oneWord= dq  x  dq                            /*surround a word in double quotes (").*/
   'NIRCMD'  "speak text"    oneWord     rate    /*NIRCMD  invokes Microsoft's Sam voice*/
   end   /*j*/                                   /*stick a fork in it,  we're all done. */

Note: The name of the above REXX program is »’SPEAKHI.REX»’

»’usage»’ using the command:


speakhi This is an example of speech synthesis. 

Ruby

{{libheader|Shoes}}
I’m having difficulty figuring out how to get Shoes to update the GUI (like Tk’s update command), so the user must click the button once for each word.

Uses the Ruby code from [[Speech synthesis]]

load 'speechsynthesis.rb'

if ARGV.length == 1
  $text = "This is default text for the highlight and speak program"
else
  $text = ARGV[1..-1].join(" ")
end
$words = $text.split

Shoes.app do
  @idx = 0

  stack do
    @sentence = para(strong($words[0] + " "), $words[1..-1].map {|word| span(word + " ")})
    button "Say word" do
      say_and_highlight
    end
  end

  keypress do |key|
    case key
    when :control_q, "x11" then exit
    end
  end

  def say_and_highlight
    speak $words[@idx]
    @idx = (@idx + 1) % $words.length
    @sentence.replace($words.each_with_index.map {|word, idx| idx == @idx ? strong(word + " ") : span(word + " ")})
  end
end

Tcl

This code uses the external /usr/bin/say program (known available on Mac OS X) as its interface to the speech engine; this produces rather stilted speech because it forces the text to be spoken one word at a time instead of as a whole sentence (in order to keep the highlighting synchronized).
{{libheader|Tk}}

package require Tcl 8.5
package require Tk 8.5
proc say {text button} {
    grab $button
    $button configure -state disabled -cursor watch
    update
    set starts [$text search -all -regexp -count lengths {S+} 1.0]
    foreach start $starts length $lengths {
	lappend strings [$text get $start "$start + $length char"]
	lappend ends [$text index "$start + $length char"]
    }
    $text tag remove sel 1.0 end
    foreach from $starts str $strings to $ends {
	$text tag add sel $from $to
	update idletasks
	exec /usr/bin/say << $str
	$text tag remove sel 1.0 end
    }
    grab release $button
    $button configure -state normal -cursor {}
}

pack [text .t]
pack [button .b -text "Speak, computer!" -command {say .t .b}] -fill x
.t insert 1.0 "This is an example of speech synthesis with Tcl/Tk."

Words in the message window will, by default, be highlighted as they are spoken. To customize the highlighting:
1.  Select the Settings button located in the toolbar.
kA1G00000008tjcKAA_en_US_1_0
Note: If the Toolbar is hidden, first select the Edit Button kA1G00000008tjcKAA_en_US_1_1 at the top right corner of your screen.

test image

2. Select Voice Settings from the Settings menu. The Settings menu will open.
3. Next to Highlighting, select Configure. The Highlighting menu will open.

kA1G00000008tjcKAA_en_US_1_2
4. Select a highlight type from the drop-down list.

  • Highlight Word: Each word will be highlighted when the message is spoken.
  • Highlight Word and Symbol:Each word and it’s corresponding symbol will be highlighted.
  • Highlight Sentence:Each sentence will be highlighted
  • Highlight Sentence and Word: Each sentence will be highlighted (with Highlight Style 2) as it is spoken. Each word will be highlighted (with Highlight Style 1) as it is spoken.

5. Select a highlight style from the Highlight Style 1 and Highlight Style 2 drop-down lists.

  • Fill Color:The word (or sentence) will be highlighted with the color you choose.
  • Text Color: The text in the word or sentence will change to the selected color as it is spoken.
  • Outline Color:The word or sentence will be highlighted with the color you choose.
  • Invert: The text and text background color will switch as the word or sentence is spoken

6. Use the Color buttons to select colors for Highlight Styles 1 and 2.

To prevent words from being highlighted, enter the Voice Settings Menu and select Disabledfrom the drop-down list next to Highlighting.

When you have finished customizing your highlighting settings, select the green Done button in the top right corner of the screen.

  • Remove From My Forums
  • Question

  • Hi, I have tried everything to get System.Soeech to highlight the spoken words in a WPF RichTextBox and have failed . . .

    I am using a TextRange to Speak the text of the WPF RichTextBox — no problem there!

    But SpeakProgress — e.CharacterPosition does not correspond to the character position in the WPF RichTextBox

    I got this far in the SpeakProgress() method, but it keeps highlighting the wrong words

    TextRange text = new TextRange(start, this.CurrentlySpeakingRichTextBox.Document.ContentEnd);
                            TextPointer current = text.Start.GetInsertionPosition(LogicalDirection.Forward);

                            while (current != null)
                            {
                                string textInRun = current.GetTextInRun(LogicalDirection.Forward);

                                if (!string.IsNullOrWhiteSpace(textInRun))
                                {
                                    int index = textInRun.IndexOf(aWord);
                                    if (index != -1)
                                    {
                                        TextPointer selectionStart = current.GetPositionAtOffset(index, LogicalDirection.Forward);
                                        TextPointer selectionEnd = selectionStart.GetPositionAtOffset(aWord.Length, LogicalDirection.Forward);
                                        TextRange selection = new TextRange(selectionStart, selectionEnd);
                                        this.RichTextBoxPointer = selectionStart;
                                        this.CurrentlySpeakingRichTextBox.Selection.Select(selection.Start, selection.End);
                                       // rtb.Focus();
                                    }
                                }
                                current = current.GetNextContextPosition(LogicalDirection.Forward);
                            }

    Please, anyone  . . . Help!

    • Edited by

      Sunday, May 22, 2016 2:44 PM

    • Moved by
      Moonlight ShengMicrosoft contingent staff
      Monday, May 23, 2016 5:43 AM

Answers

  • Many thanks DotNet Wang and Moonlight Sheng. I finally figured it out with your help.

    The code I used is for SpeakProgress is below:

             private void SpeechEngine_SpeakProgress(object sender, System.Speech.Synthesis.SpeakProgressEventArgs e)
            {

               if (e.CharacterCount > 0)
               {
                   HighlightWordInRichTextBox(this.CurrentlySpeakingRichTextBox, e.Text);
               }
            }

            private void HighlightWordInRichTextBox(RichTextBox richTextBox, String word)
            {
                // Current word at the pointer . . .
                TextRange tr = FindWordFromPosition(textPointer, word);
                if (!object.Equals(tr, null))
                {
                    // Set the pointer to the end of «word» . . .
                    textPointer = tr.End;
                    // Highlight word . . .
                    this.CurrentlySpeakingRichTextBox.Selection.Select(tr.Start, tr.End);
                }
            }

            private TextRange FindWordFromPosition(TextPointer position, string word)
            {
                while (position != null)
                {
                    if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                    {
                        string textRun = position.GetTextInRun(LogicalDirection.Forward);

                        // Find the starting index of any substring that matches «word» . . .
                        int indexInRun = textRun.IndexOf(word);
                        if (indexInRun >= 0)
                        {
                            TextPointer start = position.GetPositionAtOffset(indexInRun);
                            TextPointer end = start.GetPositionAtOffset(word.Length);
                            return new TextRange(start, end);
                        }
                    }
                    position = position.GetNextContextPosition(LogicalDirection.Forward);
                }

                // Position will be null if «word» is not found . . .
                return null;
            }


    DaveM121

    • Marked as answer by
      DaveM121
      Friday, May 27, 2016 11:56 AM
    • Edited by
      DaveM121
      Friday, May 27, 2016 11:57 AM

Looks like no one’s replied in a while. To start the conversation again, simply

ask a new question.

After selecting a portion of text to be read aloud, spoken content reads the whole selected text, but does not highlight each spoken word. Changing the highlight color did not work :(. Thanks for any help!

MacBook Pro 13″,

macOS 12.2

Posted on Mar 14, 2022 6:57 AM

This Accessibility feature works correctly in macOS 11.6.4 and 12.2.1 when I select your text above in Safari 15.3 and press option+ESC. Each word receives a yellow highlight as it is spoken, just as expected.

This feature may not work in third-party applications where the keyboard shortcut is used for another purpose, or there are no speech controls.

Tested: 2020 M1 mini w/11.6.4, and 2021 MBP M1 Pro 16-inch w/12.2.1.

Posted on Mar 14, 2022 8:58 AM

Similar questions

  • Spoken text on iPad is not working
    In accessibility, on the iPad, it has an option of spoken content. With in the settings of spoken text is highlighting, options are words, sentences, and words and sentences. However, when words is chosen spoken content does not highlight the word as it is spoken, nor does it highlight sentences when that optioned is checked. The only thing spoken text does under highlighting is to highlight the entire page. I would like to know how to fix it. I have checked an option closed it out restarted my iPad opened it back up and it still doesn’t work I’ve done this for all options. I need it’s a highlight the word as it is spoken. Which is what the iPad says that it will do. I have tried this in Kindle, books, a PDF, as well as Pages, Numbers, and iOSmail.
    it is very frustrating.
    Christy

    310
    3

  • text to speech
    how do i enable speech, so that when i highlight text even on a pdf, the computer reads aloud the highlighted text

    169
    3

  • Highlighting text and then speak text is not working
    Highlighting text and then speak text is not working.
    this is not an issue with Siri. This is an issue I have one highlighting a text whether it is in the notepad, online or in an email. I used to be able to highlight it and then tap speak and it would read it to me. That does not happen anymore and I’ve been poking around in the The iPhone system and I have not been able to figure out what I can do To resolve my problem.

    124
    2

highlighting each word as they are spoken does not work

In iOS, it is possible to have the text read out loud using the built-in text-to-speech (TTS) while the individual words highlight as they are spoken.

Like in this gif:

tts in iOS, MacOS highlight content as spoken as iOS

(taken from this you video).

I am looking for a way to get MacOS’s (10.11) built-in TTS to highlight individual words as they are spoken, as in iOS. This is extremely helpful for me when reading.

This Ask Different question get at the same issue, but it’s slightly different as it’s asking for a browser-based solution and I am primarily looking for native MacOS solution. Thanks.

asked Jan 7, 2019 at 12:40

Eric Fail's user avatar

Eric FailEric Fail

971 silver badge10 bronze badges

0

VoiceOver on macOS can do this.

  1. Use VoiceOver Utility.app to activate move highlight cursor by word
  2. Activate VoiceOver with Cmd+F5
  3. Click on the text you want to read
  4. Press Control+Alt+A to «read all»

VoiceOver Utility - Visuals - move highlight by word

How well it works will vary by application and how well they support VoiceOver.

These animations were recorded on 10.13.6 High Sierra, but VoiceOver has been around since 10.4 Tiger — so you should be OK in 10.11 El Capitan.

Pages — works well

enter image description here

FSNotes — works well

enter image description here

Safari — depends on how the page is built

enter image description here

answered Jan 22, 2019 at 18:25

Matt Sephton's user avatar

Matt SephtonMatt Sephton

4,8691 gold badge30 silver badges51 bronze badges

1

You can try Dictator by Nosrac. It’s available for free on GitHub. I’m not the developer or affiliated with the software.
enter image description here

It has a feature called ‘teleprompter mode’ that highlights the words as they’re spoken.

enter image description here

The code hasn’t been updated in a few years and I haven’t tried it myself so I can’t speak for how well it works. I’m recommending it because it looks like it does what you want and it’s free.

Matt Sephton's user avatar

Matt Sephton

4,8691 gold badge30 silver badges51 bronze badges

answered Jan 7, 2019 at 12:52

fsb's user avatar

fsbfsb

22.4k16 gold badges56 silver badges85 bronze badges

8

I tried an app called Natural Reader and it does a decent job, but the voices are terrible and it isn’t quite as seamless as iOS’s integration. I really only want this for Safari so I guess I’ll just have to Airdrop the link to my nearby iPhone or iPad and initiate the screen reader gesture there. Natural Reader does have a great Chrome Extension so I am hoping with Big Sur and the new ability to easily port Chrome Extensions to Safari that they will do that soon and let us use all of the system voices; I much prefer the UK Male Safari voice to any of Natural Reader’s voice, free and paid.

answered Jul 8, 2020 at 22:47

Cabana0309's user avatar

You must log in to answer this question.

Not the answer you’re looking for? Browse other questions tagged

.

Like this post? Please share to your friends:
  • History of word expressions
  • Highlight the misspelled word
  • History of word classes
  • History of word chat
  • History of the word values