Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML5 audio tag onplaying even is triggered before audio play in android

I have write a code for highlight text according to audio. In this the logic is when audio start playing we fire a highlight function. which highlight each word for given no of time.

And it is working fine for window PC and Desktop. But In android highlight function trigger before audio start that is why audio and highlight is not synchronized.

Below is the code.

function highlight(start,totalWords,aid) {  

            var wtime =   data[start]/defaultPlayback;
            $("#W"+start).css("color",'yellow'); 
            setTimeout(function (){    
            $("#W"+start).css("color",'');     
            start++;
            if (start <= totalWords) {highlight(start,totalWords,aid);}
            else{return false;}       
            }, wtime);    


        }

<audio  preload='auto' controls id='a2' onplaying="highlight(10,18,'bookread4');"  onended="completed('a3')" >

  <source src="http://arbordalepublishing.com/eBooks2/Animalogy/Animalogy p7.mp3" type="audio/mpeg">
  Your browser does not support the audio element.
</audio>



<span id="W10" class="calibre2">Chick </span>
<span id="W11" class="calibre2">is </span>
<span id="W12" class="calibre2">to </span>
<span id="W13" class="calibre2">feathery,</span>
<span id="W14" class="calibre2">as </span>
<span id="W15" class="calibre2">bear </span>
<span id="W16" class="calibre2">is </span>
<span id="W17" class="calibre2">to </span>
<span id="W18" class="calibre2">furry.</span>
like image 682
Krishna Nandan Avatar asked Oct 15 '25 18:10

Krishna Nandan


1 Answers

Instead of driving the text with a timer/counter, which you will have no guarantee will synchronize, you should use the currentTime property of the audio element. This will force correct time independent on start.

The property returns current absolute time in fractional seconds. Use this time to check time range for the word to be highlighted.

For example (just arbitrary times here as the original data is not available):

var words = [
    {
        id: "W10",            // or use reference to element
        start: 0,             // time in seconds
        end: 0.2,
        highlighted: false    // to reduce DOM updates
    },
    {
        id: "W11",
        start: 0.22,
        end: 0.4,
        highlighted: false
    },
    ... etc. ...
];

Then in highlight:

function highlight() {

    var time = a2.currentTime,
        i = 0, word;

    for(; word = words[i++];) {
        if (time >= word.start && time <= word.end)
          if (!word.highlighted) {
            word.highlighted = true; // to reduce the need to update DOM
            // ... set CSS for highlighted here...
          }
        }
        else if (word.highlighted) {
            // ... set CSS for not highlighted here...
            word.highlighted = false;
        }
    }
}

Live demo

Try pausing it during play and you will see text is still able to sync when continued.

// NOTE: these are not 100% synchronized - they are just for example
var words = [
    {id: "W10", start: 0, end: 0.7, highlighted: false},
    {id: "W11", start: 0.76, end: 1.1, highlighted: false},
    {id: "W12", start: 1.2, end: 1.3, highlighted: false},
    {id: "W13", start: 1.4, end: 2.1, highlighted: false},
    {id: "W14", start: 2.1, end: 2.3, highlighted: false},
    {id: "W15", start: 2.3, end: 2.7, highlighted: false},
    {id: "W16", start: 2.7, end: 3.0, highlighted: false},
    {id: "W17", start: 3.0, end: 3.2, highlighted: false},
    {id: "W18", start: 3.2, end: 3.4, highlighted: false}],
  audio = document.getElementById("a2");

audio.onplaying = highlight;

function highlight() {
  var time = a2.currentTime, i = 0, word;

    for(; word = words[i++];) {
        if (time >= word.start && time < word.end) {
          if (!word.highlighted) {
            word.highlighted = true; // to reduce the need to update DOM
            document.getElementById(word.id).style.color = "orange";
          }
        }
        else if (word.highlighted) {
            document.getElementById(word.id).style.color = "black";
            word.highlighted = false;
        }
    }

  // you should listen to end event and stop the loop using that, here, for simplicity:
  if (!audio.paused) setTimeout(highlight, 17);
  //else alert("done");
}
body {font: bold 16px sans-serif}
<audio preload='auto' controls id='a2'>
  <source src="http://arbordalepublishing.com/eBooks2/Animalogy/Animalogy p7.mp3" type="audio/mpeg">
    Your browser does not support the audio element.
</audio>
<br>
<span id="W10">Chick </span>
<span id="W11">is </span>
<span id="W12">to </span>
<span id="W13">feathery,</span>
<span id="W14">as </span>
<span id="W15">bear </span>
<span id="W16">is </span>
<span id="W17">to </span>
<span id="W18">furry.</span>

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!