Interlacing "Comb" Artifacts on Vertical HTML Text Animation

Hi everyone,

I’m encountering a persistent issue with interlacing artifacts (a “comb” or “tearing” effect) on vertically animating text in my HTML templates when outputting via DeckLink in PAL (interlaced) video mode. I’ve done a fair bit of troubleshooting, and I’m hoping someone in the community might have experienced something similar or can offer some insights.

The Problem:
When I animate simple white text on a black background, moving vertically (up or down) using CSS transform: translateY(), the text appears to “comb” or “tear” on the interlaced PAL output. This is very noticeable.
when animation matches the vertical pixels then it is not showing comb as can see in the video below where duration 4s is the value. but when we change the speed it appears.

What I’ve Observed & Troubleshooting Steps:

Confirmed Interlacing: I’ve verified that the issue is purely related to interlacing. When I switch the CasparCG channel’s video-mode to a progressive format (e.g., 720p5000), the animation is perfectly smooth, with no comb effect.

Browser Preview is Perfect: The HTML template renders flawlessly and smoothly in a standard web browser (like Chrome), indicating that the CSS animation itself is not the source of the problem.

Animation Method: I’m using transform: translateY() with a linear timing function for the animation, which is generally recommended for smooth, GPU-accelerated motion.

“Snap to Even Pixels” Workaround: I’ve implemented a “snap to even pixels” option in my test template (using JavaScript to round positions). When enabled, this does remove the comb effect, but as expected, it introduces a very noticeable jerky, stepped motion, making the animation unusable for broadcast. This confirms that the comb is directly related to sub-pixel rendering being converted to interlaced fields.

Test Template: To isolate the issue, I’ve created a very simple HTML template with:
A black background and white text.
A 1px white border around the text container (which also shows the comb).
Sliders to control animation duration and vertical distance.
A toggle to enable/disable “Snap to Even Pixels” for direct comparison.
A toggle to show/hide the border.
The text is set to a smaller font size (6vw) and the default animation distance is 50px.

My Setup:

CasparCG Server Version: 2.4.1
Operating System: Windows 10 Pro 64-bit
GPU: Quadro k4000

Seeking Your Help:
Has anyone else encountered this specific interlacing issue with HTML text animations, especially vertical ones, on interlaced output? Are there any known best practices.

below is the recording from decklink output.

below is the recording within CasparCG Server.

I’m happy to share the HTML template code if that would be helpful for diagnosis.

Any advice or shared experiences would be greatly appreciated!

Thanks,

I’m definitely not an expert, so take my advice with a grain of salt, but from my experience vertical movement of things with sharp edges and also thin horizontal lines get wobbly when being rendered in interlaced mode. It’s simply in the nature of interlaced rendering I’m afraid..

If I have to render a horizontal line, I try to make sure its height is an even number of pixels, that usually does the trick.

Something you could try with your vertically moving text, is to add some “motion blur” of 2px to it? Smoothing out the edges might reduce the interlaciness..

Here is a hack for vertical blurring, YMMV:
https://stackoverflow.com/questions/24046228/css-blur-only-in-one-direction-motion-blur

1 Like

Thank you @Nytamin for the suggestion!

First, to address the “motion blur” trick:

The suggestion of adding a 2px blur is a great idea to reduce the comb effect. I’ve tested it, and it does indeed smooth out the interlaciness. However, as expected, it comes at the cost of text sharpness, which we’re trying to avoid for a clean broadcast look. It’s a useful compromise, but not the ideal solution for this project.

My further testing has revealed a significant difference in how the interlacing is handled. When I configure CasparCG to output 720p5000 and use the DeckLink card’s hardware conversion to down-convert to PAL, the vertically animating text is noticeably smoother and has minimal combing compared to CasparCG’s direct PAL output.

This difference in quality, despite both methods resulting in a PAL interlaced signal, is quite puzzling. It strongly suggests that the method of converting the progressive source to interlaced fields is the key factor.

Of course, this isn’t a viable solution because I lose the Fill/Key output, so I’m not proposing this as a solution, but rather as a diagnostic observation. I’m hoping someone can shed light on why these two methods produce such different results.

Any insights would be greatly appreciated!

I’ve had reason to look at this as well and found that a small text-shadow of the same colour as the text improved html text with vertical animation

The problem, and solutions, are deeply embedded in sampling and aliasing.

