日常工作中,如果涉及到音视频处理,免不了使用ffmpeg工具,对音视频文件进行解析。
结合日常工作,把一套可应用于生产的JAVA工具,整理于此。
maven引用
<!--ffmpeg-->
<dependency>
<groupId>net.bramp.ffmpeg</groupId>
<artifactId>ffmpeg</artifactId>
<version>0.8.0</version>
</dependency>
java工具类
public class MediaInfoUtil {
protected static final Logger LOGGER = LoggerFactory.getLogger(MediaInfoUtil.class);
private static final FFprobe ffprobe;
static {
try {
ffprobe = new FFprobe();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 获取视频的相关信息
* url请替换成完整的内网域名
* @param path 本地路径 或者 url
* @return VideoInfoVO
* @throws IOException
*/
public static MediaInfoVO getVideoParam(String path) throws IOException {
MediaInfoVO mediaInfoVO = new MediaInfoVO();
VideoInfoVO videoVO = new VideoInfoVO();
AudioInfoVO audioVO = new AudioInfoVO();
FFmpegProbeResult probeResult = ffprobe.probe(path);
FFmpegFormat format = probeResult.getFormat();
List<FFmpegStream> streams = probeResult.getStreams();
// 音频 视频 都没有
if (CollectionUtils.isEmpty(streams)){
LOGGER.error("视频文件解析失败,该文件音频和视频数据不完整,请上传合规视频文件!");
throw new IOException("视频文件解析失败,该文件音频和视频数据不完整,请上传合规视频文件");
}
// 音频 视频 只有其中一个
if (streams.size()==1) {
FFmpegStream fFmpegStream = streams.get(0);
if (fFmpegStream.codec_type == FFmpegStream.CodecType.VIDEO) {
buildVideo(path, mediaInfoVO, videoVO, format, fFmpegStream);
LOGGER.info("getVideoParam path is {} mediaInfoVO is {}", path, JSON.toJSONString(mediaInfoVO));
return mediaInfoVO;
}
LOGGER.info("getVideoParam 只有一个音频流,文件错误 path is {}", path);
return null;
}
// 视频信息 0可能为音频信息
FFmpegStream videoStream = streams.get(0);
// 音频信息 1可能为视频信息
FFmpegStream audioStream = streams.get(1);
// 视频信息
if (videoStream.codec_type == FFmpegStream.CodecType.VIDEO) {
buildVideo(path, mediaInfoVO, videoVO, format, videoStream);
}
if (audioStream.codec_type == FFmpegStream.CodecType.VIDEO) {
buildVideo(path, mediaInfoVO, videoVO, format, audioStream);
}
//音频信息
if (audioStream.codec_type == FFmpegStream.CodecType.AUDIO) {
buildAudio(mediaInfoVO, audioVO, audioStream);
}
if (videoStream.codec_type == FFmpegStream.CodecType.AUDIO) {
buildAudio(mediaInfoVO, audioVO, videoStream);
}
LOGGER.info("getVideoParam path is {} mediaInfoVO is {}", path, JSON.toJSONString(mediaInfoVO));
return mediaInfoVO;
}
private static void buildAudio(MediaInfoVO mediaInfoVO, AudioInfoVO audioVO, FFmpegStream audioStream) {
audioVO.setChannels(audioStream.channels);
audioVO.setCodecName(audioStream.codec_name);
audioVO.setSampleRate(audioStream.sample_rate);
mediaInfoVO.setAudioInfoVO(audioVO);
}
private static void buildVideo(String path, MediaInfoVO mediaInfoVO, VideoInfoVO videoVO, FFmpegFormat format,
FFmpegStream videoStream) {
getVideoInfo(path, videoVO, format, videoStream);
mediaInfoVO.setVideoInfoVO(videoVO);
}
/**
* url请替换成完整的内网域名
* @param path 本地路径 或者 url
* @return
* @throws IOException
*/
public static AudioInfoVO getAudioParam(String path) throws IOException {
AudioInfoVO audioVO = new AudioInfoVO();
FFprobe ffprobe = new FFprobe();
FFmpegProbeResult probeResult = ffprobe.probe(path);
FFmpegFormat format = probeResult.getFormat();
//
FFmpegStream audioStream = probeResult.getStreams().get(0);
// 音频信息
if (audioStream.codec_type != FFmpegStream.CodecType.AUDIO) {
return null;
}
audioVO.setDuration(format.duration);
audioVO.setSize(format.size);
audioVO.setFormat(format.format_name);
audioVO.setChannels(audioStream.channels);
audioVO.setCodecName(audioStream.codec_name);
audioVO.setSampleRate(audioStream.sample_rate);
return audioVO;
}
/**
* url请替换成完整的内网域名
* @param path 本地路径 或者 url
* @return
* @throws IOException
*/
public static PictureInfoVO getPictureParam(String path) throws IOException {
PictureInfoVO pictureInfoVO = new PictureInfoVO();
FFprobe ffprobe = new FFprobe();
FFmpegProbeResult probeResult = ffprobe.probe(path);
FFmpegFormat format = probeResult.getFormat();
//
FFmpegStream pictureStream = probeResult.getStreams().get(0);
// 图片信息
if (pictureStream.codec_type != FFmpegStream.CodecType.VIDEO) {
return null;
}
pictureInfoVO.setSize(format.size);
pictureInfoVO.setFormat(FilenameUtils.getExtension(path).split("\\?")[0]);
int width = pictureStream.width;
int height = pictureStream.height;
//分辨率
pictureInfoVO.setResolutions(new int[]{width, height});
pictureInfoVO.setCodecName(pictureStream.codec_name);
return pictureInfoVO;
}
private static void getVideoInfo(String url, VideoInfoVO videoVO, FFmpegFormat format, FFmpegStream videoStream) {
//文件大小
videoVO.setSize(format.size);
//时长
videoVO.setDuration(format.duration);
//扩展名
videoVO.setFormat(FilenameUtils.getExtension(url).split("\\?")[0]);
int width = videoStream.width;
int height = videoStream.height;
//分辨率
videoVO.setResolutions(new int[]{width, height});
//pix格式
videoVO.setPixFmt(videoStream.pix_fmt);
//编码格式
videoVO.setCodecName(videoStream.codec_name);
//码率
videoVO.setBitRate(videoStream.bit_rate);
//帧数
videoVO.setFrames(videoStream.nb_frames);
//帧率
Fraction rFrameRate = videoStream.r_frame_rate;
String frameRateStr = rFrameRate.toString();
if (StringUtils.isEmpty(frameRateStr)) {
videoVO.setFrameRate(0);
}
String[] split = frameRateStr.split("/");
float fps = Float.valueOf(split[0]) / Float.valueOf(split[1]);
videoVO.setFrameRate(Math.round(fps));
}
}
相关JAVABean
/**
* 音视频的信息
*/
@Data
public class MediaInfoVO {
/**
* 文件名称
*/
private String fileName;
/**
* 文件url
*/
private String url;
/**
* 文件id
*/
private String id;
/** 视频信息 */
private VideoInfoVO videoInfoVO;
/** 音频信息 */
private AudioInfoVO audioInfoVO;
}
/**
* 视频的信息
*/
@Data
public class VideoInfoVO {
/**
* 文件名称
*/
private String fileName;
/**
* 文件url
*/
private String url;
/**
* 文件id
*/
private String id;
/** 视频格式*/
private String format;
/** 视频大小*/
private Long size;
/** 视频时长*/
private Double duration;
/** 视频分别率 */
private int[] resolutions;
/**视频总帧数*/
private Long frames;
/**视频帧率*/
private Integer frameRate;
private String pixFmt;
private String codecName;
private Long bitRate;
}
/**
* 视频的信息
*/
@Data
public class AudioInfoVO {
/**
* 文件名称
*/
private String fileName;
/**
* 文件url
*/
private String url;
/**
* 文件id
*/
private String id;
/** 音频格式*/
private String format;
/** 音频大小*/
private Long size;
/** 音频时长*/
private Double duration;
/** 声道数 */
private Integer channels;
/** 音频编码格式 */
private String codecName;
/** 采样率 */
private Integer sampleRate;
}