omniavatar

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 8 Imported by: 0

README

OmniAvatar

Go CI Go Lint Go SAST Docs Docs Visualization License

Batteries-included package for AI avatars with two surfaces:

  • live — real-time streaming avatars (LiveKit sessions, PCM audio streaming for lip-sync) for conversational agents
  • render — asynchronous batch avatar video generation (narration audio in, talking-head MP4 out) for offline pipelines such as presentation videos

Provides provider implementations for HeyGen, Tavus, and bitHuman.

For core interfaces only (no provider dependencies), see omniavatar-core.

Quick Start (live)

import (
    "github.com/plexusone/omniavatar"
    "github.com/plexusone/omniavatar-core/live"
    _ "github.com/plexusone/omniavatar/providers/all"
)

func main() {
    provider, err := omniavatar.GetLiveProvider("heygen",
        omniavatar.WithAPIKey(os.Getenv("LIVEAVATAR_API_KEY")),
        omniavatar.WithExtension("avatar_id", avatarID),
        omniavatar.WithExtension("sandbox", true))
    if err != nil {
        log.Fatal(err)
    }

    session, err := provider.CreateSession(live.SessionConfig{
        AudioConfig: live.DefaultAudioConfig(),
    })
    if err != nil {
        log.Fatal(err)
    }

    // Start with LiveKit
    err = session.Start(ctx, &omniavatar.LiveKitStartOptions{
        Room:             room,
        AgentIdentity:    "agent-123",
        LiveKitURL:       os.Getenv("LIVEKIT_URL"),
        LiveKitAPIKey:    os.Getenv("LIVEKIT_API_KEY"),
        LiveKitAPISecret: os.Getenv("LIVEKIT_API_SECRET"),
    })
}

Quick Start (render)

import (
    "github.com/plexusone/omniavatar"
    "github.com/plexusone/omniavatar-core/render"
    _ "github.com/plexusone/omniavatar/providers/all"
)

func main() {
    provider, err := omniavatar.GetRenderProvider("bithuman",
        omniavatar.WithAPIKey(os.Getenv("BITHUMAN_API_KEY")),
        omniavatar.WithExtension("agent_id", agentID))
    if err != nil {
        log.Fatal(err)
    }

    // Providers with hosting support can upload local narration audio.
    audioURL := ""
    if up, ok := provider.(render.AudioUploader); ok {
        audioURL, err = up.UploadAudio(ctx, "narration.mp3", audioFile)
        if err != nil {
            log.Fatal(err)
        }
    }

    job, err := provider.Generate(ctx, render.GenerateRequest{
        AvatarID: agentID,
        AudioURL: audioURL,
    })
    if err != nil {
        log.Fatal(err)
    }

    status, err := render.Wait(ctx, provider, job.ID, 5*time.Second)
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("video ready: %s (%.1fs)", status.VideoURL, status.Duration)

    out, err := os.Create("presenter.mp4")
    if err != nil {
        log.Fatal(err)
    }
    defer out.Close()

    if err := provider.Download(ctx, job.ID, out); err != nil {
        log.Fatal(err)
    }
}

Architecture

Adapters follow the PlexusOne convention: render adapters live in each provider SDK repo (heygen-go/omniavatar, …), depending only on omniavatar-core, so provider-specific knowledge stays with the SDK. The live adapters live here in the batteries-included package, because their LiveKit integration (LiveKitStartOptions, token generation) lives here. This package re-exports both, registered by name via providers/all.

omniavatar-core/              # Core interfaces + shared helpers (no provider deps)
├── live/                     # Real-time session interfaces
├── render/                   # Batch generation: Provider, AudioUploader,
│                             #   AvatarLister, GenerateRequest, Wait,
│                             #   AudioContentType/DownloadURL helpers
└── registry/                 # Factory types

heygen-go/omniavatar/         # HeyGen RENDER adapter (core-only) — in the SDK repo
tavus-go/omniavatar/          # Tavus RENDER adapter
bithuman-go/omniavatar/       # bitHuman RENDER adapter

