You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Agora UE插件onPlaybackAudioFrameBeforeMixing回调音频帧缓冲区大小计算问题

解决Agora Unreal插件音频帧复制崩溃问题

你崩溃的核心原因是缓冲区大小计算错误:你误用了samplesPerSec(每秒采样数,你的场景是16000)代替了当前回调帧的实际样本数samples,导致算出的bytes远大于当前帧的真实缓冲区大小,Memcpy时直接越界访问内存,触发崩溃。

精准获取单帧缓冲区大小的正确方法

完全不需要手动通过帧间隔×采样率计算单帧样本数,AudioFrame结构体里的samples字段已经直接给出了当前回调这一帧的样本数量,这是官方提供的精准值。正确的缓冲区字节数计算公式就是官方注释里写的:
buffer字节数 = samples × channels × bytesPerSample

修正后的代码

bool MyAudoFrameObserver::onPlaybackAudioFrameBeforeMixing(
    const char* channelId,
    agora::rtc::uid_t UserId,
    IAudioFrameObserverBase::AudioFrame& audioFrame)
{
    // 用当前帧的实际样本数计算缓冲区大小
    size_t bytes = audioFrame.samples * audioFrame.bytesPerSample * audioFrame.channels;
    
    // 栈缓冲区固定大小,注意判断避免越界
    char mybuffer[32000];
    size_t copySize = FMath::Min(static_cast<size_t>(32000), bytes);
    
    // 先检查buffer不为空再复制,避免空指针崩溃
    if (audioFrame.buffer != nullptr && copySize > 0)
    {
        FMemory::Memcpy(mybuffer, audioFrame.buffer, copySize);
        // 跨线程传递数据建议用UE的线程安全队列(比如TQueue),避免竞态问题
    }

    return true;
}

额外优化建议

  • 栈上的mybuffer固定32000字节可能不够灵活,改用UE的TArray<char>动态分配内存更安全:
TArray<char> mybuffer;
if (audioFrame.buffer != nullptr && bytes > 0)
{
    mybuffer.SetNumUninitialized(bytes);
    FMemory::Memcpy(mybuffer.GetData(), audioFrame.buffer, bytes);
    // 传递TArray时注意跨线程的生命周期管理,比如移交给目标线程
}
  • 跨线程传递音频数据时,务必用线程安全的容器(比如TQueue),避免数据访问冲突。

内容的提问来源于stack exchange,提问作者DragonTesa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 04:25:12