Skip to content

Releases: rmotafreitas/react-native-anything-player

v1.5.1

Choose a tag to compare

@github-actions github-actions released this 04 Nov 10:48
ece36a1

1.5.1 (2026-11-04)

A fix for the jump a live quality switch reports, and corrected docs and notes after 1.5.0. Nothing is removed or renamed; upgrading needs no change.

Fixed

  • A switch's jump is null when a connection jumped first. A live quality switch that could not be lined up because a connection was replaced or jumped reported, as its discontinuity's jump, a gap measured before that jump: a precise-looking wrong number. It is now null (not known). The same applies to a switch already given up for another reason when a connection jumps before it takes over. On iOS, Android and the web.
  • The docs describe 1.5.0's rule everywhere. The discontinuity TSDoc, Events and Internet radio say that any live switch while the app holds a pick can go ahead with a discontinuity. Playback's WebKit measurement says it was taken under 1.4.0's refusal rule. 1.5.0's notes now say why it is a minor, that a pick goes ahead once lining it up is given up (within 30 s), and that QUALITY_SWITCH_FAILED has other causes too (Errors).

v1.5.0

Choose a tag to compare

@github-actions github-actions released this 04 Nov 00:45
0120dbd

1.5.0 (2026-11-04)

A live quality pick that cannot be lined up goes ahead instead of being refused, and an app that keeps its own place in the station's timeline hears of the jump before the title. Nothing is removed or renamed. One documented live-stream behaviour changes: see Upgrading. By what a version number promises that would call for a major; it is a minor because 1.4.0 had been out for a few hours, the change only lets a pick through that was refused, and an app that follows 1.4.0's advice needs no change.

Added

  • A live quality pick that cannot be lined up goes ahead. A live switch the app picked with selectQuality used to be refused (QUALITY_SWITCH_FAILED) when it could not be lined up with what is heard, and tried again a minute later. A pick that can never be lined up, such as a new connection behind what is heard on iOS (AVPlayer cannot run a live stream faster), then never landed. While the app holds a pick, a live switch is now lined up when it can be, and otherwise goes ahead with a discontinuity (reason: 'switch') once lining it up is given up (within 30 s), as a switch the player needs already did. Automatic quality (a step up) still waits for one that can be lined up. See Live renditions (a4f6ac5).

Fixed

  • A switch that went ahead without being lined up reports its discontinuity before the title the new connection reached. The title came first, so an app that places its song again on discontinuity took it for a song change heard at the song's start. Now the title told after the discontinuity is known to be partway into its song. On iOS, Android and the web (2c7e5f9).

Upgrading

  • A pick is no longer refused when it cannot be lined up. It goes ahead with a discontinuity instead. An app that re-opened the source on QUALITY_SWITCH_FAILED to force its pick through can stop doing so, and should place its position again on discontinuity, as 1.4.0 already advised. QUALITY_SWITCH_FAILED no longer comes from a pick that could not be lined up; it still comes from a switch whose new connection fails or is not ready in time (it sits out a minute and is tried again), and from an automatic step up that was refused. See Errors.

v1.4.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 22:26
a96d255

1.4.0 (2026-11-03)

Live quality switches that line up with what is heard, and voice and car playback on a fresh install. Nothing is removed or renamed. A few live-stream behaviours change, and an app that handled them itself may need to stop doing so: see Upgrading.

