Skip to content

repeatAudio() does not produce lip-sync or audio for custom VIDEO avatars in LITE mode #92

Description

@Yuvraj3905

Description

session.repeatAudio(pcmString) in LITE mode sends audio chunks correctly via WebSocket but produces no visible lip-sync and no audio output for custom VIDEO avatars. The server fires rapid AVATAR_SPEAK_STARTED / AVATAR_SPEAK_ENDED events per chunk (~20ms each) instead of treating them as a single utterance.

Environment

  • SDK version: @heygen/liveavatar-web-sdk@0.0.12
  • Avatar type: Custom VIDEO avatar (created from uploaded video)
  • Session mode: LITE
  • Browser: Chrome 130+ (also tested Firefox)

Steps to Reproduce

  1. Create a session token with mode: "LITE" and a custom VIDEO avatar
  2. Connect and wait for SESSION_STREAM_READY
  3. Generate PCM audio (24kHz, 16-bit mono, binary string) — tested with both OfflineAudioContext resampling and manual linear interpolation from a 22050Hz WAV source
  4. Call session.repeatAudio(pcmString)

Expected Behavior

  • Avatar lip-syncs to the provided audio
  • Audio plays through the LiveKit audio track
  • Single AVATAR_SPEAK_STARTED at the beginning, single AVATAR_SPEAK_ENDED at the end

Actual Behavior

  • No lip movement on the avatar
  • No audio output through the stream
  • Rapid cycling of AVATAR_SPEAK_STARTEDAVATAR_SPEAK_ENDED events (one pair per ~20ms chunk, hundreds of pairs for a 3-second audio clip)

Console output:

[useHeyGenAvatar] Avatar lip-sync started
[useHeyGenAvatar] Avatar lip-sync ended
[useHeyGenAvatar] Avatar lip-sync started
[useHeyGenAvatar] Avatar lip-sync ended
... (repeats 100+ times in rapid succession)

Verification Steps Taken

We verified the issue is not in our PCM encoding:

  1. Attempt 1 — OfflineAudioContext resampling: Fetched WAV (22050Hz) → decoded with AudioContext.decodeAudioData → resampled to 24kHz via OfflineAudioContext → Float32 to Int16 → binary string → repeatAudio(). Same rapid start/stop, no lip-sync.

  2. Attempt 2 — Manual WAV parsing + linear interpolation: Parsed WAV header manually → extracted raw Int16 PCM → resampled 22050→24000 with linear interpolation → binary string → repeatAudio(). Identical result.

  3. FULL mode works: The same avatar works perfectly with session.repeat(text) in FULL mode — lip-sync, audio, and speaking lifecycle events all function correctly.

  4. LITE mode session connects fine: SESSION_STREAM_READY fires, video stream renders, SESSION_STATE_CHANGED: CONNECTED fires. The session itself is healthy.

PCM Diagnostics

WAV: 22050Hz, 16bit, 1ch, 45678 bytes
Extracted 22000 mono samples, duration: 1.00s
Resampled 22000 (22050Hz) → 24000 (24000Hz)
Binary string: 48000 chars (24000 samples, 1.00s)
Calling repeatAudio with 48000 chars PCM

The PCM data matches the format expected by splitPcm24kStringToChunks() (960 bytes = 20ms at 24kHz mono 16-bit).

Use Case

We want to use an external TTS engine (Vachana AI, Indian English) to provide the voice while using HeyGen's avatar for lip-sync. This is the intended use case of LITE mode + repeatAudio() per the SDK architecture, but it doesn't work for custom VIDEO avatars.

Question

Is repeatAudio() in LITE mode supported for custom VIDEO avatars? If not, are there plans to support it? This would unlock third-party TTS integration which is a significant use case for non-English voices.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions