spatius_avatarkit 1.3.8 copy "spatius_avatarkit: ^1.3.8" to clipboard
spatius_avatarkit: ^1.3.8 copied to clipboard

AvatarKit — real-time, audio-driven avatar rendering SDK for Flutter.

Changelog #

All notable changes to this project will be documented in this file.

1.3.8 - 2026-10-03 #

Bridges the Android 1.3.6 and iOS 1.3.6 native SDKs. Rolls up everything from the 1.3.8 beta line.

Added #

  • AvatarWidget(audioFormat:): the audio format is now set per view instead of once for the whole process in AvatarSDK.initialize(). Two views in one process can run different sample rates. Defaults to 16 kHz PCM as before; inputAudioFormat, opusBitrate and opusUplinkEnabled move with it and keep their meaning.
  • AvatarController.setAudioFormat({sampleRate, inputAudioFormat, opusBitrate, opusUplinkEnabled}): change the audio format of a live view without tearing the SDK down. Every parameter is optional (null = keep the current value). Whatever field changes, the call interrupts whatever is playing and, in DrivingServiceMode.direct, disconnects; call start() again and feed audio in the new format. Switching inputAudioFormat to AudioCodec.opus pins the sample rate at 48000; switching back to PCM keeps the current rate unless a sampleRate is passed in the same call. Accepted sample rates are 8000, 16000, 22050, 24000, 32000, 44100 and 48000; an unsupported rate, or a sampleRate paired with Opus input, is logged natively and leaves the format untouched. Same API on the Web, Android and iOS SDKs.
  • AvatarController.audioFormat(): reads the format currently in effect for the view, after the native SDK's normalization.
  • AudioFormat.toJson() / AudioFormat.fromJson(), and AudioFormat now has value equality.
  • Custom animations. An avatar can carry named animation clips authored alongside it, and the host can play them on demand: controller.playCustomAnimation(name) starts a clip, controller.getCustomAnimationNames() lists the clips that loaded and can be played, and controller.onCustomAnimationState fires with the clip name when one starts. Clips are downloaded with the avatar and prepared when the view is created, so playback starts at once and needs no driving-service connection. A clip behaves like a spoken round: onConversationState reports playing and returns to idle when it ends, interrupt() / pause() / resume() apply, and a clip started while speech or another clip is playing takes over (reported as idle then playing, like any interrupted round). There is no separate completion callback: to loop or chain clips, call playCustomAnimation again from the idle callback. An unknown name is logged natively and ignored; it does not reach onError. Same API on the native SDKs.
  • Configuration.extraParams (Map<String, String>, default empty): application-defined metadata the native SDK sends unchanged in the session handshake when it connects to the driving service. It is not used when requesting or setting a session token, and AvatarSDK.configuration() returns it. Same field on the Web, Android and iOS SDKs.

Changed #

  • Breaking: AnimationType.mono is renamed AnimationType.fallback, following the same rename in the native SDKs. It is the value onAnimationState would report while the SDK plays its locally generated animation because no server animation arrived. No alias is kept: locally generated animation is not enabled in current native releases, so no host receives this value today.
  • Both native SDKs updated to 1.3.6. Neither reports telemetry to PostHog any more (the dependency is gone from the Android POM and the iOS binary); internal events continue through the existing OpenTelemetry channel.

Fixed (native) #

  • With Opus uplink enabled (the default in Direct Mode), a round whose connection dropped while a chunk was still being encoded went silent — no sound, no motion, no fallback. Both SDKs now fall back to audio-only playback with locally generated animation, as they already did when the connection was down at send() time.
  • Android: resizing the avatar view at the moment it was being removed (for example a PlatformView being rebuilt) could crash the app with a native SIGSEGV inside the system Vulkan library. A size change that arrives while the view is being torn down is now dropped.
  • Android: a round started from inside the onConversationState(idle) callback right after interrupt() was discarded. Android and iOS: when a fallback round ends while the avatar is showing the idle loop, the loop no longer jumps back to its first frame.