omniavatar/                   # Batteries-included (this package)
├── registry.go               # Global live + render registries
├── token.go / start_options.go  # LiveKit token + start options
└── providers/
    ├── heygen/               # HeyGen LIVE adapter (LiveAvatar); registers the SDK render adapter
    ├── tavus/                # Tavus LIVE adapter (CVI)
    ├── bithuman/             # bitHuman LIVE adapter
    └── all/                  # Convenience import (registers every provider)

Provider Registry

Priority System

Providers register with a priority level:

Priority Constant Description
0 PriorityThin Minimal implementations
10 PriorityThick Full SDK implementations

Higher priority providers override lower priority registrations for the same name.

Auto-Registration

Providers auto-register both surfaces via init() when imported:

// Import specific provider
import _ "github.com/plexusone/omniavatar/providers/heygen"

// Or import all providers
import _ "github.com/plexusone/omniavatar/providers/all"
Registry Functions
// Live (real-time sessions)
provider, err := omniavatar.GetLiveProvider("heygen", opts...)
names := omniavatar.ListLiveProviders()
ok := omniavatar.HasLiveProvider("heygen")

// Render (batch video generation)
provider, err := omniavatar.GetRenderProvider("heygen", opts...)
names := omniavatar.ListRenderProviders()
ok := omniavatar.HasRenderProvider("heygen")

Supported Providers

HeyGen

Live: real-time avatar with lip-sync using HeyGen LiveAvatar LITE mode. Render: HeyGen Video Generation API (v2).

Note: the live surface uses the LiveAvatar API key (LIVEAVATAR_API_KEY); the render surface uses the HeyGen API key (HEYGEN_API_KEY). They are different credentials.

// Live
provider, err := omniavatar.GetLiveProvider("heygen",
    omniavatar.WithAPIKey(os.Getenv("LIVEAVATAR_API_KEY")),
    omniavatar.WithExtension("avatar_id", "josh_lite3_20230714"),
    omniavatar.WithExtension("sandbox", true),           // 60s limit, no credits
    omniavatar.WithExtension("video_quality", "high"),   // very_high, high, medium, low
)

// Render
provider, err := omniavatar.GetRenderProvider("heygen",
    omniavatar.WithAPIKey(os.Getenv("HEYGEN_API_KEY")),
    omniavatar.WithExtension("avatar_id", avatarID),
)
Surface Option Description
live avatar_id Avatar UUID (required)
live sandbox Enable sandbox mode (recommended for dev)
live video_quality Video quality preset
render avatar_id Default avatar ID
render upload_base_url Custom asset upload service URL (default: upload.heygen.com)
render request talking_photo_id Use a talking photo instead of an avatar
render request avatar_style normal, circle, closeUp
render request voice_id TTS voice for Script input
render request test Watermarked test video, no credits

The HeyGen render provider implements render.AudioUploader via the HeyGen asset upload API (MP3/audio/mpeg is the documented audio asset type).

Tavus

Live: real-time avatar using Tavus PAL (Personalized AI Likeness). Render: Tavus Video Generation using replicas.

// Live
provider, err := omniavatar.GetLiveProvider("tavus",
    omniavatar.WithAPIKey(os.Getenv("TAVUS_API_KEY")),
    omniavatar.WithExtension("pal_id", "pal_xxx"),   // Optional
    omniavatar.WithExtension("face_id", "face_xxx"), // Optional
)

// Render
provider, err := omniavatar.GetRenderProvider("tavus",
    omniavatar.WithAPIKey(os.Getenv("TAVUS_API_KEY")),
    omniavatar.WithExtension("replica_id", "rep_xxx"),
)
Surface Option Description
live pal_id PAL ID (optional, uses stock avatar if not set)
live face_id Face override (optional)
render replica_id Default replica ID
render request fast Faster generation (disables some features)
render request callback_url Completion webhook URL

Tavus has no audio upload API; supply a publicly fetchable GenerateRequest.AudioURL (.wav or .mp3).

bitHuman

Live: ultra-low latency real-time avatars. Render: bitHuman video generation, including audio upload support (render.AudioUploader).

// Live
provider, err := omniavatar.GetLiveProvider("bithuman",
    omniavatar.WithAPIKey(os.Getenv("BITHUMAN_API_KEY")),
    omniavatar.WithExtension("agent_id", "agent_xxx"),
)

