我正在编写一个JS应用程序,突出显示与预先录制的音频同步的单词。这个过程非常简单。我列出了每个单词在音频中开始的时间,我每隔.1秒调用一个JS函数来检查audio.currentTime并查看它是否已达到下一个单词的阈值。我已经尝试过使用音频timeUpdate事件,并且为了我的目的,并没有在平台上频繁触发。单词被跳过。
我已经在移动Chrome,iPad(移动版Safari),Kindle Fire(丝网浏览器或他们现在称之为的任何内容)的Moto E上测试了我的代码,并在Windows上使用最新的Chrome,Firefox和IE 11。
除了一个例外,它一切运行良好:Firefox滞后。同步在FF中工作正常,但每次我将音频提示到一个新的时间,Firefox似乎落后,并在第10页左右(即使我只是按下我的"下一页"重复按钮),滞后是显而易见的。叙述者将完成一个单词,FF将开始突出显示前一个单词。
以下是相关代码:
一旦对书籍信息的AJAX调用回来,就会调用它:
window.setInterval( bundleFunctions.execute, 100 );
bundleFunctions
对象只是一种同时调用动态功能组的简单方法。
有两个功能被添加到bundleFunctions
。我关心的是highlightWord
。
var lasthighlight = -1;
function highlightWord() {
var debug = false;
// find the last word time that comes before the current time.
var playerSound = document.getElementById( "playerSound" ); // audio tag
// wordTimes is an array of times where each word starts in the recorded audio
var indexToHighlight = Math.max.apply( Math, $.map( wordTimes, function( time, index ) {
// only highlight words that start before the current time with a buffer equal to the interval at which this function is called
// don't highlight word for more than 2 seconds.
if ( time - .1 > playerSound.currentTime || playerSound.currentTime - time > 2 ) {
return null;
// if this is the last or first wordTime or the preceding word time
// is less than the current time, return the index of that word time
} else {
return index;
}
}));
// minimize lag by not touching the DOM if there's no new word to highlight
if ( typeof indexToHighlight != "undefined" ) {
if ( lasthighlight != indexToHighlight ) {
lasthighlight = indexToHighlight;
if ( debug ) {
console.log( "highlighting word [ " + $( ".word.use:eq(" + indexToHighlight + ")" ).text() + "] at this index: [" + indexToHighlight + "]" );
console.log( indexToHighlight );
}
$word = $( ".word:eq(" + indexToHighlight + ")");
$( ".word" ).css( "color", "black" );
$word.css( "color", "red" );
}
}
}
你可以看到我添加了一些代码来尝试最小化DOM操作,希望这是FF落后的原因,但它没有任何效果。请注意,页面上一次只有40个左右的单词,所以它不像是一些重型DOM操作,并且延迟似乎与在音频中搜索直接相关,而不是任何问题FF JS引擎已经处理了它的工作量。
bundleFunction调用的另一个函数检查我们是否已到达页面的末尾。这是该函数(override
允许我手动跳过下一页):
function checkAdvancePage( override ) {
var debug = false;
override = override === true;
if ( playerSound.currentTime >= timeToSeconds( book.pages.page[ curPage ][ "_f" ]) || override ) {
if ( book.pages.page.length >= curPage + 2 ) {
if ( debug ) {
console.log( "advancing page from [" + curPage + "]" );
}
curPage++;
if ( debug ) {
console.log( "to [" + curPage + "]" );
}
// this book has another page. Keep going.
startPage( book );
} else {
// this book is on its last page
endScreen( book );
}
}
}
正如你所看到的,它非常基本。 99.9%的时间它将评估一行代码 - "是currentTime>当前页面的结束时间?",返回false,结束。
最后,这里是代码,其中包括代码,其中,代码在音频中寻找页面变化的新页面的开头。奇怪的结构化书籍对象就是这样,因为它是从XML转换而来的:
var soundLoaded = false;
var isPlaying = false;
function queueAudio( book ) {
var debug = false;
var playerSound = document.getElementById( "playerSound" ); // audio tag
var playing = false;
playerSound.addEventListener( 'canplaythrough', function queue() {
if ( debug ) {
console.log( "tracing this page" );
console.log( book.pages.page[ curPage ]);
}
playerSound.currentTime = timeToSeconds( book.pages.page[ curPage ]["_s" ]);
playerSound.removeEventListener( 'canplaythrough', queue );
bundleFunctions.add( checkAdvancePage );
soundLoaded = true;
});
if ( !soundLoaded ) {
var playerSource = document.getElementById( "playerSource" ); // source tag
playerSource.src = BOOKS_DIR + book.track[ "_src" ];
playerSound.load();
playerSound.play(); // has to be called here to link a mobile tap to the play command
isPlaying = true;
} else {
playerSound.currentTime = timeToSeconds( book.pages.page[ curPage ]["_s" ]);
}
// manual click to next page. Only add the listener once.
if ( typeof( document.getElementById( "next" ).onclick ) == "undefined" ) {
$( "#next" ).click( function() {
console.log( "next page clicked" );
checkAdvancePage( true );
});
}
// watches current time of audio and advances to the next page when we get to the end of the audio for that page
function checkAdvancePage( override ) {
var debug = false;
override = override === true; // if true, advance the page regardless of currentTime
if ( playerSound.currentTime >= timeToSeconds( book.pages.page[ curPage ][ "_f" ]) || override ) {
playerSound.removeEventListener( 'timeupdate', checkAdvancePage );
if ( book.pages.page.length >= curPage + 2 ) {
if ( debug ) {
console.log( "advancing page from [" + curPage + "]" );
}
curPage++;
if ( debug ) {
console.log( "to [" + curPage + "]" );
}
// this book has another page. Keep going.
startPage( book );
} else {
// this book is on its last page
endScreen( book );
}
}
}
}
如果一个单词在说出的确切时刻不突出显示,则可以接受。什么是不可接受的是在之后突出显示 >
最快的单词大概是在0.1秒内说出来的。如果有一段时间,只要突出显示保持同步,就会跳过其中一个超快速的单词。 提前感谢您提供的任何帮助。