Added

  • Live quality switches line up with what is heard. A switch between live renditions (Icecast mounts at different bitrates, HLS or DASH renditions with program dates, live MPEG-TS sound channels) no longer repeats or skips audio. The new connection is played muted, a little faster or slower, until it reaches the same point in the program, then takes over: within about 0.3 s in Chromium, Firefox, WebKit and on Android, where switches used to land up to 18 s off. Sources that can never be lined up switch as before: a browser's plain <audio> (a stream without CORS), a live TS channel with a picture in a browser, and every live TS channel on iOS. iOS has the code for the rest but has not been recorded on a device yet. See Live renditions.
  • liveOffset is the whole delay behind live: the server's burst, the buffer and the decoder. On a progressive stream (ICY, plain HTTP, live TS) it is measured from what has arrived, so it holds steady while audio plays, grows while paused or stalled, and carries on across a lined-up switch. HLS and DASH report their own clock.
  • liveOffsetSettled (on getProgress() and progress) turns true once the connect burst has arrived and liveOffset has held for 3 s, so a delay shown to the user, or lyrics placed against it, does not move. It turns false again after a discontinuity or a new load.
  • programDate: the epoch milliseconds that the stream's own clock gives what plays now (HLS EXT-X-PROGRAM-DATE-TIME, DASH), null without one. On iOS, DASH converted for AVPlayer now carries program dates too.
  • discontinuity says why and by how much: reason ('reconnect' or 'switch') and jump (seconds skipped, or heard again when negative; null when unknown).
  • A catalog the app bundles, for voice assistants and cars on a fresh install that was never opened. With Expo: ["react-native-anything-player", { "catalog": "./catalog.json" }], checked at prebuild with setCatalog's rules. Bare apps write the same file into their assets. See Voice assistants (#80).
  • A voice request or car pick for what is already loaded plays on: no gap, and the app's updateNowPlaying fields, headers and DRM stay. A catalog item can set the quality it starts at.
  • Cars for one platform: the plugin's car: { ios: false } sets up Android Auto alone, and { android: false } sets up CarPlay alone. CarPlay's scene is added in any plugin order, including with expo-build-properties' ios.enableSceneSupport.

Fixed

  • A player released and created again with the same id is a new one. A remount in the same tick used to attach to the player being released, which then ended it ("The player was released" on the next command). A released player's late commands, events and status never reach the new one either (#90).
  • After a JavaScript reload, the old runtime's late release can no longer end the new runtime's player.
  • On Android, an assistant request that opens a fresh install before the app has a catalog now waits for setCatalog and plays then, instead of opening the app idle (#79).
  • On Safari for iPhone and iPad, a live stream plays through MSE again. It had fallen back to the plain element, which meant no ICY titles and no visualizer.
  • The visualizer works for streams in Safari and every iOS browser. It used to draw a flat line, because WebKit reads silence from a stream played through MSE.

Upgrading

  • A live switch that cannot be lined up is refused when it is optional. A quality pick or an automatic step up that cannot be lined up (for example, the new mount has not settled) keeps the current quality and reports a non-fatal QUALITY_SWITCH_FAILED. Do not re-open the source when you get it: that brings back the gap this release removes. A switch the player needs, because the current connection stalled, still goes ahead and reports a discontinuity with reason: 'switch'.
  • A lined-up switch reports no discontinuity, and positions carry on. An app that keeps its own place in the station's timeline (a song's progress, lyrics) should place it again on discontinuity, not on every change of status.quality.
  • liveOffset reads larger than before on progressive streams (it now includes the whole delay) and can be null until there is something to measure. Wait for liveOffsetSettled before showing it.
  • TypeScript: progress readings gain liveOffsetSettled and programDate, and discontinuity gains reason and jump. Code that only reads them needs no change. A test fake that builds these objects needs the new fields.

v1.3.1

Choose a tag to compare

@github-actions github-actions released this 31 Oct 00:04
3b3046e

1.3.1 (2026-10-30)

Quality switching for audio players. This release adds features, so by Semantic Versioning it should have been 1.4.0: the release tool missed the commits that added them. Nothing is removed or renamed, so upgrading is safe.

Added

  • Audio renditions. An audio Player takes renditions, separate files of one sound (e.g. MP3 at 320 and 192 kbps and AAC+ at 64 kbps), and switches between them with no gap, as video does. On iOS and Android this needs no video module; the second player is made only at the first switch. On the web, AirPlay and the visualizer follow the file that is playing. See Qualities.
  • Automatic quality for audio players. Every player now reports its bandwidth. An audio player starts at the highest quality (a file starts at what the last reading fits), and two stalls within 30 s step it down. A live stream steps up again after 120 s without a stall; a step up that stalls again waits twice as long next time.
  • A quality pick that holds. selectQuality(id) and the new load(source, { quality }) are kept for the next loads, matched by id; 'auto' clears the pick. Rendition.id gives stable ids (default r<index>). JavaScript refuses an unknown or duplicate id, and 'auto', before anything changes.
  • A failed switch is reported: a non-fatal error with the new QUALITY_SWITCH_FAILED code and the new file's own failure in cause. The current file plays on. See Errors.

