Docs index: /llms.txt · every page as Markdown: add .md

‹ Platforms

Build an Android app

Stream audio into an Android avatar and show its frames in your app.

Integrate into your app

In a live conversation, keep one avatar open and stream into it.

JobExpression 2Essence 2
Audio in16 kHz mono FloatArray, −1 to 116 kHz mono 16-bit little-endian PCM ByteArray
Stream audio as it arrivesfeed(chunk) per chunkfeed(chunk) per chunk
Show framespull(bitmap), 20 a secondpull(buffer), 25 a second
End of a replyflushTail()endOfAudio()
Idle between repliesavatar.idleLoop?.next(bitmap)idle(buffer)
Interrupt the replyresetState(true)resetAudio()
Check the sessionExpression2Exception from create or pullEssence2MeteringRefused from pull/idle; checkRender() throws Essence2RenderFailed if the engine stopped
Close itclose()close()

To feed the microphone, declare <uses-permission android:name="android.permission.RECORD_AUDIO"/> in your manifest and ask for it at runtime (ActivityResultContracts.RequestPermission) before you start AudioRecord; without it the buffers are silent. The SDKs need only INTERNET, which their AARs merge in for you.

Resample 24 kHz speech (OpenAI Realtime’s) to 16 kHz, and close the avatar when the app leaves the screen: Companion app.

After your API secret is accepted, a network loss does not stop the session for 5 minutes of rendered video. After that, render calls throw a retryable exception until the connection returns. Usage is reported to your account when it does.

For a Flutter app, the Flutter plugin wraps these engines.

Complete example

Two apps you can clone and run on a phone, each with idle motion between replies:

Platform notes

  • Release builds: isMinifyEnabled = true needs nothing extra. Both AARs ship their own keep rules.

  • Two models in one app: essence2-android needs minSdk 29. Raise the app to 29, or put each model in its own module.

  • Threads: download and create() on a background thread. The first download is the size shown above, into app-private storage.

  • Check the version you resolved: Gradle keeps an exact version, so read it back when behaviour differs from this page.

    ./gradlew :app:dependencies --configuration releaseRuntimeClasspath | grep ai.bithuman
  • Private avatars: an avatar you created downloads with the secret you set with Expression2Credential.set or Essence2Credential.set; there is nothing else to pass.

Reference