Javascript template - setInterval - innacurate

HTML Template with timer tick:

var timer = 60;
var timer_handle = setInterval(timerTick,1000);

function timerTick(){
   timer--;
}

In browser works fine, inside Caspar works 10-20% faster… why?
I know I can get around using current time etc, but why overcomplicate? This should work accurate enought.

I just tested with the NRK fork and according to timing done with performance.now - it’s the same as in browser (varies by 1-2ms).

<html><head></head><body>
<script>
var timer = 60;
function timerTick() {
	if(timer == 0) {
		console.log('Measured running time: ' + (performance.now() - start) + ' ms');
		clearTimeout(timeoutHandler);
		return;
	}
	timer--;
	console.log(timer);
}
var start = performance.now();
var timeoutHandler = setInterval(timerTick, 1000);
</script>
</body></html>

Which CCG version are your running?

CasparCG Server 2.3.0_12
Intel 6800K 6c12t @ 4.1GHz, 32GB RAM, GTX 1070 - basicly it’s iddleing…

[2020-02-11 21:16:21.157] [info]    Starting CasparCG Video and Graphics Playout Server 2.3.0 4a8f03f3 Dev
[2020-02-11 21:16:21.518] [info]    Initializing OpenGL Device.
[2020-02-11 21:16:21.522] [info]    Initialized OpenGL 4.5.0 NVIDIA 442.19 NVIDIA Corporation
[2020-02-11 21:16:21.526] [info]    Initialized ffmpeg module.
[2020-02-11 21:16:21.526] [info]    Initialized oal module.
[2020-02-11 21:16:21.526] [info]    Initialized decklink module.
[2020-02-11 21:16:21.526] [info]    Initialized screen module.
[2020-02-11 21:16:21.526] [info]    Initialized newtek module.
[2020-02-11 21:16:21.556] [info]    Initialized html module.
[2020-02-11 21:16:21.606] [info]    Initialized flash module.
[2020-02-11 21:16:21.608] [info]    Initialized bluefish module.
[2020-02-11 21:16:21.608] [info]    Initialized image module.
[2020-02-11 21:16:21.608] [info]    "D:/CASPAR\CasparCG Server 2.3.0_12\casparcg.config":
[2020-02-11 21:16:21.608] [info]    -----------------------------------------
[2020-02-11 21:16:21.608] [info]    <?xml version="1.0" encoding="utf-8"?>
[2020-02-11 21:16:21.608] [info]    <configuration>
[2020-02-11 21:16:21.608] [info]       <paths>
[2020-02-11 21:16:21.608] [info]          <media-path>D:\CASPAR\MEDIA\</media-path>
[2020-02-11 21:16:21.608] [info]          <log-path>log/</log-path>
[2020-02-11 21:16:21.608] [info]          <data-path>data/</data-path>
[2020-02-11 21:16:21.608] [info]          <template-path>D:\CASPAR\TEMPLATES\</template-path>
[2020-02-11 21:16:21.608] [info]          <thumbnails-path>thumbnails\</thumbnails-path>
[2020-02-11 21:16:21.608] [info]       </paths>
[2020-02-11 21:16:21.608] [info]       <log-level>debug</log-level>
[2020-02-11 21:16:21.608] [info]       <channels>
[2020-02-11 21:16:21.608] [info]          <channel>
[2020-02-11 21:16:21.608] [info]             <video-mode>1080p6000</video-mode>
[2020-02-11 21:16:21.608] [info]             <consumers>
[2020-02-11 21:16:21.608] [info]                <newtek-ivga/>
[2020-02-11 21:16:21.608] [info]                <screen>
[2020-02-11 21:16:21.608] [info]                   <device>1</device>
[2020-02-11 21:16:21.608] [info]                </screen>
[2020-02-11 21:16:21.608] [info]             </consumers>
[2020-02-11 21:16:21.608] [info]          </channel>
[2020-02-11 21:16:21.608] [info]       </channels>
[2020-02-11 21:16:21.608] [info]       <controllers>
[2020-02-11 21:16:21.608] [info]          <tcp>
[2020-02-11 21:16:21.608] [info]             <port>5250</port>
[2020-02-11 21:16:21.608] [info]             <protocol>AMCP</protocol>
[2020-02-11 21:16:21.608] [info]          </tcp>
[2020-02-11 21:16:21.608] [info]       </controllers>
[2020-02-11 21:16:21.608] [info]    </configuration>
[2020-02-11 21:16:21.608] [info]    -----------------------------------------
[2020-02-11 21:16:21.613] [info]    Initialized OpenGL Accelerated GPU Image Mixer for channel 1
[2020-02-11 21:16:21.614] [info]    video_channel[1|1080p6000] Successfully Initialized.
[2020-02-11 21:16:21.619] [info]    Loaded D:\CASPAR\CasparCG Server 2.3.0_12\Processing.AirSend.x64.dll
[2020-02-11 21:16:21.630] [info]    newtek-ivga[not connected] Initialized.
[2020-02-11 21:16:21.631] [info]    Screen consumer [1|1080p6000] Initialized.
[2020-02-11 21:16:21.631] [info]    Initialized channels.
[2020-02-11 21:16:21.634] [info]    Initialized controllers.
[2020-02-11 21:16:21.634] [info]    Initialized osc.

