基于javacv的视频转码(升级版)

目录

  • 目标
  • 依赖
  • VideoFormat.java
  • Video.java
  • 怎么使用

目标

将所有格式的视频转码为H5能播放的mp4格式

依赖

<!-- 依赖很多,不需要的自行排除 -->
<!-- 转码功能只需要以ffmpeg、javacpp、javacv、openblas、opencv开头的jar包依赖 -->
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv-platform</artifactId>
    <version>1.5.3</version>
</dependency>

VideoFormat.java

package com.videotest;

public class VideoFormat {
	
	private boolean exists;
	
	private boolean isFile;
	
	private String absolutePath;
	
	private String parent = "";
	
	private String name = "";
	
	private String simpleName = "";
	
	private String extName = "";//扩展名

	/**
	 * @See {org.bytedeco.ffmpeg.global.avcodec}
	 */
	private int videoCodec;//视频编码格式
	
	/**
	 * @See {org.bytedeco.ffmpeg.global.avcodec}
	 */
	private int audioCodec;//音频编码格式
	
	private String format = "";//封装格式

	public boolean isExists() {
		return exists;
	}

	public void setExists(boolean exists) {
		this.exists = exists;
	}

	public boolean isFile() {
		return isFile;
	}

	public void setFile(boolean isFile) {
		this.isFile = isFile;
	}

	public String getAbsolutePath() {
		return absolutePath;
	}

	public void setAbsolutePath(String absolutePath) {
		this.absolutePath = absolutePath;
	}

	public String getParent() {
		return parent;
	}

