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
相关产品推荐
相关产品推荐

