Repository navigation
alpha-video-gpu 1.0.0
First public release.
- Plays transparent animations stored as ASTC texture arrays in KTX2 files. Metal on iOS, OpenGL ES on Android, WebGL 2 on the web.
- Streaming (
stream, on by default) and preloaded playback, with frames in VRAM (memoryStrategy="vram", the default) or RAM. Streaming takes KTX2-internal zstd and uncompressed (memory-mapped) files. One setting,streamingPrefetchAhead(1 to 100), sets how many frames are kept decoded after the shown one; the player holds that many plus 2, on the GPU withvramand in RAM withram. With verbose logging on, each pass logs the fewest frames it had ahead and how often it ran out, for tuning it. - Frame size, count and ASTC format come from the KTX2 header, and the frame rate from the standard
KTXanimDatakey (30 fps without it). Frame rates are fractional on every platform, so 29.97 fps (1001/30000 s per frame) plays exactly. Files in the earlier experimental formats (Basis Universal UASTC, atlas packing, GLB containers, multi-part files, whole-file.zst) are rejected; they play on thearchive/basis-atlas-partsbranch. - Sources:
https://,file://, absolute paths,asset://(Android assets, the iOS bundle, the web root), and on Androidcontent://andres/rawnames. - Android and iOS read http(s) files by range requests as they play, through the range-source add-on, instead of downloading them whole first.
source.headersgo with every request.- A streamed zstd file starts after its header and seek table, and is then read 256 KB at a time as it decodes. A seek reads from its seek point. Uncompressed files, and every file with
streamoff, are read whole first. Servers without range support work too. - Reads never block the render loop: a frame whose bytes haven't arrived is decoded on a later tick. A dropped connection is retried 3 times. A read that still fails reports
Reading <uri> failed: …throughonError, and a source that can't be opened reportsLoading <uri> failed: …. storage('auto','disk','memory','none') keeps what was played between plays, partially: a clip played through plays again offline.maxStorageBytescaps it (512 MB by default), andcacheKeynames the stored copy. Replaces the whole-file download cache.- Data sources: an app registers one under a name (range-source's
RangeDataSources, with aRangeDataSource, on both platforms) and names it insource.dataSource, to read the bytes with its own HTTP client, cache or decryption. One registration serves this player andalpha-video.dev.mediacache:range-source-media3adapts any Media3DataSource.Factoryon Android. - range-source is found at runtime, and included by default: a dependency of
dev.mediacache:alpha-video-gpu(dev.mediacache:range-source), the pod'sSourcesubspec, and the Swift package's default traitSource. React Native apps installreact-native-range-sourcebeside the player. An app can leave it out (Gradleexclude,pod 'alpha-video-gpu', :subspecs => ['Core'],traits: []from a package, or not installing it). A URL is then downloaded whole into a temporary file for each play, with a warning logged once, and a data source reportsonErrorwith the codeNO_SOURCE_MODULE. An Xcode app project can't turn a package's traits off, so SwiftPM apps added in Xcode always have it. - On iOS, setting
sourceloads it on the next main-queue turn, so the other properties can be set in any order, and changing the source frees the previous one's resources first.
- A streamed zstd file starts after its header and seek table, and is then read 256 KB at a time as it decodes. A seek reads from its seek point. Uncompressed files, and every file with
- The web player reads files by range instead of downloading them whole, through range-source-web, an npm dependency of
alpha-video-gpu-web.- A URL streams after its first few hundred kilobytes, and a seek fetches from its seek point on. Servers without range support are read progressively.
setSource(source, { cacheKey, headers })also takes aBloborFile, anArrayBufferorUint8Array, or a byte source ({ size, read(offset, length, signal) }) for an app's own fetcher or cache.headersgo with every request. The React component and React Native Web take the same, throughsrcorsource.storagekeeps what was played between visits:'auto'(OPFS, else IndexedDB; the default for URLs),'opfs','indexeddb','cache','memory','none', or a custom store.maxStorageBytescaps it (512 MB by default), evicting the least recently played. A clip stored whole plays again offline. A partial copy is dropped when the file'sETag,Last-Modifiedor length changes.- With
'none', clips up to 16 MB stay in memory, so loops don't fetch again. And with any storage, a streamed clip whose frames all fit the streaming buffer loops without reading or decoding again. - Replaces the IndexedDB whole-file cache, and its
getCachedFileandsetCachedFileexports.
- Playback control:
play,pause,stop,seekToFrameandseekToTimeon every platform, pluspaused,autoPlay,loopandplaybackSpeed. testIDreaches the view on every platform, including React Native Web.- Events:
onLoad,onFrameUpdate(withenableFrameEvents),onStateChange,onFinishedandonError.onErrorhas acodefor errors an app may handle:NO_SOURCE_MODULEon Android (PlayerCallback.onError(error, code)), iOS (theonErrorblock'scode) and React Native, andASTC_UNSUPPORTEDorWEBGL_UNSUPPORTEDon the web. - A software ASTC decoder for emulators, devices and browsers without ASTC. On the web it's the same decoder compiled to WebAssembly, loaded only by browsers without
WEBGL_compressed_texture_astc; they reportASTC_UNSUPPORTEDonly if WebAssembly is blocked as well. - Streaming seeks start at seek points. When a zstd level ends with a seek table (zstd's seekable format, written by alpha-video-gpu-encoder's
--seek-interval), a seek starts decoding at the zstd frame before its target, or carries on from the decoder if that is closer. Files without a table play as before, and seek from the start of the file.- A long catch-up to a seek runs in slices: 8 ms per task on the web, per display tick on iOS, and 16 ms per render-loop pass on Android, so drawing, input, later seeks and teardown aren't held up.
- Streamed zstd levels made of several frames decode on every platform. iOS stopped decoding at each frame end, and its seeks stopped skipping there, landing on the wrong frame.
- Decoders no longer lose the last bytes when the input runs out while zstd still holds output (Android, iOS and the web). The web decoder also stops on corrupt data, where it used to loop forever.
- The web player feeds zstd 256 KB of input at a time and decodes straight into frame buffers. Before, every start copied the whole level into WebAssembly memory, and each frame was gathered by re-copying a growing buffer.
- Web streaming no longer stalls when a seek restarts decoding in the same task as an earlier seek or
play()(seen withmemoryStrategy="ram", after a seek back to the start). - Colours reach the screen exactly as encoded on every platform. iOS devices sample ASTC as plain (LDR) data, like Android and the web; before 1.0.0 they sampled it as sRGB, which darkened mid-tones by about half and gave semi-transparent edges dark fringes.
- React Native: one
AlphaVideoGpuViewfor Android, iOS and react-native-web, on both the new architecture (Fabric) and the old one. - Standalone Android and iOS libraries, and
alpha-video-gpu-webfor plain JS/TS and React. - Android libraries are linked for 16 KB pages.