// Render
provider, err := omniavatar.GetRenderProvider("bithuman",
    omniavatar.WithAPIKey(os.Getenv("BITHUMAN_API_KEY")),
    omniavatar.WithExtension("agent_id", "agent_xxx"),
)
Surface Option Description
live agent_id bitHuman agent ID (required)
render agent_id Default agent ID
render request voice_id TTS voice for Script input

Session Lifecycle (live)

1. Get Provider    → omniavatar.GetLiveProvider("heygen", opts...)
2. Create Session  → provider.CreateSession(cfg)
3. Start           → session.Start(ctx, &LiveKitStartOptions{...})
4. Wait for Join   → session.WaitForJoin(ctx, 30*time.Second)
5. Stream Audio    → session.AudioOutput().CaptureFrame(ctx, pcm)
6. Close           → session.Close(ctx)

Job Lifecycle (render)

1. Get Provider    → omniavatar.GetRenderProvider("heygen", opts...)
2. Upload Audio    → provider.(render.AudioUploader).UploadAudio(...)  [optional]
3. Generate        → provider.Generate(ctx, render.GenerateRequest{...})
4. Wait            → render.Wait(ctx, provider, job.ID, interval)
5. Download        → provider.Download(ctx, job.ID, dst)

LiveKit Integration

Token Generation

Generate tokens for avatar participants to join LiveKit rooms:

token, err := omniavatar.GenerateAvatarToken(omniavatar.TokenOptions{
    APIKey:        os.Getenv("LIVEKIT_API_KEY"),
    APISecret:     os.Getenv("LIVEKIT_API_SECRET"),
    RoomName:      "my-room",
    Identity:      "avatar-heygen-abc123",
    Provider:      "heygen",
    AgentIdentity: "agent-123",
    TTL:           time.Hour,
})
Start Options
type LiveKitStartOptions struct {
    Room             *lksdk.Room  // LiveKit room reference
    AgentIdentity    string       // Agent's participant identity
    LiveKitURL       string       // LiveKit server URL
    LiveKitAPIKey    string       // API key for token generation
    LiveKitAPISecret string       // API secret for token generation
}

Audio Format (live)

Default audio configuration:

Parameter Value
Sample Rate 24000 Hz
Channels 1 (mono)
Encoding PCM16 (linear16)

Provider Comparison

Provider Live Latency Video Quality Voice Cloning Render Audio Upload
HeyGen ~500ms Excellent Yes Yes (asset API, MP3)
Tavus ~300ms Excellent Yes (via PAL) No (URL only)
bitHuman ~200ms Good No Yes

Specs

Resources

Documentation

Overview

Package omniavatar provides a unified, provider-agnostic interface for AI avatars.

This is the batteries-included package that imports all providers. For a minimal dependency footprint, use github.com/plexusone/omniavatar-core instead.

Two surfaces are supported:

  • live: real-time streaming avatar sessions (LiveKit rooms, PCM audio streaming for lip-sync) for conversational agents
  • render: asynchronous batch avatar video generation (narration audio in, talking-head MP4 out) for offline pipelines such as presentation videos

Quick Start (live)

import (
    "github.com/plexusone/omniavatar"
    _ "github.com/plexusone/omniavatar/providers/all"
)

func main() {
    provider, err := omniavatar.GetLiveProvider("heygen",
        omniavatar.WithAPIKey(os.Getenv("LIVEAVATAR_API_KEY")),
        omniavatar.WithExtension("avatar_id", avatarID),
        omniavatar.WithExtension("sandbox", true))
    if err != nil {
        log.Fatal(err)
    }

    session, err := provider.CreateSession(live.SessionConfig{
        AudioConfig: live.DefaultAudioConfig(),
    })
    if err != nil {
        log.Fatal(err)
    }

    // Use session with LiveKit or other platform adapters
}

Quick Start (render)

provider, err := omniavatar.GetRenderProvider("heygen",
    omniavatar.WithAPIKey(os.Getenv("HEYGEN_API_KEY")))
if err != nil {
    log.Fatal(err)
}

job, err := provider.Generate(ctx, render.GenerateRequest{
    AvatarID: avatarID,
    AudioURL: narrationURL,
})
status, err := render.Wait(ctx, provider, job.ID, 5*time.Second)
err = provider.Download(ctx, job.ID, outFile)