When signals are sampled by a clock the baseband signal spectrum is convolved with the spectrum of the sampling signal, resulting in the spectrum being repeated above and below every integer multiple of the sample clock frequency. When the continuous signal format is again required the sampled signal passes through a bandpass pass filter that, ideally, passes all baseband spectrum and blocks all other frequencies. The basic requirement is the sample frequency must be at least twice the bandwidth of the source baseband signal. This requires the source signal be filtered before the sampling process to avoid high baseband frequencies being mirrored back into the output of the reconstruction filter.

For video and audio signals the signal spectrum starts at zero (video) and very low frequency (audio). Thus the bandwidth and the maximum signal frequency are identical measures of the source signal spectral properties.

Television inherently includes two sampling processes - the vertical spatial content and the number of pictures captured per second. The third sampling clock is that applied to the horizontal detail of the image - for example the sample 74.25 MHz clock used to sample the Y (luminace) signal in a 1080i HD signal. When looking at aliasing issues in a television signal we must consider the 3-D spectrum space and how the sample clocks may cause unexpected issues. For example a 50 fields per second 1080 interlaced signal system containing content with 540 cycles per active picture height (c/aph) repeats at an interlace clock located at V=540 c/aph and F=25Hz it creates an in-band signal component at 0 c/aph with a 25 Hz repeat rate that shows as flashing on a display.

The vertical and temporal sampling processes, and the filtering required to avoid issues are detailed in a BBC Engineering Report publish in 1984. This paper is available to download for personal use from the BBC website here. This paper describes the sampling processes in a 625 line PAL system, but the principles are equally applicable to a DCI Ultra-HD scan system and to the graphics displays used by computer systems.

A significant difference between computer displays and television systems is the computer monitor direct connection to the graphics card supports much higher bandwidth signals than the broadcast signals that may have to travel through a controlled bandwidth RF transport system. Thus TV signal pre-filtering ahead of the sampling processes must be incuded in the signal management design.

When a TV camera was pointed at an optical caption that was then moved (for example a roller credit list) the integration of the reflected light onto the camera sensor provides both a spatial and temporal low pass filter that occurs before the sampling clocks. Making an electronic moving caption needs the same filtering if it is to avoid aliasing display defects.

When we start with a progressive scan signal form, such as 1080p50 and wish to create a 1080i25 signal we must create a low pass spatial filter to reduce the vertical domain signal content, and also apply a temporal low pass filter before we create the new sample structures. In practice the filtering and interpolation that creates the new signal form can occur in one process as the interpolation system must blend several adjacent samples and it does so using a low-pass Finite Impulse Response (FIR) filter. Ideally we need to stop vertical frequency detail above 270 c/aph where the source signal could have used up to 540 c/aph. The pass band of the low pass filter is a rectangular shape. When we use Fourier to transform between spatial and frequency domains the rectangular shape becomes a sin(x)/x function that we use to determine the weighting gains in the taps of the FIR filter.

The suggestions of ensuring equal energy in the two fields, and moving at an even number of lines per frame both contribute to the alias-avoidance schemes.

The perfect solution to the issues described by the original poster would require some major re-writes in the chromium framework, so I suspect the only realistic mechanisms are issue avoidance strategies described by @Nytamin and @silid.

If there is sufficient memory in the CasparCG server in use, it may also be possible to create multiple versions of the rendered graphic each instance using a fractional line offset with ant-alias pre-filtering when the graphic is loaded. This may, of course, impact on load latency for the graphic. When movement is required the relevant offset version is then bit-blatted into an HTML canvas element which should be a computationally efficient process.

2 Likes

I alleviated this type of problem by applying a slight vertical distortion to the layer, with settings such as:

  • top: -1

  • height: 1082

Similarly, for horizontal crawls that had aliasing issues, the most effective solution I found after many tests was to apply a distortion filter, setting the width to 1922px, since I couldn’t enable antialiasing filters in Caspar.

I know, it’s not an elegant solution but it’s the only one I’ve found that works well enough.

Andrea.

Hi Andrea,

I think I might be misunderstanding where to apply the settings. Could you please elaborate a little more about your solution.

Thanks,

I applied the scale on the Caspar mixer on the layer where the HTML scene is running
You can use the Distort Filter from CasparCG Client or write commands direct to the server.
I’m using these parameters:
MIXER 1-20 PERSPECTIVE 0 -0.000925926 1.00052 -0.000925926 1 1 0 1 0 Linear

alright thank you for your suggestion.