Removed #

  • Breaking: Configuration.audioFormat. Pass the format to AvatarWidget(audioFormat:) instead (see Added above). No deprecation shim is kept: the native SDKs removed the field in the same way and the plugin has no process-wide format left to forward it to. AvatarSDK.configuration() no longer returns an audio format.
  • The test-only AvatarSDK.setAudioFormatForTesting(); tests create an AvatarWidget with the format they need.

Deprecated #

  • The audioFormat parameter of AvatarController.yieldAudioData() stays deprecated and ignored; the message now points at AvatarWidget.audioFormat / setAudioFormat.

1.3.8-beta.2 - 2026-09-22 #

Bridges the Android 1.3.6-beta.2 and iOS 1.3.6-beta.2 native SDKs.

Added #

  • Custom animations. An avatar can carry named animation clips authored alongside it, and the host can play them on demand: controller.playCustomAnimation(name) starts a clip, controller.getCustomAnimationNames() lists the clips that loaded and can be played, and controller.onCustomAnimationState fires with the clip name when one starts. Clips are downloaded with the avatar and prepared when the view is created, so playback starts at once and needs no driving-service connection. A clip behaves like a spoken round: onConversationState reports playing and returns to idle when it ends, interrupt() / pause() / resume() apply, and a clip started while speech or another clip is playing takes over (reported as idle then playing, like any interrupted round). There is no separate completion callback: to loop or chain clips, call playCustomAnimation again from the idle callback. An unknown name is logged natively and ignored; it does not reach onError. Same API on the native SDKs.

Changed #

  • Breaking: AnimationType.mono is renamed AnimationType.fallback, following the same rename in the native SDKs. It is the value onAnimationState would report while the SDK plays its locally generated animation because no server animation arrived. No alias is kept: locally generated animation is not enabled in current native releases, so no host receives this value today.

Fixed (native) #

  • Android: a round started from inside the onConversationState(idle) callback right after interrupt() was discarded. Android and iOS: when a fallback round ends while the avatar is showing the idle loop, the loop no longer jumps back to its first frame.

1.3.8-beta.1 - 2026-09-21 #

Bridges the Android 1.3.6-beta.1 and iOS 1.3.6-beta.1 native SDKs.

Added #

  • AvatarWidget(audioFormat:): the audio format is now set per view instead of once for the whole process in AvatarSDK.initialize(). Two views in one process can run different sample rates. Defaults to 16 kHz PCM as before; inputAudioFormat, opusBitrate and opusUplinkEnabled move with it and keep their meaning.
  • AvatarController.setAudioFormat({sampleRate, inputAudioFormat, opusBitrate, opusUplinkEnabled}): change the audio format of a live view without tearing the SDK down. Every parameter is optional (null = keep the current value). Whatever field changes, the call interrupts whatever is playing and, in DrivingServiceMode.direct, disconnects; call start() again and feed audio in the new format. Switching inputAudioFormat to AudioCodec.opus pins the sample rate at 48000; switching back to PCM keeps the current rate unless a sampleRate is passed in the same call. Accepted sample rates are 8000, 16000, 22050, 24000, 32000, 44100 and 48000; an unsupported rate, or a sampleRate paired with Opus input, is logged natively and leaves the format untouched. Same API on the Web, Android and iOS SDKs.
  • AvatarController.audioFormat(): reads the format currently in effect for the view, after the native SDK's normalization.
  • AudioFormat.toJson() / AudioFormat.fromJson(), and AudioFormat now has value equality.

Changed #

  • Both native SDKs updated to 1.3.6-beta.1. Highlights: with Opus uplink enabled (the default in Direct Mode), a round whose connection dropped while a chunk was still being encoded went silent — no sound, no motion, no fallback; both SDKs now fall back to audio-only playback with locally generated animation, as they already did when the connection was down at send() time. Neither SDK reports telemetry to PostHog any more (the dependency is gone from the Android POM and the iOS binary); internal events continue through the existing OpenTelemetry channel.

Removed #

  • Breaking: Configuration.audioFormat. Pass the format to AvatarWidget(audioFormat:) instead (see Added above). No deprecation shim is kept: the native SDKs removed the field in the same way and the plugin has no process-wide format left to forward it to. AvatarSDK.configuration() no longer returns an audio format.
  • The test-only AvatarSDK.setAudioFormatForTesting(); tests create an AvatarWidget with the format they need.

