Thursday, July 30, 2015

Word Highlighting in a read-to-me app

One of the common use case while developing a read-to-me book apps is highlight the word as it is read to the user. In this example we discuss how we can achieve it. The source code is at https://github.com/cspnanda/TextHighlight

We are going to use a UIWebView for this. UIWebView uses HTML so can be easily styled. I found it easier than using the NSAttributedString with a TextView. For this purpose we will need a audio file and a file containing beginning time offset and lengths of each word. 

The text we are going to display is "The quick brown fox jumps over the lazy dog". In the offset file you will need 9 value pairs, one for each word. I really want to know if there is a better way to solve it, but did not find any. To easily find the time offset, you can open your sound file in Audacity. The words are waveforms and the pause between the words are flat.



Then add these values to a plist file. The plist file now looks like
<dict>
        <key>offset</key>
        <array>
                <array>
                        <string>The</string>
                        <real>0.019</real>
                        <real>0.218</real>
                </array>
                <array>
                        <string>quick</string>
                        <real>0.237</real>
                        <real>0.283</real>
                </array>
                <array>
                        <string>brown</string>
                        <real>0.52</real>
                        <real>0.382</real>
                </array>

Then we need to have a timer which will fire at those specific intervals.

[NSTimer scheduledTimerWithTimeInterval:[[thisWord objectAtIndex:2] floatValue]
     target:self
     selector:@selector(highlightText)
     userInfo:nil
     repeats:NO];

In the highligtText function we have to set all the words except the current one in normal color and highlight the current word.

htmlString = [htmlString stringByAppendingString:@"<span class='highlight'> "];
htmlString = [htmlString stringByAppendingString:[words 
              objectAtIndex:currentWord]];
htmlString = [htmlString stringByAppendingString:@"</span> "];

Then we invalidate the current timer and schedule for the next word.

[webView loadHTMLString:htmlString baseURL:nil];
currentWord++;
[timer2 invalidate];
timer2 = Nil;
timer2 = [NSTimer scheduledTimerWithTimeInterval:([[thisWord objectAtIndex:2] floatValue])
    target:self
    selector:@selector(highlightText)
    userInfo:nil
    repeats:NO];

Now when you run the project, you get an output like





No comments:

Post a Comment