Hello,
I often get distracted by my own thoughts while reviewing cards in AnkiDroid.
I like the built-in on-screen timer that shows the time spent on each card, but I tend to lose track of time.
Is there any way to make the timer vibrate or play a short beep when the maximum answer time is reached?
Thank you!
Add an audio file prefixed with an underscore to your collection.media folder or make a note with an audio file and use the name AnkiDroid assigns to it.
Add this code to your templates. You should change the name and time (in milliseconds):
<script>
var audio = new Audio('_alertAudio.mp3');
setTimeout(() => {
audio.play();
}, 3000);
</script>
kaiu
June 19, 2026, 12:51pm
3
Vibration is also not difficult to do, here is vibration and a pause of 100 ms between them
navigator.vibrate([200, 100, 200]);
Thank you @ZornHadNoChoice and @kaiu !
Combining your approaches and AI I finished with this version (tap on the text tests the vibration):
<div id="t" style="font-size:0.5em;text-align:right;margin:15px 0;color:grey;cursor:pointer">Time: 60s</div>
<script>
const S=60; let t=S; const d = document.getElementById('t');
function u(){d.textContent=`Time: ${t}s`;}
function vibrate() {if ("vibrate" in navigator) navigator.vibrate([800]);}
setInterval(()=>{t--; u(); if(t<=0){vibrate(); t=S; u();}},1000);
d.addEventListener('click', vibrate); u();
</script>
It’s compacted, because it’s copied to all card types.
i have better code, just change the number in the div or span. this will countdown to 0 and auto changes to red
<span class="amx-timer-widget" style="font-size:0.5em;text-align:right;margin:15px 0;color:inherite;opacity:75%;cursor:pointer">Time: 45s</span>
<span class="amx-timer-widget">Timer 1: 30s</span>
<span class="amx-timer-widget">Timer 1: 20s</span>
<!--- 13:02 revision --->
<script>
(function(){
// bersihkan semua timer dari render/kartu sebelumnya dulu
if(window.__amxTimerRegistry){
window.__amxTimerRegistry.forEach(id=>clearInterval(id));
}
window.__amxTimerRegistry = [];
document.querySelectorAll('.amx-timer-widget:not([data-amx-init])').forEach(function(el){
el.setAttribute('data-amx-init','1');
const match=el.textContent.match(/^(.*?)(\d+)\s*s?\s*$/);
const label=match?match[1].trim():'Time';
const duration=match?parseInt(match[2]):60;
let remaining=duration;
let tickInterval=null;
function render(){
el.textContent=`${label} ${remaining}s`;
el.style.color=remaining<=0?'red':'';
}
function buzz(){ if("vibrate" in navigator) navigator.vibrate([800]); }
function startTicking(){
if(tickInterval) clearInterval(tickInterval);
tickInterval=setInterval(()=>{
remaining--;
if(remaining<=0){
remaining=0; render(); buzz();
clearInterval(tickInterval);
} else {
render();
}
},1000);
window.__amxTimerRegistry.push(tickInterval);
}
el.addEventListener('click',()=>{
buzz();
if(remaining<=0){
remaining=duration; render(); startTicking();
}
});
render();
startTicking();
});
})();
</script>
I’ve fixed the front-back vibration. no more mistakes for this new revision!