问题
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>
回答1:
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>
来源:https://stackoverflow.com/questions/28811139/html5-audio-tag-onplaying-even-is-triggered-before-audio-play-in-android