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

FFmpeg使用fps滤镜时内存暴涨崩溃但scale滤镜正常如何排查

问题原因与修复方案

scale滤镜为逐帧处理的同步滤镜,输入1帧立刻输出1帧,内部不会留存多余帧;但fps滤镜属于帧率转换滤镜,需要缓存多帧完成插帧或帧丢弃逻辑,尤其是当设置的目标帧率高于源视频帧率时,滤镜会持续缓存帧用于生成中间插帧,你现有代码的帧拉取逻辑存在缺陷,导致滤镜内部缓存的帧无法被及时取出,内存占用持续升高最终崩溃。

具体代码缺陷

  • 帧拉取逻辑不合理:applyFilter函数每次仅拉取1帧就返回,若fps滤镜输入1帧生成多帧,剩余输出帧会滞留在滤镜缓冲区中;当返回EAGAIN(暂无输出帧)时,你直接跳过编码逻辑,滞留在缓冲区的帧永远不会被取出,积累量越来越大。
  • 帧引用处理逻辑有问题:无论applyFilter返回值是否有效,你都直接替换frame指针,若返回EAGAIN时filterFrame为空,会导致后续编码逻辑拿到空指针,同时原输入帧的引用管理也存在冗余问题。
  • 注意你贴出的代码存在低级语法错误:char filterDesc = "fps=fps=30000/1000"应为char *filterDesc,字符变量无法存储字符串指针。

修复方案

调整滤镜的调用逻辑,送帧后循环拉取所有可输出的滤镜帧,全部完成编码后再处理下一输入帧,同时添加末尾冲刷逻辑取出滤镜残留的所有帧。

修正后代码示例

char *filterDesc = "fps=fps=30000/1000";
filter = initFilter(filterDesc, params);

for (EVER) {
    getFrame(decoder, frame, packet);
    if (decoder->container->streams[packet->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        if (filter != NULL) {
            // 输入帧送入滤镜
            int ret = av_buffersrc_add_frame_flags(filter->buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF);
            if (ret < 0) {
                printf("Error while sending frame to filter\n");
                return -1;
            }
            // 循环拉取所有可用输出帧
            while (1) {
                ret = av_buffersink_get_frame(filter->buffersink_ctx, filterFrame);
                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                    break;
                }
                if (ret < 0) {
                    printf("Error while getting filtered frame\n");
                    return -1;
                }
                // 拿到有效帧直接编码
                encode(decoder, encoder, filterFrame, packet->stream_index);
                av_frame_unref(filterFrame);
            }
            av_frame_unref(frame);
            // 跳过后续通用编码逻辑,避免重复编码
            continue;
        }
    }
    // 非视频流或未启用滤镜的场景直接编码
    encode(decoder, encoder, frame, packet->stream_index);
    av_frame_unref(frame);
}

// 所有输入帧处理完成后,冲刷滤镜缓冲区取出剩余帧
if (filter != NULL) {
    av_buffersrc_add_frame_flags(filter->buffersrc_ctx, NULL, 0);
    while (av_buffersink_get_frame(filter->buffersink_ctx, filterFrame) >= 0) {
        encode(decoder, encoder, filterFrame, packet->stream_index);
        av_frame_unref(filterFrame);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 23:30:03