Mobile Development 15 min read

How Bilibili’s Chronos Engine Powers Real‑Time Support Bullet‑Screen Word Clouds on Mobile

This article explains how Bilibili’s Chronos cross‑platform engine enables a new support‑bullet‑screen feature that turns user comments into animated word‑cloud overlays on video, detailing the client‑side layout algorithm, integral‑image optimization, spiral point generation, and worker‑thread rendering to achieve sub‑second performance on mobile devices.

Bilibili Tech
Bilibili Tech
Bilibili Tech
How Bilibili’s Chronos Engine Powers Real‑Time Support Bullet‑Screen Word Clouds on Mobile

Chronos Rendering Engine

Chronos is Bilibili’s cross‑platform rendering engine for Android and iOS. It is written in TypeScript and offers high‑level APIs for drawing text, graphics and animations efficiently.

Support‑Bullet‑Screen (Support Danmaku)

The feature maps user comments onto a background image, forming a word‑cloud that fills the image while animating, thereby increasing interaction during video playback.

progress – time offset when the bullet appears

duration – how long the bullet stays on screen

position – screen coordinates for the bullet group

picture – background image used as the word‑cloud canvas

dms – array of comment data to be placed inside the cloud

Layout Strategy

Two approaches were evaluated:

Client‑side real‑time layout calculation before each display.

Server‑side pre‑computed layout sent to the client.

Client‑side layout was chosen because server‑side results cannot guarantee consistent font rendering across devices and would lose per‑bullet animation.

Word‑Cloud Fill Implementation

Fillable regions are identified by reading the alpha channel of the background image. Pixels with zero alpha are marked as occupied.

image.toPixelData().forEach((pixel, index) => {
  if (pixel.alpha <= 0) {
    this._filledSet.add(index);
  }
});

To test overlap quickly, an integral image (summed‑area table) is built. The sum of a rectangular region can be obtained with four look‑ups:

const totalPixelCount = this._integralPixelArray[this.positionToIndex(maxCol, maxRow)];
const topPixelCount = minRow <= 0 ? 0 : this._integralPixelArray[this.positionToIndex(maxCol, minRow - 1)];
const leftPixelCount = minCol <= 0 ? 0 : this._integralPixelArray[this.positionToIndex(minCol - 1, maxRow)];
const leftTopPixelCount = (minRow <= 0 || minCol <= 0) ? 0 : this._integralPixelArray[this.positionToIndex(minCol - 1, minRow - 1)];
return totalPixelCount - topPixelCount - leftPixelCount + leftTopPixelCount <= 0;

Integral Image Construction

for (let col = 0; col < this._width; col++) {
  for (let row = 0; row < this._height; row++) {
    const index = this.positionToIndex(col, row);
    this._filledArray[index] = this._colorArray[index][3] > 0 ? 0 : 1;
    this._integralPixelArray[index] = this._filledArray[index];
    if (col > 0) {
      this._integralPixelArray[index] += this._integralPixelArray[this.positionToIndex(col - 1, row)];
    }
    if (row > 0) {
      this._integralPixelArray[index] += this._integralPixelArray[this.positionToIndex(col, row - 1)];
    }
    if (col > 0 && row > 0) {
      this._integralPixelArray[index] -= this._integralPixelArray[this.positionToIndex(col - 1, row - 1)];
    }
  }
}

Greedy Placement with Rectangular Spiral

A rectangular spiral generator produces candidate points starting from the image centre. The algorithm moves each comment rectangle along the spiral until the integral‑image check reports no overlap.

function createRectSpiralGenerator(width, height, dt) {
  let x = 0, y = 0;
  return function(t, offset = 0) {
    t = t + offset;
    const sign = t < 0 ? -1 : 1;
    const num = Math.ceil(Math.sqrt(1 + 4 * t * sign) - sign) & 3;
    if (num === 0) x += dt;
    else if (num === 1) y += dt;
    else if (num === 2) x -= dt;
    else y -= dt;
    return { col: x + Math.floor(width / 2), row: y + Math.floor(height / 2) };
  };
}

Asynchronous Layout and Rendering

Layout and fill calculations run on a worker thread. The main thread receives incremental results and updates the screen in small batches, avoiding long VSYNC stalls.

App.getTaskWorkerBinder()?.sendMsg(Task.WORD_CLOUD_UPDATE, { timeout, count }, (response, expired) => {
  const textureKey = response.key ?? null;
  if (expired) {
    cron.TransferCenter.instance.popObjectForKey(textureKey)?.release();
    return;
  }
  const count = response.count ?? 0;
  const completed = response.completed ?? false;
  const success = response.success ?? false;
  if (completed) this.reportShowEventIfNeeded(success, count);
  else this.triggerWordCloudEngineUpdate();
  const texture = cron.TransferCenter.instance.popObjectForKey(textureKey);
  this._displayer.addOneGroup(texture, completed, success);
  texture.release();
});

Rendering Optimizations

Layout results are batched into multiple textures. Blending modes are used to compose these textures, reducing draw calls and keeping the animation smooth.

Rendering optimization diagram
Rendering optimization diagram

Performance

On a 600 × 600 background image the complete layout and fill process finishes in under 1.5 seconds on typical mobile hardware. By splitting the work into incremental worker messages, the perceived latency drops to a few frames, preventing noticeable frame drops.

Conclusion

The client‑side implementation delivers a responsive support‑bullet‑screen with real‑time word‑cloud layout. Integral images, rectangular‑spiral candidate generation, and asynchronous processing together satisfy the strict performance constraints of mobile video playback while preserving per‑bullet animation.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

MobileanimationReal-TimeRenderingTypeScriptword cloud
Bilibili Tech
Written by

Bilibili Tech

Provides introductions and tutorials on Bilibili-related technologies.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.