业务场景:获取海康威视的PS流,放到管道流里进行推流
用到了javacv里的FFmpegFrameRecorder和FFmpegFrameGrabber
在linux上运行尝试推流,但报了以下的错误,想知道各位有没有遇到或解决过这样的问题:
Warning: [mpeg @ 0x7f5ee4022e80] Could not find codec parameters for stream 1 (Audio: mp2, 0 channels): unspecified frame size
Consider increasing the value for the 'analyzeduration' and 'probesize' options
Info: Input #0, mpeg, from 'java.io.BufferedInputStream@237659eb':
Info: Duration:
Info: N/A
Info: , start:
Info: 39998.215000
Info: , bitrate:
Info: N/A
Info:
Info: Stream #0:0
Info: [0x1e0]
Info: : Video: h264 (Main), yuvj420p(pc, bt709, progressive), 1920x1080
Info: ,
Info: 15 fps,
Info: 25 tbr,
Info: 90k tbn,
Info: 30 tbc
Info:
Info: Stream #0:1
Info: [0x1c0]
Info: : Audio: mp2, 0 channels
Info:
Warning: [flv @ 0x7f5ee4060740] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
Info: Output #0, flv, to 'rtmp://192.168.1.200:1935/live/admin':
Info: Metadata:
Info: encoder :
Info: Lavf58.29.100
Info:
Info: Stream #0:0
Info: : Video: h264 (Main) ([7][0][0][0] / 0x0007), yuvj420p(pc, bt709, progressive), 1920x1080, q=2-31
Info: , SAR 1:1 DAR 16:9
Info: ,
Info: 25 fps,
Info: 1k tbn,
Info: 25 tbc
Info:
代码内容如下:
FFmpegLogCallback.set();
// 配置 FFmpegFrameGrabber 的视频流和音频流属性并开始推流
String rtmpUrl = "rtmp://192.168.1.200:1935/live/admin";
// 创建 FFmpegFrameGrabber 对象并设置视频流参数
// 采集器
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputStream, 0);
// 设置读取的最大数据,单位字节
grabber.setOption("probesize", "1000000");
// 设置分析的最长时间,单位微秒
grabber.setOption("analyzeduration", "1000000");
grabber.setVideoOption("vcodec", "copy");
grabber.setFormat("mpeg");
grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
grabber.setVideoCodec(avcodec.AV_CODEC_ID_H264);
// grabber.setAudioStream(Integer.MAX_VALUE);
grabber.setAudioChannels(0);
grabber.setAudioCodec(avcodec.AV_CODEC_ID_NONE);
// grabber.setImageWidth(1920);
// grabber.setImageHeight(1080);
grabber.setFrameRate(25);
grabber.setVideoBitrate(1500000);
grabber.setOption("threads", "2");
grabber.start(true);
System.out.println("grabber:ImageHeight:"+grabber.getImageHeight());
System.out.println("grabber:ImageWidth:"+grabber.getImageWidth());
// 视频参数设置
// 该参数用于降低延迟
videoOption.put("tune", "zerolatency");
/**
** 权衡quality(视频质量)和encode speed(编码速度) values(值): *
* ultrafast(终极快),superfast(超级快), veryfast(非常快), faster(很快), fast(快), *
* medium(中等), slow(慢), slower(很慢), veryslow(非常慢) *
* ultrafast(终极快)提供最少的压缩(低编码器CPU)和最大的视频流大小;而veryslow(非常慢)提供最佳的压缩(高编码器CPU)的同时降低视频流的大小
*/
videoOption.put("preset", "ultrafast");
// 画面质量参数,0~51;18~28是一个合理范围
videoOption.put("crf", "25");
// 创建 FFmpegFrameRecorder 对象并设置视频流参数
// 解码器
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(rtmpUrl, 1920, 1080);
recorder.setInterleaved(true);
recorder.setVideoOptions(videoOption);
// 设置比特率
recorder.setVideoBitrate(bitrate);
// h264编/解码器
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
// 封装flv格式
recorder.setFormat("flv");
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
// 视频帧率(保证视频质量的情况下最低25,低于25会出现闪屏)
recorder.setFrameRate(framerate);
// 关键帧间隔,一般与帧率相同或者是视频帧率的两倍
recorder.setGopSize((int) framerate * 2);
recorder.setOption("crf", "25");
recorder.setOption("preset", "fast");
recorder.setOption("tune", "zerolatency");
recorder.setOption("maxrate", "2M");
recorder.setOption("bufsize", "4M");
AVFormatContext fc = null;
fc = grabber.getFormatContext();
recorder.start(fc);
maven版本:
org.bytedeco
javacv
1.5.3
org.bytedeco
ffmpeg-platform
4.2.2-1.5.3
参考GPT和自己的思路:根据报错信息,提示未找到音频流的解码参数,建议尝试调整一下参数来解决这个问题:
增加 analyzeduration
和 probesize
的值,例如设置为 10000000 或更大。
尝试设置音频流的参数,例如设置 grabber.setAudioChannels(1)
,来明确音频流的配置。
如果还是无法解决问题,可以尝试使用更高版本的 FFmpegFrameGrabber 和 FFmpegFrameRecorder 库,看能否解决这个问题。
该回答引用于gpt与OKX安生共同编写:
根据提示信息,错误可能是因为 FFmpegFrameGrabber 无法找到音频流的编解码器参数。建议您尝试指定 'analyzeduration' 和 'probesize' 参数的值,以确保能够正确地解析音频流。
另外, 'mp2' 是一种不常用的编解码器,并且它在 FFmpeg 中似乎存在一些问题。建议考虑使用其他音频编解码器,例如 'aac' 或 'libfdk_aac' 等。
以下是示例代码,您可以根据需要进行修改:
// 创建 FFmpegFrameGrabber 并设置参数
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputStream, 0);
grabber.setOption("analyzeduration", "5000000");
grabber.setOption("probesize", "5000000");
// 设置音频流参数
grabber.setAudioStream(1); // 根据实际情况设置音频流索引
grabber.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
// 创建 FFmpegFrameRecorder 并设置参数
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(rtmpUrl, 1920, 1080);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
recorder.setFormat("flv");
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
recorder.setFrameRate(framerate);
recorder.setGopSize((int) framerate * 2);
recorder.setVideoBitrate(bitrate);
// 设置音频流参数
recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
recorder.setAudioChannels(2);
recorder.setSampleRate(44100);
// 开始推流
grabber.start();
recorder.start();
希望这能够帮助您解决问题!
该回答引用自ChatGPT
这个错误提示中提到了两个选项:analyzeduration和probesize,建议尝试增加它们的值,可以通过设置FFmpegFrameGrabber对象的options属性来实现:
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("your_input_stream");
grabber.setOption("analyzeduration", "1000000");
grabber.setOption("probesize", "1000000");
其中,analyzeduration和probesize的值可以根据实际情况进行调整。此外,还需要注意以下两点:
海康威视的PS流可能不支持mp2音频格式,可以尝试修改音频编码方式,比如使用AAC。
在推流时,建议使用h264视频编码和AAC音频编码,因为它们是常用的编码格式,兼容性更好。同时,需要确保推流的帧率和分辨率与采集的视频流一致。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
可以尝试增加probesize和analyzeduration的值,或者设置为-1,例如:
grabber.setOption("probesize", "5000000");
grabber.setOption("analyzeduration", "5000000");
这两个参数会影响解析视频流的速度和精度,如果值设置过小,可能会导致无法解析出视频流的相关信息,从而出现类似的警告和错误信息。另外,如果仍然无法解决问题,可以考虑手动指定音频参数,例如:
grabber.setAudioOption("acodec", "mp3");
grabber.setAudioOption("ar", "44100");
同时,为了更好的排除问题,建议先通过FFmpeg命令行工具尝试播放和转码原始视频流,检查视频流的相关信息是否正确。
下面是增加probesize和analyzeduration参数的代码样例:
FFmpegLogCallback.set();
// 配置 FFmpegFrameGrabber 的视频流和音频流属性并开始推流
String rtmpUrl = "rtmp://192.168.1.200:1935/live/admin";
// 创建 FFmpegFrameGrabber 对象并设置视频流参数
// 采集器
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputStream, 0);
// 设置读取的最大数据,单位字节
grabber.setOption("probesize", "5000000");
// 设置分析的最长时间,单位微秒
grabber.setOption("analyzeduration", "5000000");
grabber.setVideoOption("vcodec", "copy");
grabber.setFormat("mpeg");
grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
grabber.setVideoCodec(avcodec.AV_CODEC_ID_H264);
//手动指定音频参数
grabber.setAudioOption("acodec", "mp3");
grabber.setAudioOption("ar", "44100");
grabber.setAudioChannels(0);
grabber.setAudioCodec(avcodec.AV_CODEC_ID_NONE);
grabber.setFrameRate(25);
grabber.setVideoBitrate(1500000);
grabber.setOption("threads", "2");
grabber.start(true);
如果我的回答解决了您的问题,请采纳!
根据提示信息可以看到警告 [mpeg @ 0x7f5ee4022e80] Could not find codec parameters for stream 1 (Audio: mp2, 0 channels): unspecified frame size,是由于FFmpegFrameGrabber无法找到码流的音频参数,建议调整analyzeduration 和 probesize 参数来提高音频参数检测的成功率。
可以在创建grabber时设置这两个参数,例如:
grabber.setOption("probesize", "5000000");
grabber.setOption("analyzeduration", "5000000");
同时注意,在创建grabber时,建议设置音频参数的读取,例如:
grabber.setAudioStream(1);
grabber.setAudioChannels(2);
grabber.setSampleRate(44100);
在这里,可以通过调整 setAudioStream 方法来指定需要读取的音频流。如果该视频码流不包含音频流,可以直接将 setAudioChannels 设置为0,表示不读取音频。
如果还有问题,建议提供更详细的日志信息以及代码细节,便于更好地定位问题。