Technical Solution and Performance Optimization for Animated Lyrics Using ASS Subtitle Rendering on Mobile
The project replaces karaoke effects with ASS‑based lyrics on Android, using a backend to generate ASS files and a JNI renderer that rasterizes and composites bitmap fragments; optimizations like transparent‑fragment filtering, opacity early‑out, NEON SIMD, copy elimination, and double‑buffered decoding cut frame time from 52 ms to under 3 ms, raise frame rate from 7 fps to 15 fps, and shrink memory usage from 180 MB to under 10 MB.
Lyrics browsing is a standard feature in music apps, usually implemented with simple per‑character karaoke coloring or multi‑line scrolling. The goal of this project is to improve the basic lyric experience and provide differentiated VIP effects to encourage subscription.
After several requirement reviews, three technical directions were considered: upgrading the existing lyric component, using a Shader‑based sprite‑sheet animation, and using an ASS (Advanced SubStation Alpha) subtitle‑based sprite‑sheet animation. The ASS approach was selected because it supports per‑character animation via K‑tags, has open‑source support, and is cross‑platform.
The final architecture splits responsibilities: the backend stores and composes the ASS files, while the client parses and renders the resulting bitmap frames.
ASS workflow : a text file is enriched with K‑tags (time‑coded karaoke tags) to produce an ASS file. The ASS file is parsed together with a font library to rasterize each subtitle line into one or more small bitmap fragments. These fragments are then composited into a large bitmap that is displayed at a fixed frame rate.
The implementation on Android uses a JNI interface:
private native int decodeFrame(long time, int[] pixels);Java passes the current timestamp and an int[] buffer to the native libass code, which parses the relevant subtitle events, rasterizes them into small bitmaps, composites them into a large bitmap, and copies the result into the pixel buffer. The bitmap is then wrapped into a Canvas for rendering.
Performance bottlenecks identified were noticeable stutter (7 fps on a Samsung Note 3) and high native memory usage (≈180 MB). The following optimizations were applied:
Filter transparent fragments : skip generation of completely transparent small bitmaps, reducing parsing overhead and memory allocation.
Pixel opacity checks : during compositing, early‑out for fully transparent (k==0) or fully opaque (k==255) pixels. if(k == 0){ // fully transparent continue; } if(k == 255){ // fully opaque dst = color; continue; }
Simplify alpha calculations : replace division by 255 with a right‑shift and use bitwise NOT for 255‑x, turning a costly expression into a single multiplication and bit‑shifts. dstA = ~((~k) * (~dstA)) >> 8);
Parallel NEON computation : process eight pixels simultaneously using 128‑bit NEON registers, achieving roughly an 8× speed‑up for the compositing loop.
Remove pixel copy : write composited results directly into the JNI‑provided int[] buffer, eliminating an extra native memory copy (≈11 ms saved).
Eliminate Bitmap setPixels copy : use reflection to obtain the Bitmap buffer and write directly, reducing rendering time by about 65 %.
Double‑buffer asynchronous rendering : decode frames in one thread while rendering in another, swapping two buffers to avoid race conditions. This decouples decoding from rendering and improves frame throughput.
After these optimizations, per‑frame compositing time dropped from 52 ms to under 3 ms, and the complex effect’s frame rate on the Note 3 increased from 7 fps to 15 fps.
Memory optimization : libass’s default cache (128 MB bitmap + 64 MB composite) was excessive. Experiments showed that a total cache of 4–16 MB is sufficient, and adjusting the bitmap/composite ratio from 2:1 to 1:1.8 (i.e., allocating more to composite) achieved the same hit‑rate with only 8 MB of memory.
These changes stabilized memory usage (no longer a 180 MB spike) and reduced the risk of OOM and GC‑induced stutter.
The article concludes with a summary of the technical choices, performance gains, and a brief recruitment notice from the Tencent Music technology team.
Tencent Music Tech Team
Public account of Tencent Music's development team, focusing on technology sharing and communication.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.