Deprecated #

  • The audioFormat parameter of AvatarController.yieldAudioData() stays deprecated and ignored; the message now points at AvatarWidget.audioFormat / setAudioFormat.

1.3.7 - 2026-09-18 #

Bridges the Android 1.3.5 and iOS 1.3.5 native SDKs.

Added #

  • AvatarError.renderNotSupported and AvatarError.renderInitFailed are now delivered to onError. The first means this device cannot render the avatar at all (Android: no usable Vulkan instance / physical device / logical device; iOS: no Metal device) and is deterministic — tell the user rather than retry. The second covers any other failure while setting up the renderer. Until now a renderer that failed to initialize was only logged natively: the host saw a view that never drew anything and received no callback.

Changed #

  • Both native SDKs updated to 1.3.5. Highlights: the Android SDK fixes an ANR where destroying the avatar view froze the app's main thread until Android killed it — which on Flutter is triggered by ordinary PlatformView disposal, so any Flutter app that navigates away from an avatar screen was exposed; the iOS SDK applies the same bounded-wait rule preventively. Both also report far more about renderer failures, host teardown and blank frames.

Removed #

  • Breaking: AvatarError.appIDUnrecognized. The native SDKs never produced it — the service has no separate signal for an unknown app ID, which surfaces as a session-token error instead. Code that switches exhaustively over AvatarError must drop this case.

1.3.6 - 2026-09-01 #

Packaging fix only. The plugin's own API and both native SDKs are unchanged from 1.3.5 (Android 1.3.4 / iOS 1.3.4).

Fixed #

  • The published package no longer contains the iOS AvatarKit.xcframework. It was bundled by mistake in 1.3.4 and 1.3.5, which made those downloads roughly 60 MB larger than necessary — the framework is fetched from its own release during pod install, so the copy inside the package was never used. The package is back to about 5 MB.

1.3.5 - 2026-08-31 #

Bridges the Android 1.3.4 and iOS 1.3.4 native SDKs. No changes to the plugin's own API.

Changed #

  • Both native SDKs now send their diagnostics to a collection gateway instead of the storage backend directly, and no longer carry any credentials for that backend.
  • Both native SDKs now check, one second after the first frame is reported as rendered, whether anything was actually drawn, and report a diagnostic when the view is completely blank.
  • Updated the analytics dependency bundled by both native SDKs.

Fixed #

  • End-to-end latency is now reported when the host application supplies the motion data, not only when the SDK connects to the driving service itself. Applies to both platforms.

1.3.4 - 2026-08-22 #

Bridges the Android 1.3.3 and iOS 1.3.3 native SDKs. No changes to the plugin's own API.

Fixed #

  • Fixed the SDK continuing to send audio under an already-finished conversation id in direct mode (Android). After send(audio, end: true), feeding new audio while that round had not started playing yet reused the same conversation id on the wire, so the driving service received new audio on a request it had already been told was over. A new round now always starts under a fresh id, whether or not the previous one had begun playing. iOS was not affected.
  • The timestamp prefix on session and request ids is now generated in UTC on Android, matching the other platforms.
  • Internal telemetry only, no change to public API or runtime behaviour: the connection identifier is now attached automatically to the diagnostic events and traces both native SDKs report; playback records additionally carry the rendering SDK's own version; loading and connection timings are now reported for failed attempts as well; and HTTP request duration buckets were widened to match the other platforms.

1.3.3 - 2026-08-08 #

Bridges the Android 1.3.2 and iOS 1.3.2 native SDKs. Rolls up everything from the 1.3.3 beta line.