Available Providers

  • heygen: HeyGen LiveAvatar (live) and HeyGen Video Generation (render)
  • tavus: Tavus Conversational Video (live) and Video Generation (render)
  • bithuman: bitHuman Real-time Avatars (live) and Video Generation (render, with audio upload support)

Architecture

omniavatar follows the same pattern as omnivoice:

  • omniavatar-core: Core interfaces (live, render) with no provider dependencies
  • omniavatar: Provider implementations with auto-registration
  • omniavatar/providers/all: Convenience import for all providers

Index

Constants

View Source
const (
	// PriorityThin is the priority for thin (stdlib-only) provider implementations.
	// These have no external dependencies beyond the standard library.
	PriorityThin = 0

	// PriorityThick is the priority for thick (official SDK) provider implementations.
	// These use official provider SDKs for full feature support.
	PriorityThick = 10
)

Priority constants for provider registration. Higher priority values override lower priority registrations.

Variables

View Source
var (
	WithAPIKey    = registry.WithAPIKey
	WithBaseURL   = registry.WithBaseURL
	WithExtension = registry.WithExtension
)

Re-export option functions from omniavatar-core/registry.

Functions

func GenerateAvatarToken

func GenerateAvatarToken(opts TokenOptions) (string, error)

GenerateAvatarToken creates a JWT token for an avatar to join a room.

The token includes the special "lk.publish_on_behalf" attribute that allows the avatar participant to publish tracks that appear in the UI as if they came from the agent participant.

func GetLiveProvider added in v0.2.0

func GetLiveProvider(name string, opts ...ProviderOption) (live.Provider, error)

GetLiveProvider creates a live provider instance from the registry. Returns an error if the provider is not registered or if creation fails.

Example:

provider, err := omniavatar.GetLiveProvider("heygen",
    omniavatar.WithAPIKey(os.Getenv("LIVEAVATAR_API_KEY")),
    omniavatar.WithExtension("avatar_id", avatarID))

func GetLiveProviderPriority added in v0.2.0

func GetLiveProviderPriority(name string) int

GetLiveProviderPriority returns the priority of the registered live provider. Returns -1 if the provider is not registered.

func GetRenderProvider added in v0.2.0

func GetRenderProvider(name string, opts ...ProviderOption) (render.Provider, error)

GetRenderProvider creates a render provider instance from the registry. Returns an error if the provider is not registered or if creation fails.

Example:

provider, err := omniavatar.GetRenderProvider("heygen",
    omniavatar.WithAPIKey(os.Getenv("HEYGEN_API_KEY")))

func GetRenderProviderPriority added in v0.2.0

func GetRenderProviderPriority(name string) int

GetRenderProviderPriority returns the priority of the registered render provider. Returns -1 if the provider is not registered.

func HasLiveProvider added in v0.2.0

func HasLiveProvider(name string) bool

HasLiveProvider returns true if a live provider with the given name is registered.

func HasRenderProvider added in v0.2.0

func HasRenderProvider(name string) bool

HasRenderProvider returns true if a render provider with the given name is registered.

func ListLiveProviders added in v0.2.0

func ListLiveProviders() []string

ListLiveProviders returns a list of all registered live provider names.

func ListRenderProviders added in v0.2.0

func ListRenderProviders() []string

ListRenderProviders returns a list of all registered render provider names.

func RegisterLiveProvider added in v0.2.0

func RegisterLiveProvider(name string, factory LiveProviderFactory, priority int)

RegisterLiveProvider registers a live (real-time session) provider factory with the given name and priority. Higher priority values override lower priority registrations.

Example:

// In omniavatar/providers/heygen/register.go (thick, priority 10)
func init() {
    omniavatar.RegisterLiveProvider("heygen", NewProviderFromConfig, omniavatar.PriorityThick)
}

func RegisterRenderProvider added in v0.2.0

func RegisterRenderProvider(name string, factory RenderProviderFactory, priority int)

RegisterRenderProvider registers a render (batch generation) provider factory with the given name and priority. Higher priority values override lower priority registrations.

Example:

// In omniavatar/providers/heygen/register.go (thick, priority 10)
func init() {
    omniavatar.RegisterRenderProvider("heygen", NewRenderProviderFromConfig, omniavatar.PriorityThick)
}