	public void setParent(String parent) {
		this.parent = parent;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getSimpleName() {
		return simpleName;
	}

	public void setSimpleName(String simpleName) {
		this.simpleName = simpleName;
	}

	public String getExtName() {
		return extName;
	}

	public void setExtName(String extName) {
		this.extName = extName;
	}

	public int getVideoCodec() {
		return videoCodec;
	}

	public void setVideoCodec(int videoCodec) {
		this.videoCodec = videoCodec;
	}

	public int getAudioCodec() {
		return audioCodec;
	}

	public void setAudioCodec(int audioCodec) {
		this.audioCodec = audioCodec;
	}

	public String getFormat() {
		return format;
	}

	public void setFormat(String format) {
		this.format = format;
	}

	@Override
	public String toString() {
		return "VideoFormat [exists=" + exists + ", isFile=" + isFile + ", parent=" + parent + ", name=" + name
				+ ", simpleName=" + simpleName + ", extName=" + extName + ", videoCodec=" + videoCodec + ", audioCodec="
				+ audioCodec + ", format=" + format + "]";
	}

}

Video.java

package com.videotest;

import java.io.File;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Video {
	private static final Logger logger = LoggerFactory.getLogger(Video.class);
	
	private static final String DEFAULT_EXTNAME = "mp4";
	
	private static final String DEFAULT_FORMAT = "mov,mp4,m4a,3gp,3g2,mj2";

	private VideoFormat videoFormat;
	
	public Video (String absolutePath) {
		this(new File(absolutePath));
	}
	
	public Video (String parent, String fileName) {
		this(new File(parent, fileName));
	}
	
	public Video (File file) {
		VideoFormat videoFormat = new VideoFormat();
		FFmpegFrameGrabber frameGrabber = null;
		try {
			videoFormat.setExists(file.exists());
			videoFormat.setFile(file.isFile());
			videoFormat.setAbsolutePath(file.getAbsolutePath());
			videoFormat.setParent(file.getParent());
			videoFormat.setName(file.getName());
			if (!file.isFile()) {
				return;
			}
			int dotLastIndex = videoFormat.getName().lastIndexOf(".");
			if (dotLastIndex > 0 && dotLastIndex < videoFormat.getName().length() - 1) {
				videoFormat.setSimpleName(videoFormat.getName().substring(0, dotLastIndex));
				videoFormat.setExtName(videoFormat.getName().substring(dotLastIndex + 1));
			} else {
				videoFormat.setSimpleName(videoFormat.getName());
			}
			frameGrabber = FFmpegFrameGrabber.createDefault(file);
			frameGrabber.start();
			videoFormat.setVideoCodec(frameGrabber.getVideoCodec());
			videoFormat.setAudioCodec(frameGrabber.getAudioCodec());
			videoFormat.setFormat(frameGrabber.getFormat());
		} catch (Exception e) {
			logger.warn(file.getAbsolutePath() + " -> error", e);
		} finally {
			if (frameGrabber != null) {
				try {
					frameGrabber.close();
				} catch (org.bytedeco.javacv.FrameGrabber.Exception e) {
					logger.warn("frameGrabber.close异常", e);
				}
			}
		}
		this.videoFormat = videoFormat;
	}

	protected VideoFormat getVideoFormat() {
		return videoFormat;
	}
	
	public boolean isVideo () {
		return this.getVideoFormat().getVideoCodec() != avcodec.AV_CODEC_ID_NONE;
	}
	
	protected boolean hasAudio () {
		return this.getVideoFormat().getAudioCodec() != avcodec.AV_CODEC_ID_NONE;
	}
	
	protected boolean isMp4 () {
		return DEFAULT_EXTNAME.equalsIgnoreCase(this.getVideoFormat().getExtName());
	}
	
	protected boolean canPlayInH5IgnoreExtName () {
		if (!this.isVideo()) {
			return false;
		}
		VideoFormat videoFormat = this.videoFormat;
		if (this.hasAudio() && videoFormat.getAudioCodec() != avcodec.AV_CODEC_ID_AAC) {
			return false;
		}
		if (videoFormat.getVideoCodec() != avcodec.AV_CODEC_ID_H264) {
			return false;
		}
		if (!DEFAULT_FORMAT.equals(videoFormat.getFormat())) {
			return false;
		}
		return true;
	}
	
	public boolean canPlayInH5 () {
		if (!this.isMp4()) {
			return false;
		}
		return this.canPlayInH5IgnoreExtName();
	}
	
	public String convert2Mp4 () throws Exception {
		return this.convert2Mp4(this.videoFormat.getParent());
	}
	
	/**
	 * 
	 * @param outputParent 输出目录
	 * @return 输出文件的绝对路径
	 * @throws Exception
	 */
	public String convert2Mp4 (String outputParent) throws Exception {
		VideoFormat videoFormat = this.videoFormat;
		if (!this.isVideo()) {
			throw new org.bytedeco.javacv.FrameGrabber.Exception("[" + videoFormat.getAbsolutePath() + "] 不是视频文件");
		}
		File outfile = new File(outputParent);
		if (outfile.isFile()) {
			throw new FileAlreadyExistsException("[" + outputParent + "] 是文件并且已存在");
		}
		if (!outfile.exists()) {
			outfile.mkdirs();
		}
		String outFilePath = new File(outputParent, videoFormat.getSimpleName() + "_recode." + DEFAULT_EXTNAME).getAbsolutePath();
		outFilePath = outFilePath.replace("\\", "/");
		//如果视频本来就能在浏览器中播放,则只进行复制
		if (this.canPlayInH5IgnoreExtName()) {
			Files.copy(new File(videoFormat.getParent(), videoFormat.getName()).toPath(), new File(outFilePath).toPath(), StandardCopyOption.REPLACE_EXISTING);
			return outFilePath;
		}
		FFmpegFrameGrabber frameGrabber = FFmpegFrameGrabber.createDefault(new File(videoFormat.getParent(), videoFormat.getName()));
		Frame captured_frame = null;
		FFmpegFrameRecorder recorder = null;
		try {
			frameGrabber.start();
			recorder = new FFmpegFrameRecorder(outFilePath, frameGrabber.getImageWidth(), frameGrabber.getImageHeight(), frameGrabber.getAudioChannels());
			recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
			recorder.setFormat(DEFAULT_EXTNAME);
			recorder.setFrameRate(frameGrabber.getFrameRate());
			recorder.setVideoBitrate(frameGrabber.getVideoBitrate());
			recorder.setAspectRatio(frameGrabber.getAspectRatio());
			recorder.setAudioOptions(frameGrabber.getAudioOptions());
			recorder.setSampleRate(frameGrabber.getSampleRate());
			recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
			recorder.start();
			while (true) {
				captured_frame = frameGrabber.grabFrame();
				if (captured_frame == null) {
					logger.info(outFilePath + "转码完成");
					break;
				}
				recorder.record(captured_frame);
			}
		} finally {
			if (recorder != null) {
				try {
					recorder.close();
				} catch (Exception e) {
					logger.warn("recorder.close异常", e);
				}
			}
			try {
				frameGrabber.close();
			} catch (org.bytedeco.javacv.FrameGrabber.Exception e) {
				logger.warn("frameGrabber.close异常", e);
			}
		}
		return outFilePath;
	}

}

怎么使用

public static void main(String[] args) throws Exception {
	Video video = new Video("D:", "1607589556364324.mkv");
	if (video.isVideo()) {
		String convert2Mp4 = video.convert2Mp4();
		System.out.println(convert2Mp4);
	}
	
//		Video video = new Video("D:", "1607589556364324.mkv");
//		if (video.isVideo() && !video.canPlayInH5()) {
//			String convert2Mp4 = video.convert2Mp4();
//			System.out.println(convert2Mp4);
//		}
}

基于javacv的视频截图和转码(升级版)

你可能感兴趣的:(java,javacv,ffmpeg,mp4,视频转码)