Known issues #

  • On some Android devices (Huawei and Mediatek/Mali GPUs are the ones reported), tearing down and rebuilding the avatar view in quick succession can abort the app with java.lang.IllegalStateException: Image is already closed. This is a Flutter engine bug in how platform views hand images to the rasterizer (flutter/flutter#175267), not something this plugin can guard against — it affects any plugin that renders through a platform view. The engine fix (flutter/flutter#185125, merged 2026-04-29) makes the failure non-fatal, but has not landed in a stable release yet; it is expected in the 3.47 line. Until then, avoid mounting and unmounting AvatarWidget in a tight loop.

Added #

  • Opus audio support. AudioFormat.inputAudioFormat (AudioCodec.pcm default, or AudioCodec.opus) declares the format the host feeds into the SDK via send/yieldAudioData; opus input is decoded back to PCM16 for local rendering and forwarded upstream as-is in direct mode. AudioFormat.opusBitrate tunes the target bitrate. Only effective in direct mode.
  • AvatarError.invalidAudioInput is now reported when audio handed to the SDK does not match AudioFormat.inputAudioFormat — for example Opus input that is neither Ogg Opus nor a bare Opus packet, is stereo, or changes shape mid-conversation.

Changed #

  • The direct-mode uplink now compresses audio to Opus by default (AudioFormat.opusUplinkEnabled, previously off). It cuts the upload to roughly 1/8 at the cost of client-side encoding, which matters most on the mobile networks where stalls actually happen. Pass opusUplinkEnabled: false to keep the raw PCM uplink. Unchanged for host mode (no uplink) and for opus input (already compressed). If the configured sampleRate is not one of 8000/16000/24000/48000, the SDK logs a warning and falls back to a raw PCM uplink.
  • Configuration.region now defaults to automatic selection (kDefaultRegion is 'auto'): when left unset, the SDK picks the closest serving region at initialization, and reuses the cached choice on later launches. Passing an explicit region continues to force that region, unchanged. If automatic selection can't be reached, the SDK falls back to a default region and continues initializing.
  • initialize with a missing appID now fails fast, surfacing missing configuration immediately during local development. The accompanying message points to https://app.spatius.ai/ to obtain an app ID.

Deprecated #

  • The per-call audioFormat parameter of AvatarController.yieldAudioData is deprecated and now ignored; the audio format comes from Configuration.audioFormat passed to initialize. It will be removed in a future release.

1.3.3-beta.1 - 2026-07-31 #

Bridges the Android 1.3.2-beta.1 and iOS 1.3.1-beta.1 native SDKs.

Added #

  • Opus audio support. AudioFormat.inputAudioFormat (AudioCodec.pcm default, or AudioCodec.opus) declares the format the host feeds into the SDK via send/yieldAudioData; opus input is decoded back to PCM16 for local rendering and forwarded upstream as-is in direct mode. AudioFormat.opusUplinkEnabled (default false) opts the direct-mode uplink into Opus compression (roughly 1/8 the upload, at the cost of client-side encoding), and AudioFormat.opusBitrate tunes the target bitrate. Only effective in direct mode.
  • AvatarError.invalidAudioInput is now reported when audio handed to the SDK does not match AudioFormat.inputAudioFormat — for example Opus input that is neither Ogg Opus nor a bare Opus packet, is stereo, or changes shape mid-conversation.

Changed #

  • Configuration.region now defaults to automatic selection (kDefaultRegion is 'auto'): when left unset, the SDK picks the closest serving region at initialization. Passing an explicit region continues to force that region, unchanged. If automatic selection can't be reached, the SDK falls back to a default region and continues initializing.
  • When opusUplinkEnabled is true but the configured sampleRate is not Opus-compatible (8000/16000/24000/48000), initialize logs a warning and automatically falls back to a raw PCM uplink instead of silently failing.
  • initialize with a missing appID now fails fast, surfacing missing configuration immediately during local development. The accompanying message points to https://app.spatius.ai/ to obtain an app ID.

Deprecated #

  • The per-call audioFormat parameter of AvatarController.yieldAudioData is deprecated and now ignored; the audio format comes from Configuration.audioFormat passed to initialize. It will be removed in a future release.

1.3.2 - 2026-07-13 #

Bridges the Android 1.3.1 native SDK. No Dart API changes.

Fixed #

  • On Android, native libraries are now aligned to a 16 KB memory page size, ensuring compatibility with 16 KB page-size devices and meeting Google Play's upload requirement (effective Nov 1, 2025) for apps targeting Android 15+.

1.3.1 - 2026-07-05 #

Documentation-only release. No code or native dependency changes since 1.3.0.

Changed #

  • Cleaned up the package README shown on pub.dev and fixed the documentation link.

1.3.0 - 2026-07-05 #

Bridges the v1.3.0 native SDKs. No breaking Dart API changes.

Changed #

  • Native dependencies bumped to v1.3.0 (Android ai.spatius:avatarkit:1.3.0, iOS xcframework v1.3.0).

Added #

  • Avatars are now automatically classified as body-fixation or non-body-fixation and loaded on the matching path, driven by the asset's compatibility flags (handled by the native SDKs).
  • Loading an avatar whose asset requires a newer SDK now fails fast with an incompatible-asset error instead of rendering incorrectly, prompting an SDK upgrade.

1.2.0 - 2026-06-28 #

First stable 1.2 release. No Dart API changes since 1.2.0-beta.1; this release bumps the native SDKs to v1.2.0 for playback and asset-loading reliability fixes.

Changed #

  • Native dependencies bumped to v1.2.0 (Android ai.spatius:avatarkit:1.2.0, iOS xcframework v1.2.0).

Fixed #

  • Fixed a crash that could occur when audio playback was interrupted by the system (e.g. an incoming phone call). Such interruptions are now handled gracefully instead of crashing the app.
  • Fixed local avatar assets with absent or null optional fields (such as transform) being wrongly rejected when derived. Such assets now load correctly.

1.2.0-beta.1 - 2026-06-20 #

Aligns the public API with native iOS / Android SDK v1.2.0-beta.1.

Added #

  • FrameStarvationMode enum (audioIndependent / strictSync) and AvatarController.setFrameStarvationMode(FrameStarvationMode mode) — choose how playback behaves when animation frames can't keep up with audio. audioIndependent (default) keeps audio playing while animation catches up; strictSync pauses audio until frames arrive, keeping audio and animation strictly in sync.
  • AvatarController.onPlaybackStall — void Function(bool stalled)? callback that fires when audio is paused/resumed due to frame starvation (only in strictSync).
  • AvatarError.incompatibleAvatarAsset — thrown when a local asset is in an unsupported (legacy) format.

Changed #

  • Native dependencies bumped to v1.2.0-beta.1 (Android ai.spatius:avatarkit:1.2.0-beta.1, iOS xcframework v1.2.0-beta.1).

1.1.0-beta.1 - 2026-06-09 #

Aligns the public API with native iOS / Android SDK v1.1.0-beta.2.

Added #

  • RenderQuality enum (standard / high / ultra) and Configuration({RenderQuality renderQuality = RenderQuality.ultra}) to set render quality at initialization.
  • AvatarSDK.setRenderQuality(RenderQuality quality) — change render quality at runtime.
  • AvatarSDK.setRenderResolutionCap({required bool enabled, int maxHeight = 1440}) — cap internal render resolution height to bound GPU/bandwidth cost.
  • AvatarController.renderSize() → Size — current drawable size in pixels.
  • AvatarController.getBoundingRect() → Rect? — rendered avatar bounds.
  • AvatarError.invalidAvatarMetadata and AvatarError.invalidAnimationData.

Changed #

  • Native dependencies bumped to v1.1.0-beta.2 (Android ai.spatius:avatarkit:1.1.0-beta.2, iOS xcframework v1.1.0-beta.1).

Breaking #

  • DrivingServiceMode values renamed: sdk → direct, host → backend. Update Configuration(drivingServiceMode: ...) call sites accordingly.

1.0.0 - 2026-05-20 #

First stable release.

  • Flutter plugin bridging native AvatarKit (Android ai.spatius:avatarkit:1.0.0, iOS xcframework v1.0.0).
  • Public API: AvatarSDK, AvatarManager, AvatarWidget, AvatarController.
  • Real-time avatar rendering with audio-driven and host-driven modes.
  • See README.md for installation and usage.

Pre-1.0 beta history archived at docs/history/CHANGELOG-pre-1.0.md.

0
likes
150
points
283
downloads

Documentation

API reference

Publisher

verified publisherspatius.ai

Weekly Downloads

AvatarKit — real-time, audio-driven avatar rendering SDK for Flutter.

Homepage
View/report issues

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on spatius_avatarkit

Packages that implement spatius_avatarkit