Types

type AvatarMetadata

type AvatarMetadata struct {
	// Kind identifies this as an avatar participant.
	Kind string `json:"kind"`

	// Provider is the avatar provider name.
	Provider string `json:"provider,omitempty"`

	// AgentIdentity is the identity of the agent this avatar represents.
	AgentIdentity string `json:"agent_identity,omitempty"`
}

AvatarMetadata is the standard metadata structure for avatar participants.

func DefaultAvatarMetadata

func DefaultAvatarMetadata(provider, agentIdentity string) AvatarMetadata

DefaultAvatarMetadata returns the default metadata for avatar participants.

type LiveKitStartOptions

type LiveKitStartOptions struct {
	// Room is the LiveKit room the agent has joined.
	// Required.
	Room *lksdk.Room

	// AgentIdentity is the identity of the agent participant.
	// The avatar will publish tracks on behalf of this identity
	// using the lk.publish_on_behalf attribute.
	// Required.
	AgentIdentity string

	// LiveKitURL is the LiveKit server URL for the avatar to connect to.
	// This should match the URL the agent connected to.
	// Required.
	LiveKitURL string

	// LiveKitAPIKey is used to generate tokens for the avatar.
	// Required.
	LiveKitAPIKey string

	// LiveKitAPISecret is used to generate tokens for the avatar.
	// Required.
	LiveKitAPISecret string

	// Callbacks configures optional event callbacks.
	Callbacks *live.SessionCallbacks

	// AudioDestination is the audio output for streaming TTS audio.
	// If provided, the session will use this instead of creating its own.
	// Optional.
	AudioDestination live.AudioDestination
}

LiveKitStartOptions contains LiveKit-specific start options for avatar sessions.

This is passed to Session.Start() when integrating with LiveKit.

func (*LiveKitStartOptions) Validate

func (o *LiveKitStartOptions) Validate() error

Validate checks that all required fields are set.

type LiveProviderFactory added in v0.2.0

type LiveProviderFactory = registry.LiveProviderFactory

LiveProviderFactory creates a live.Provider from configuration.

type ProviderConfig

type ProviderConfig = registry.ProviderConfig

ProviderConfig holds common configuration options for creating providers.

type ProviderOption

type ProviderOption = registry.ProviderOption

ProviderOption configures a ProviderConfig.

type RenderProviderFactory added in v0.2.0

type RenderProviderFactory = registry.RenderProviderFactory

RenderProviderFactory creates a render.Provider from configuration.

type TokenOptions

type TokenOptions struct {
	// APIKey is the LiveKit API key.
	// Required.
	APIKey string

	// APISecret is the LiveKit API secret.
	// Required.
	APISecret string

	// RoomName is the room the avatar will join.
	// Required.
	RoomName string

	// AvatarIdentity is the participant identity for the avatar.
	// Required.
	AvatarIdentity string

	// AvatarName is the display name for the avatar participant.
	// Optional, defaults to AvatarIdentity.
	AvatarName string

	// PublishOnBehalf is the identity of the agent participant.
	// The avatar will publish tracks that appear as if they're from this participant.
	// Required.
	PublishOnBehalf string

	// TTL is the token validity duration.
	// Default: 5 minutes
	TTL time.Duration

	// Metadata is optional participant metadata.
	Metadata string
}

TokenOptions configures avatar token generation.

Directories

Path Synopsis
examples
render-basic command
Command render-basic generates a talking-head video from narration audio using any registered render provider.
Command render-basic generates a talking-head video from narration audio using any registered render provider.
providers
all
Package all imports all avatar providers for side-effect registration.
Package all imports all avatar providers for side-effect registration.
bithuman
Package bithuman provides a bitHuman Real-time Avatars provider for omniavatar.
Package bithuman provides a bitHuman Real-time Avatars provider for omniavatar.
heygen
Package heygen provides a HeyGen LiveAvatar provider for omniavatar.
Package heygen provides a HeyGen LiveAvatar provider for omniavatar.
tavus
Package tavus provides a Tavus Conversational Video provider for omniavatar.
Package tavus provides a Tavus Conversational Video provider for omniavatar.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL