Player controls for the ZTSL audio/lyric container format: decode a .ztsl file and get audio playback with synchronized, scrolling lyrics.
This repository holds two packages that build on each other:
| Package | What it is |
|---|---|
| ZTSL.Player.Core | Platform-agnostic decoder. Reads a .ztsl stream, decodes the Opus audio to PCM, writes WAV, and exposes a timestamped lyric timeline. No UI. |
| ZTSL.Player.Blazor | Plug-and-play Blazor Server component built on Core. Drop in <ZtslPlayer Source="@bytes" /> and get audio + scrolling lyrics for free. |
Both are on nuget.org: ZTSL.Player.Core · ZTSL.Player.Blazor.
// Program.cs — two lines
builder.Services.AddZtslPlayer();
app.MapZtslPlayer();@if (data is not null)
{
<ZtslPlayer Source="@data" />
}Where data is a byte[] of .ztsl content (load it from disk, blob storage, an HTTP response — wherever). The component owns decoding, WAV serving with HTTP range support, and lyric sync; you never touch a Guid, a URL, or a parallel lyric list.
If you're building your own player UI, use Core on its own:
using var stream = File.OpenRead("song.ztsl");
var ztsl = new ZTSLContent(stream);
byte[] wav = WavWriter.Write(
ztsl.PcmTrimmed,
ztsl.AudioStreamDescriptor.Channels,
ztsl.AudioStreamDescriptor.SampleRate);
foreach (var line in ztsl.LyricTimeline)
Console.WriteLine($"{line.TimestampMs} ms: {line.Text}");ZTSL.Player.Blazor depends on ZTSL.Player.Core, which in turn depends on the closed-source ZTSL format library. Adding the Blazor package resolves both transitively.
ZTSL is a single-file container that interleaves Opus audio with a timestamped lyric stream. The format specification is published at SHW511/ZTSL; the format library itself ships as a closed-source NuGet package.
Apache-2.0. See LICENSE.