Fixed

  • selectQuality('auto') lets go of a kept pick even when the current source has nothing to pick from.
  • On Safari with AirPlay (as on Cast), a quality switch re-opens the item in place instead of moving to an element the receiver isn't playing.
  • The background, listen-only mode and the audio fallback never lower an audio player's quality.

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 30 Oct 16:28
8900763

1.3.0 (2026-10-30)

Video, on every platform, as an opt-in part of the same player. Audio apps get the fixes below; the only change to plan for is the JavaScript size (see Upgrading).

Added

  • Video. new Player({ video: true }) plays a picture with the same engine, recovery, events and lock-screen integration as audio. <VideoView player={player} /> shows it in React Native, React Native Web, Expo web and React DOM, and player.attachTo(element) on any web page; a player outlives its views, and moving it between views has no gap. Files, HLS and DASH (Shaka on the web, rewritten as HLS for AVPlayer on iOS); renditions (one file per quality) switched behind the picture without a gap; quality caps for the view's size, metered networks and Data Saver; fullscreen, Picture in Picture and whenBackgrounded (pause, audio, pip); nativeControls; posters, thumbnails, seekTo(t, { exact }), loop and playback stats. The qualities to pick from are on the status itself (status.qualities, status.quality, status.selectedQuality), for selectQuality(). Opt-in on iOS and Android with the Expo plugin's video option (npx rnap add video, rnapVideo=true / RNAP_VIDEO=1 without Expo); always available on the web. See Video.
  • Matroska, WebM and MPEG-TS everywhere, files and live IPTV channels, with their audio languages and subtitles. Nothing is transcoded: ExoPlayer reads them, and RNAP remuxes them for AVPlayer and for browsers (on the web the server must allow CORS).
  • Subtitles and tracks. SubRip, WebVTT, TTML and basic ASS files, encoding detection, a source's own audio languages and subtitles, one overlay that follows the OS caption style, useCues(), subtitleDelay, and an automatic choice from the OS languages and accessibility settings. See Subtitles.
  • DRM. FairPlay, Widevine, PlayReady and Clear Key: license servers with headers, Clear Key keys in the source, or the app's own getLicense exchange. FairPlay is not yet tried on hardware.
  • Video over Google Cast and AirPlay, with the app's subtitle files on Cast receivers.
  • Android software decoders (npx rnap add video-decoders, rnapVideoDecoders=true): FFmpeg for Dolby, DTS and MPEG audio, libvpx and dav1d for VP9 and AV1, used only for what the device cannot decode. They are built in CI from pinned sources and downloaded from this repository's releases, checked against pinned checksums.
  • A feature matrix of what audio features do on a video player, per OS and browser engine (Features).