https://wetransfer.com/downloads/5ff74cb5858fb46a717b00f61efc08ce20200211184250/1092dd

video shows proof of concept (.NET app client for launching CasparCG HTML Templates with different params). there is clock counter, which clearly counts too fast.

You will never get an acurate timer using an interval or delay. You can use whatever programming language you want. These timers are made in software to delay an operation, not to measure time.

The only way to get an acurate clock using one of these is, to use the real time clock. Store the current time on the click of the start button and use the difference to the current time every time the interval is hiting. Whenever needed update the display.

I normally also store the difference in seconds in a variable and let the timer hit 10 times a second (every 100ms). Whenever the difference is different I update the display. That gives you a quite nice counting clock.

2 Likes

I may be rambling here but the fact that you’re using a ‘K’ processor could be messing with ticks timing and that extra speed in the clock is what gives you that extra percentage. Much like the ‘turbo’ on games from the old days.
I’m just guessing.

We’ll if there is a deviation in timers that can be affecting other things (and I guess lots of developers use setTimout etc to delay stuff), then we must look into it. However I can’t reproduce this timing issue.

Here is a dead simple example of a countdown using timestamps and updating with rAF if anyone is interested:

<html><head></head>
<body>

<div id="timeDisplay">60</div>

<script>
var timeDisplay = document.getElementById('timeDisplay');
var start; // Just to check timing

function countdown(seconds, showMilliseonds) {
	var end = Date.now() + (seconds * 1000);
	countdownUpdate(end, showMilliseonds);
	start = performance.now(); // Just to check timing
}

function countdownUpdate(end, showMilliseonds) {
	window.requestAnimationFrame(function() {
		var newTime = (end - Date.now()) / 1000;

		if(newTime <= 0) {
			timeDisplay.textContent = showMilliseonds ? '0.000' : 0;
			console.log('Ended, ran for: ' + (performance.now()-start) + 'ms'); // Just to check timing
			return;
		}
		timeDisplay.textContent = showMilliseonds ? newTime : ~~newTime;
		countdownUpdate(end, showMilliseonds);
	});	
}

countdown(60, true);
</script>
</body></html>

internal hardware bus clock is separated from the clock exposed by OS API

Norbert: did you run my setInterval test and get the same 10-20% speedup?

I’ll try different versions of CasparCG and get back to you.

my entire code:

var timer = 0;
var timer_active = false;
var timer_handle = setInterval(timerTick,1000);

function timerTick(){
    if (timer_active) {
        if (timer>0) {timer--;}
        $('#timer_text').text(timer);
    }
}

some other part of code sets timer_active to true, but it’s irrelevant

Can’t reproduce this error. This happened after whole day of development, when CCG worked in the background. Maybe this has something to do with it?