You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

HeyGen交互式Avatar的LiveKit视频唇形同步连接不稳定问题求助

HeyGen交互式Avatar的LiveKit视频唇形同步连接不稳定问题求助

大家好,我最近在做一个直接嵌入HTML的JavaScript轻量原型,集成HeyGen的交互式Avatar——用WebSocket处理音频流,LiveKit负责视频唇形同步,但碰到了非常棘手的连接稳定性问题,想请教下社区里有没有人遇到过类似情况,或者能给点排查思路?

问题具体表现

  • 音频通过WebSocket的流一直稳定工作,但LiveKit的视频唇形同步异常不稳定:
    • 偶尔能正常连接并运行
    • 有时启动后直接冻结
    • 大多数情况下视频能加载出来,但完全不响应我发送的文本指令,动画会毫无征兆地停滞
  • 控制台日志显示LiveKit房间连接完全成功(能看到Connected事件、状态变更的正常日志),但就是在连接完成后,视频动画开始变得不稳定,甚至直接停住

我已经尝试过的排查步骤

  • 更换不同的Avatar ID、语音ID,调整LiveKit的参数(比如adaptiveStreamdynacast),问题依旧
  • 反复检查了WebSocket和LiveKit的并行处理逻辑,没找到明显的时序冲突
  • 仔细翻阅了HeyGen官方文档,但没有针对这个特定问题的解决指引;更糟的是,文档里提供的示例代码还失效了——指定的Avatar已经不存在,直接跑示例根本无法成功
  • 我高度怀疑问题出在LiveKit连接的这行代码:
    await room.connect(sessionInfo.url, sessionInfo.access_token);
    
    虽然控制台明确输出了连接成功的日志,但执行完这行后,视频动画的稳定性就彻底出问题了

我的核心代码片段

下面是创建会话并连接LiveKit的关键代码:

// ------------------------------------------------------
// 1️⃣ Create + Start a new streaming session via Flask
// ------------------------------------------------------
async function createNewSession() {
  try {
    updateStatus("🔄 Creating streaming session (v2)…");
    const res = await fetch("/api/session/create", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        avatar_name: avatarID.value,
        voice_id: voiceID.value,
      }),
    });
    if (!res.ok) throw new Error("Backend /create failed");
    const data = await res.json();
    sessionInfo = {
      session_id: data.session_id,
      url: data.url,
      access_token: data.access_token,
      session_token: data.session_token,
      livekit_agent_token: data.livekit_agent_token,
      realtime_endpoint: data.realtime_endpoint,
    };
    updateStatus("✅ Session info received from server");

    // --- Connect to LiveKit Room ---
    room = new LivekitClient.Room({
      adaptiveStream: true,
      dynacast: true,
      videoCaptureDefaults: {
        resolution: LivekitClient.VideoPresets.h720.resolution,
      },
    });

    // ✅ Track LiveKit connection status
    room
      .on(LivekitClient.RoomEvent.Connected, () => {
        updateStatus("✅ [LiveKit] Connected");
      })
      .on(LivekitClient.RoomEvent.Reconnecting, () => {
        updateStatus("⚠️ [LiveKit] Reconnecting…");
      })
      .on(LivekitClient.RoomEvent.Reconnected, () => {
        updateStatus("🔁 [LiveKit] Reconnected");
      })
      .on(LivekitClient.RoomEvent.Disconnected, (reason) => {
        updateStatus("❌ [LiveKit] Disconnected: " + reason);
      })
      .on(LivekitClient.RoomEvent.ConnectionStateChanged, (state) => {
        updateStatus(`🔄 [LiveKit] state → ${state}`);
      });

    // Handle room events
    room.on(LivekitClient.RoomEvent.DataReceived, (message) => {
      const data = new TextDecoder().decode(message);
      console.log("Room message:", JSON.parse(data));
    });

    // Handle media streams
    mediaStream = new MediaStream();
    room.on(LivekitClient.RoomEvent.TrackSubscribed, (track) => {
      if (track.kind === "video" || track.kind === "audio") {
        mediaStream.addTrack(track.mediaStreamTrack);
        if (
          mediaStream.getVideoTracks().length > 0 &&
          mediaStream.getAudioTracks().length > 0
        ) {
          mediaElement.srcObject = mediaStream;
          mediaElement.autoplay = true;
          //mediaElement.playsInline = true;
          updateStatus("Media stream ready");
          updateStatus(`🎬 Subscribed: ${track.kind}`);
        }
      }
    });

    // connect the video lip-sync room
    updateStatus("🔗 Connecting to LiveKit room…");
    await room.connect(sessionInfo.url, sessionInfo.access_token);
    updateStatus("✅ Connected to LiveKit room");

    // connect the audio lip‑sync websocket
    await connectWebSocket(sessionInfo.session_id, sessionInfo.session_token);
    document.querySelector("#startBtn").disabled = true;
    updateStatus("🚀 Session ready — send text to talk!");
  } catch (err) {
    console.error(err);
    updateStatus(`❌ Error: ${err.message}`);
  }
}

目前我完全卡在这里了,音频流一直正常,就是LiveKit连接后的视频动画不稳定,要么停住要么不响应指令。有没有朋友能帮我看看可能哪里出问题了?或者有没有HeyGen v2流式会话的正确实践可以参考?

火山引擎 最新活动