Fixed

  • A playback rate holds across loads. On the web, a new source (or hls.js and Shaka attaching later) reset it to 1x while status.rate kept the old one; on iOS, a load could start at the default rate; on Android, the rate did not follow the audio to a Cast receiver and back. A Cast receiver now plays the rate set, between 0.5x and 2x, on every platform (#49).
  • The duration and seek range follow what the platform learns. A fragmented MP4 that reports 18 s at first, then 600 s, no longer keeps seeks clamped to 18 s, and a start position past an early duration waits for the longer one; a Cast receiver's later duration reaches the player too, and an unknown one taken for live becomes a file once known (#50).
  • A stall in the last frame of a file ends it. WebKitGTK could stop a few milliseconds before the end without ended; the engine re-opened the item at its end every few seconds, forever, so a queue or a sleep-at-end never moved on. All three engines now end (or loop) the item (#59).
  • A transient media-pipeline failure is retried. On the web, a MediaError 4 from an element that hls.js, the remuxer or MSE feeds, after its metadata loaded, was reported as a fatal UNSUPPORTED_FORMAT; on iOS and Android, a decode or parse failure after the item was ready was fatal too. It is now a recoverable DECODER_ERROR, and the engine re-opens the item (#58).
  • A player that plays without saying so (WebKitGTK at readyState 2) is treated as playing once its playhead runs, instead of being re-opened as a dead stall.
  • Android reports no duration for a live stream (the live window's length changed on every refresh), as iOS and the web do.

Changed

  • A start position costs no wasted request. hls.js starts loading at the segment that holds it, and iOS seeks the item before it reaches the player, instead of fetching the first segment first (#57).

Upgrading

  • More JavaScript. The React Native entry is about 16 KB gzipped (6 KB before), and a web page loads about 56–57 KB (31 KB before), because the video API, the engine's video rules and the subtitle parsers' entry points are part of the main entries, even for an app that plays only audio. Native code for video is only built when you turn it on. See Comparison.
  • Nothing else changes for audio apps: no API was removed or renamed.

Video preview 0 (feat/video @ dc61d03)

Pre-release

Choose a tag to compare

@rmotafreitas rmotafreitas released this 27 Oct 21:03

Pre-release build of the feat/video branch (draft PR #46) at dc61d03, packed for apps that need video before it is merged and released. Not a release-please release: releases/latest stays on v1.2.1.

  • Package version inside: 1.3.0-video.0
  • Built with yarn prepare && npm pack (same steps as the release workflow), Node 24.22, Yarn 4.11
  • SHA-256 (react-native-anything-player.tgz): ed383a46f6020d626ae6da77aa17430189ccf2034082819b596df6178e3b8b21
bun add https://github.com/rmotafreitas/react-native-anything-player/releases/download/video-preview.0/react-native-anything-player.tgz

v1.2.1

Choose a tag to compare

@github-actions github-actions released this 24 Oct 02:41
856fe7f

1.2.1 (2026-10-24)

Reliability fixes across the three engines and the iOS, Android and web hosts. Late callbacks, timeouts, stalls and reconnect: false now behave the same everywhere (22 new conformance scenarios, 127 in all). Three behaviours are stricter (see Upgrading).

Fixed

  • Engine (iOS, Android, web)
    • A late end or failure from an item that was stopped, failed or released no longer turns the player into ended or error. An item that ends during a stop's fade-out stays stopped, and a repeated end is reported once.
    • load() without autoplay (or paused while loading, or refused audio focus) times out after 12 s instead of waiting forever.
    • A silent stall (the playhead freezes while the native player says it is playing) ends as soon as audio moves again, instead of being re-opened from the start. A re-opened file resumes where the playhead got to.
    • recovery.reconnect: false is honoured everywhere. Stalls, network changes, returning to the foreground, media-services resets and the drivers' own connection splicing no longer re-open on their own.
    • A source loaded with live: false ends at its end even when its duration is unknown, instead of reconnecting.
    • Returning to the foreground at the same moment as a network restore no longer aborts the fresh connection.
    • A sleep timer or fade longer than 24 h is rejected instead of crashing (iOS) or firing at once (Android).
    • ICY: whitespace between fields (StreamTitle='…'; StreamUrl='…';) no longer leaks into the title, and the artwork URL is read.
  • iOS
    • HLS streams whose URL does not end in .m3u8 play: the stream proxy hands the playlist to AVFoundation instead of breaking its relative segment URLs.
    • A file served without Content-Length and loaded with live: false ends instead of starting over.
    • The Sound API no longer switches a Player's audio session to ambient, which would make the Player obey the silent switch and lose background audio. A Player restores its category when something changed it.
    • The visualizer no longer works on the audio render thread, and it stops with its item.
  • Android: the Cast title reader keeps asking for ICY metadata, even when the source's headers say Icy-MetaData: 0.
  • Web
    • A play refused by the browser's autoplay policy (from a media key, for instance) no longer makes the next, unrelated command reject with AUTOPLAY_BLOCKED.
    • Releasing a player closes its visualizer's AudioContext (browsers limit how many a page may have).
    • Google Cast tries to load its SDK again after a failure (offline at page load, for instance).
    • A stream whose buffer stays full is ended and recovered, instead of silently skipping audio.
  • Packaging: tarballs packed with Yarn include the Codegen specs (src/native), and the exports map lists ./app.plugin.js.
  • Expo plugin: a project name containing a backslash or a quote no longer breaks the App Intents entry in the Xcode project.

Upgrading

  • reconnect: false is now strict. A stall or a lost connection ends in a fatal NETWORK_ERROR instead of recovering; call play() to retry. With reconnect left on (the default) nothing changes.
  • load() with autoplay: false can reject with TIMEOUT when the source does not answer within 12 s.
  • Durations over 24 h in sleep(), fadeTo() and fade reject with INVALID_ARGUMENT.
  • Files served without Content-Length: load them with live: false so they end at their end (iOS used to treat them as radio).

Android software decoders (android-decoders-1.11.1-1)

Choose a tag to compare

Media3's software decoders for Android, built by scripts/decoders/build-android.sh at 494d392.
Apps get them with rnapVideoDecoders=true. FFmpeg is LGPL; see the Video guide.

3960872ec58ff265c71314cf8224629e1d0ab6db3d0761ad4761f6d9bc1f35e9  media3-decoder-av1-1.11.1.aar
8377f18592455cda0a954103e0c08bbad54072173fcf65580430c7b1fcd07256  media3-decoder-ffmpeg-1.11.1.aar
443b0bf5baaceb44b826713cc3203326d8dfd53791916efa8cfc9709d70fb5ad  media3-decoder-vp9-1.11.1.aar

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 00:15
d275bff

1.2.0 (2026-10-23)

Short sounds, cars and watches, a sleep timer, and a CLI that sets up the optional parts. Everything is additive except one rule for catalog ids (see Upgrading).

Added

  • Sound API (react-native-anything-player/sound): short sounds for UI clicks and games, preloaded into memory and played with low latency. Several voices at once (the oldest is stolen when all are busy), per-play volume, rate, pan and loop, a handle per voice, and stopAll(). It mixes with other audio and has no media session. iOS on AVAudioEngine, Android on one shared SoundPool (32 voices), the web on Web Audio. Opt-in on iOS and Android with the Expo plugin's sound option (rnapSound=true / RNAP_SOUND=1 without Expo); always available on the web. New error code SOUND_UNAVAILABLE. See Sound.
  • Cars and watches. Catalog items take a group ("Jazz", "Podcasts/Daily"), and the catalog becomes a browse tree in CarPlay, Android Auto, Android Automotive OS and Wear OS, with "Recently played" and favorites (setCatalog(items, { browse }), setFavorites(ids)). A pick plays through the same path as a voice request and is reported as searchPlay with request.origin: 'browse'. Long folders are split for car screens, and searchCatalog / playFromSearch filter by group. CarPlay and Android Auto are opt-in with the plugin's car option (rnapCar / RNAP_CAR without Expo); Wear OS needs nothing. See Cars & watches.
  • Sleep timer and fades. player.sleep({ after, fadeOut }) pauses after a delay, fading out first; sleep(null) cancels it, status.sleepAt and a sleep event report it, and useSleepTimer() counts down. Opt-in fades on play, pause and stop (new Player({ fade: { in, out } }), setFade()), and fadeTo(volume, seconds). The native engine runs them, so they keep working while JavaScript is frozen in the background. 25 new conformance scenarios, passed by all three engines. See Playback.
  • CLI: modules, size, info, migrate. npx rnap is the documented name. rnap modules, rnap add and rnap remove turn the optional parts on and off (HLS, Cast, Siri, Assistant, the iOS background mode, the Sound API, cars) by writing gradle.properties, Podfile.properties.json or the Expo plugin's options, after showing the diff. rnap size shows what each costs in a release APK and a web page. rnap info prints a report to paste into a bug report. rnap migrate rewrites react-native-track-player, expo-audio and expo-av code to RNAP where the mapping is mechanical, and marks the rest. A write is atomic and refused if the file changed after its diff was shown. doctor reports module settings that disagree. See CLI.

Changed

  • Web: less JavaScript on page load. The hls.js glue loads when hls.js is registered (configureHls), and Google Cast's driver and Firefox's MP4 repackaging only when they are used: about 8 KB a page without them never loads. The Sound API is its own entry, so a page that only streams does not load it.
  • The API reference has a player and a sound section; links to its old paths redirect.

Upgrading

  • Catalog ids starting with rnap: are rejected with INVALID_ARGUMENT, because the browse tree names its folders with that prefix. Rename such ids before upgrading. No other change is needed.

v1.1.1

Choose a tag to compare

@github-actions github-actions released this 22 Oct 20:34
f7320f3

1.1.1 (2026-10-22)

Fixed

  • android: no crash when the network is reported as the runtime starts (f23a5bb)
  • package: ship only what apps use (bcefa0f)
  • package: ship the Codegen specs and the autolinking config (877047c)

Changed

  • android: leave out of R8-shrunk apps what RNAP does not use (5f98caf)
  • web: load Google Cast and the MP4 repackaging only when used (808f335)