JavaCV转DHAV到RTSP报错:不支持无全局头的AAC
解决JavaCV转RTSP时"AAC with no global headers"错误
核心问题分析
你遇到的错误是因为RTSP传输AAC时要求必须携带全局头信息,但当前AAC编码器未启用该配置。你的代码中直接复用了抓取端的AVFormatContext启动录制器,而抓取端的音频是PCM格式,录制端转码为AAC时未正确配置编码器的全局头参数。
有效解决方案
方案1:给AAC编码器添加全局头参数
在初始化FFmpegFrameRecorder后、调用start()前,添加以下配置:
// 给AAC编码器设置全局头(+表示添加标志,而非覆盖) recorder.setAudioOption("flags", "+global_header"); // 添加RTSP的LATM参数,适配部分RTSP服务器要求 recorder.setOption("rtpflags", "latm");
方案2:直接操作CodecContext设置全局头
如果方案1不生效,可直接修改编码器上下文的flags:
recorder.setAudioCodec(AV_CODEC_ID_AAC); // 先初始化编码器上下文 recorder.prepareAudioCodec(); // 获取音频编码器上下文并设置全局头标志 AVCodecContext audioCodecCtx = recorder.getAudioCodecContext(); if (audioCodecCtx != null) { audioCodecCtx.flags(audioCodecCtx.flags() | avcodec.AV_CODEC_FLAG_GLOBAL_HEADER); }
方案3:避免直接复用抓取端的AVFormatContext
你的代码中使用recorder.start(avFormatContext)复用了抓取端的格式上下文,但抓取端音频是PCM,录制端需要转码为AAC,这种复用可能导致编码器配置未生效。建议改为单独启动录制器:
// 不要用recorder.start(avFormatContext),改用无参的start() recorder.start();
同时,将grabPacket()+recordPacket()改为grabFrame()+recordFrame(),确保转码过程正确执行:
Frame frame; while ((frame = grabber.grab()) != null) { recorder.record(frame); Thread.sleep(1); }
调整后的关键代码片段
// ... 前面的初始化代码 ... FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(pushAddress, frameWidth, frameHeight, audioChannels); recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); recorder.setInterleaved(true); switch (pushPotocol) { case "rtsp" -> { recorder.setFormat("rtsp"); recorder.setOption("rtpflags", "latm"); } case "rtmp" -> { recorder.setFormat("flv"); } } recorder.setFrameRate(frameRate); recorder.setAudioCodec(AV_CODEC_ID_AAC); recorder.setGopSize(frameRate * 2); recorder.setAudioChannels(grabber.getAudioChannels()); // 配置AAC全局头 recorder.setAudioOption("flags", "+global_header"); // 启动录制器,不复用抓取端的AVFormatContext recorder.start(); Frame frame; while ((frame = grabber.grab()) != null) { recorder.record(frame); Thread.sleep(1); } // ... 后续关闭代码 ...
为什么之前的尝试无效?
- 你修改的是抓取端的
avFormatContext.flags,但录制端转码AAC时使用的是新的编码器上下文,该配置不生效。 setAudioOption("flags", "global_header")缺少+号,FFmpeg中+表示添加该标志而非覆盖原有配置。
内容的提问来源于stack exchange,提问作者zhoutian
相关产品推荐
相关产品推荐

