描述
视频文件中包含视频和音频数据,那如何通过Java将处理音视频文件,这里案例使用OpenCV的视觉框架,OpenCV对FFMPEG(音视频)框架做了封装。
OpenCV的jar包支持跨平台:window系统、Linux系统(x86-x64 arm)、macos
核心类
-
FFmpegFrameGrabber 它可以打开本地视频或拉取RTMP流媒体服务器。内部实现FFMPEG中的 解复用->解码->像素转换->重采样等操作
-
FFmpegFrameRecorder 将视频中每一帧数据存储音频或视频数据存储到本地。内部实现FFMPEG中的 复用->编码->封装包->数据到本地
FFmpegFrameGrabber 类方法
方法名称 | 方法描述 |
---|---|
FFmpegFrameGrabber(String filename) | 构造函数,实例化传入文件路径,或流媒体地址 |
setFrameRate | 设置视频帧率 |
setGopSize | 设置视频gop,与帧率相同,相当于间隔1秒chan's一个关键帧 |
setVideoCodec | 设置压缩方式 ,如AV_CODEC_ID_H264,AV_CODEC_ID_MJPEG等 |
setPixelFormat | 设置封装格式 |
setVideoOption | 设置ffmpeg参数 |
start | 开启视频解码操作 |
setOption | 设置ffmpeg参数,如:rtsp_transport |
grab() | 获取一帧解码数据 |
getImageWidth() | 视频宽 |
getImageHeight() | 视频高 |
getAudioChannels() | 音频声道数量,单声道,双声道 |
grabPacket() | FFMPEG包数据 |
FFmpegFrameRecorder 类方法
方法名称 | 方法描述 |
---|---|
FFmpegFrameRecorder(String filename, int imageWidth, int imageHeight) | 设置视频文件存放路径 |
FFmpegFrameRecorder(String filename, int audioChannels) | 设置音频文件存放路径 |
FFmpegFrameRecorder(String filename, int imageWidth, int imageHeight, int audioChannels) | 设置音视频存放路径 |
setVideoOption | 设置视频参数,参考ffmpeg |
setFrameRate | 设置帧率 |
setGopSize | 设置gop,与帧率相同,相当于间隔1秒chan's一个关键帧 |
setVideoCodec | 设置压缩方式 ,如AV_CODEC_ID_H264,AV_CODEC_ID_MJPEG等 |
setPixelFormat | 设置封装格式 |
setAudioCodec | 设置音频编码格式 |
start | 开始录制 |
recordPacket | 写入AVPacket包数据 |
grab | 写入Frame解压数据 |
引入Maven依赖
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv-platform</artifactId>
<version>4.5.3-1.5.6</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>4.4-1.5.6</version>
</dependency>
音视频分离存储
package com.xl.ffmpeg;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FFmpegLogCallback;
import org.bytedeco.javacv.Frame;
import static org.bytedeco.ffmpeg.global.avutil.*;
public class Test4 {
public static void main(String[] args) throws Exception {
//开启日志
FFmpegLogCallback.set();
String inputUrl="2.mp4";
//抽取视频和音频存储路径
String outputVideoUrl="d:\\1.mp4";
String outputaduioUrl="d:\\2.aac";
//1.拉取视频
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputUrl);
grabber.start();
//2.录制视频
FFmpegFrameRecorder videoRecorder=new FFmpegFrameRecorder(outputVideoUrl,grabber.getImageWidth(),grabber.getImageHeight());
videoRecorder.setFrameRate(25);// 设置帧率
videoRecorder.setGopSize(25);// 设置gop,与帧率相同,相当于间隔1秒chan's一个关键帧
videoRecorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); //压缩方式264
videoRecorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); //视频源数据yuv
videoRecorder.setVideoOption("threads", "8"); //解码线程数
videoRecorder.start();
//3.录制音频
FFmpegFrameRecorder audioRecorder=new FFmpegFrameRecorder(outputaduioUrl,grabber.getAudioChannels());
audioRecorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC); //设置音频压缩方式
audioRecorder.start();
//读取每一种数据,一帧数据可能是音频或视频
Frame avFrame=null;
while((avFrame = grabber.grab())!=null){
if(avFrame.streamIndex==AVMEDIA_TYPE_VIDEO){ //视频帧
videoRecorder.record(avFrame); //录制视频
}else if(avFrame.streamIndex==AVMEDIA_TYPE_AUDIO){ //音频帧
audioRecorder.record(avFrame); //录制音频
}
}
//关闭相关对象
grabber.close();
videoRecorder.close();
audioRecorder.close();
}
}
RTMP拉流存储
package com.xl.ffmpeg;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FFmpegLogCallback;
import org.bytedeco.javacv.Frame;
import static org.bytedeco.ffmpeg.global.avutil.*;
public class Test4 {
public static void main(String[] args) throws Exception {
//开启日志
FFmpegLogCallback.set();
String inputUrl="rtmp://58.200.131.2:1935/livetv/hunanhd";
//抽取视频和音频存储路径
String outputVideoUrl="d:\\1.flv";
//1.拉取视频
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputUrl);
grabber.setOption("threads", "1");
// 设置缓存大小,提高画质、减少卡顿花屏
grabber.setOption("buffer_size", "1024000");
// 读写超时,适用于所有协议的通用读写超时
grabber.setOption("rw_timeout", "15000000");
// 探测视频流信息,为空默认5000000微秒
grabber.setOption("probesize","15000000");
// 解析视频流信息,为空默认5000000微秒
grabber.setOption("analyzeduration", "15000000");
// rtmp拉流缓冲区,默认3000毫秒
grabber.setOption("rtmp_buffer", "1000");
grabber.start();
//2.录制视频/音频
FFmpegFrameRecorder recorder=new FFmpegFrameRecorder(outputVideoUrl,grabber.getImageWidth(),grabber.getImageHeight());
recorder.setFrameRate(25);// 设置帧率
recorder.setGopSize(25);// 设置gop,与帧率相同,相当于间隔1秒chan's一个关键帧
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); //压缩方式264
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); //视频源数据yuv
recorder.setVideoOption("threads", "8"); //解码线程数
recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC); //设置音频压缩方式
recorder.setFormat("flv");
recorder.start();
//读取每一种数据,一帧数据可能是音频或视频
Frame avFrame=null;
while((avFrame = grabber.grab())!=null){
recorder.record(avFrame); //录制
}
//关闭相关对象
grabber.close();
recorder.close();
}
}
网友评论