目录

  • 目标
  • 全量依赖
  • 最小依赖
  • 截图配置类
  • 转码配置类
  • 提取音频配置类
  • 源视频处理结果类
  • 核心类
  • 怎么使用

目标

将所有格式的视频转码为H5能播放的mp4格式,也可以截取任意一帧图片

全量依赖

<dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.3</version>
</dependency>

最小依赖

直接引入javacv-platform依赖,打包后大约有800MB,以下是支持linux-x86_64和windows-x86_64平台的转码和截图功能的最小依赖配置

<properties><javacv.version>1.5.3</javacv.version><javacv.linux-x86_64>linux-x86_64</javacv.linux-x86_64><javacv.windows-x86_64>windows-x86_64</javacv.windows-x86_64>
</properties><dependencies><dependency><groupId>org.bytedeco</groupId><artifactId>javacv</artifactId><version>${javacv.version}</version><exclusions><exclusion><groupId>org.bytedeco</groupId><artifactId>flycapture</artifactId></exclusion><exclusion><groupId>org.bytedeco</groupId><artifactId>libdc1394</artifactId></exclusion><exclusion><groupId>org.bytedeco</groupId><artifactId>libfreenect</artifactId></exclusion><exclusion><groupId>org.bytedeco</groupId><artifactId>libfreenect2</artifactId></exclusion><exclusion><groupId>org.bytedeco</groupId><artifactId>librealsense</artifactId></exclusion><exclusion><groupId>org.bytedeco</groupId><artifactId>librealsense2</artifactId></exclusion><exclusion><groupId>org.bytedeco</groupId><artifactId>videoinput</artifactId></exclusion><exclusion><groupId>org.bytedeco</groupId><artifactId>artoolkitplus</artifactId></exclusion><exclusion><groupId>org.bytedeco</groupId><artifactId>flandmark</artifactId></exclusion><exclusion><groupId>org.bytedeco</groupId><artifactId>leptonica</artifactId></exclusion><exclusion><groupId>org.bytedeco</groupId><artifactId>tesseract</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>ffmpeg</artifactId><version>4.2.2-${javacv.version}</version><classifier>${javacv.linux-x86_64}</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>ffmpeg</artifactId><version>4.2.2-${javacv.version}</version><classifier>${javacv.windows-x86_64}</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>javacpp</artifactId><version>${javacv.version}</version><classifier>${javacv.linux-x86_64}</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>javacpp</artifactId><version>${javacv.version}</version><classifier>${javacv.windows-x86_64}</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>openblas</artifactId><version>0.3.9-${javacv.version}</version><classifier>${javacv.linux-x86_64}</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>openblas</artifactId><version>0.3.9-${javacv.version}</version><classifier>${javacv.windows-x86_64}</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>opencv</artifactId><version>4.3.0-${javacv.version}</version><classifier>${javacv.linux-x86_64}</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>opencv</artifactId><version>4.3.0-${javacv.version}</version><classifier>${javacv.windows-x86_64}</classifier></dependency>
</dependencies>

截图配置类

TargetShot.java

package com.videotest.video;public class TargetShot {private String targetParentPath;//截图保存目录,如果不设置,则与源文件目录相同private String prefix = "";//截图文件名前缀private String suffix = "_shot";//截图文件简单名后缀private String extName = "jpg";//截图文件扩展名private int frameNum = 1;//截取视频第几帧public String getTargetParentPath() {return targetParentPath;}public TargetShot setTargetParentPath(String targetParentPath) {this.targetParentPath = targetParentPath;return this;}public String getPrefix() {return prefix;}public TargetShot setPrefix(String prefix) {this.prefix = prefix;return this;}public String getSuffix() {return suffix;}public TargetShot setSuffix(String suffix) {this.suffix = suffix;return this;}public String getExtName() {return extName;}public TargetShot setExtName(String extName) {this.extName = extName;return this;}public int getFrameNum() {return frameNum;}public TargetShot setFrameNum(int frameNum) {if (frameNum < 1) {frameNum = 1;}this.frameNum = frameNum;return this;}@Overridepublic String toString() {return "TargetShot [targetParentPath=" + targetParentPath + ", prefix=" + prefix + ", suffix=" + suffix+ ", extName=" + extName + ", frameNum=" + frameNum + "]";}}

转码配置类

TargetVideo.class

package com.videotest.video;public class TargetVideo {private String targetParentPath;//转码后的文件保存目录,如果不设置,则与源文件目录相同private String prefix = "";//转码后的文件名前缀private String suffix = "_recode";//转码后的文件简单名后缀private boolean closeSound;//转码后的文件是否删除音轨,默认不删除public String getTargetParentPath() {return targetParentPath;}public TargetVideo setTargetParentPath(String targetParentPath) {this.targetParentPath = targetParentPath;return this;}public String getPrefix() {return prefix;}public TargetVideo setPrefix(String prefix) {this.prefix = prefix;return this;}public String getSuffix() {return suffix;}public TargetVideo setSuffix(String suffix) {this.suffix = suffix;return this;}public boolean isCloseSound() {return closeSound;}public TargetVideo setCloseSound(boolean closeSound) {this.closeSound = closeSound;return this;}@Overridepublic String toString() {return "TargetVideo [targetParentPath=" + targetParentPath + ", prefix=" + prefix + ", suffix=" + suffix+ ", closeSound=" + closeSound + "]";}}

提取音频配置类

TargetSound.class

package com.videotest.video;public class TargetSound {private String targetParentPath;//截图保存目录,如果不设置,则与源文件目录相同private String prefix = "";//截图文件名前缀private String suffix = "_sound";//截图文件简单名后缀private String extName = "mp3";//截图文件扩展名public String getTargetParentPath() {return targetParentPath;}public TargetSound setTargetParentPath(String targetParentPath) {this.targetParentPath = targetParentPath;return this;}public String getPrefix() {return prefix;}public TargetSound setPrefix(String prefix) {this.prefix = prefix;return this;}public String getSuffix() {return suffix;}public TargetSound setSuffix(String suffix) {this.suffix = suffix;return this;}public String getExtName() {return extName;}public TargetSound setExtName(String extName) {this.extName = extName;return this;}@Overridepublic String toString() {return "TargetSound [targetParentPath=" + targetParentPath + ", prefix=" + prefix + ", suffix=" + suffix+ ", extName=" + extName + "]";}}

源视频处理结果类

VideoInfo.class

package com.videotest.video;public class VideoInfo<T> {private T id;//数据唯一标识private boolean sourceExists;//源文件是否存在private boolean sourceIsFile;//源文件是否文件private String sourceAbsolutePath;//sourceParentPath + "/" + sourceNameprivate String sourceParentPath = "";//源文件目录private String sourceName = ""; //sourceSimpleName + ["." + extName]private String sourceSimpleName = "";private String sourceExtName = "";//扩展名/*** @See {org.bytedeco.ffmpeg.global.avcodec}*/private int sourceVideoCodec;//视频编码格式/*** @See {org.bytedeco.ffmpeg.global.avcodec}*/private int sourceAudioCodec;//音频编码格式private String sourceFormat = "";//封装格式private boolean shotExists;//处理结果是否存在截图private String targetShotPath;//截图绝对路径private String targetShotName;//截图文件名private boolean videoExists;//处理结果是否存在转码后的视频private String targetVideoPath;//转码后的视频绝对路径private String targetVideoName;//转码后的视频文件名private boolean soundExists;//处理结果是否存在音频private String targetSoundPath;//提取的音频绝对路径private String targetSoundName;//提取的音频文件名public VideoInfo(T id) {this.id = id;}public T getId() {return id;}void setId(T id) {this.id = id;}public boolean isSourceExists() {return sourceExists;}void setSourceExists(boolean sourceExists) {this.sourceExists = sourceExists;}public boolean isSourceIsFile() {return sourceIsFile;}void setSourceIsFile(boolean sourceIsFile) {this.sourceIsFile = sourceIsFile;}public String getSourceAbsolutePath() {return sourceAbsolutePath;}void setSourceAbsolutePath(String sourceAbsolutePath) {this.sourceAbsolutePath = sourceAbsolutePath;}public String getSourceParentPath() {return sourceParentPath;}void setSourceParentPath(String sourceParentPath) {this.sourceParentPath = sourceParentPath;}public String getSourceName() {return sourceName;}void setSourceName(String sourceName) {this.sourceName = sourceName;}public String getSourceSimpleName() {return sourceSimpleName;}void setSourceSimpleName(String sourceSimpleName) {this.sourceSimpleName = sourceSimpleName;}public String getSourceExtName() {return sourceExtName;}void setSourceExtName(String sourceExtName) {this.sourceExtName = sourceExtName;}public int getSourceVideoCodec() {return sourceVideoCodec;}void setSourceVideoCodec(int sourceVideoCodec) {this.sourceVideoCodec = sourceVideoCodec;}public int getSourceAudioCodec() {return sourceAudioCodec;}void setSourceAudioCodec(int sourceAudioCodec) {this.sourceAudioCodec = sourceAudioCodec;}public String getSourceFormat() {return sourceFormat;}void setSourceFormat(String sourceFormat) {this.sourceFormat = sourceFormat;}public boolean getShotExists() {return shotExists;}void setShotExists(boolean shotExists) {this.shotExists = shotExists;}public String getTargetShotPath() {return targetShotPath;}void setTargetShotPath(String targetShotPath) {this.targetShotPath = targetShotPath;}public String getTargetShotName() {return targetShotName;}void setTargetShotName(String targetShotName) {this.targetShotName = targetShotName;}public boolean getVideoExists() {return videoExists;}void setVideoExists(boolean videoExists) {this.videoExists = videoExists;}public String getTargetVideoPath() {return targetVideoPath;}void setTargetVideoPath(String targetVideoPath) {this.targetVideoPath = targetVideoPath;}public String getTargetVideoName() {return targetVideoName;}void setTargetVideoName(String targetVideoName) {this.targetVideoName = targetVideoName;}public boolean isSoundExists() {return soundExists;}void setSoundExists(boolean soundExists) {this.soundExists = soundExists;}public String getTargetSoundPath() {return targetSoundPath;}void setTargetSoundPath(String targetSoundPath) {this.targetSoundPath = targetSoundPath;}public String getTargetSoundName() {return targetSoundName;}void setTargetSoundName(String targetSoundName) {this.targetSoundName = targetSoundName;}@Overridepublic String toString() {return "VideoInfo [id=" + id + ", sourceExists=" + sourceExists + ", sourceIsFile=" + sourceIsFile+ ", sourceAbsolutePath=" + sourceAbsolutePath + ", sourceParentPath=" + sourceParentPath+ ", sourceName=" + sourceName + ", sourceSimpleName=" + sourceSimpleName + ", sourceExtName="+ sourceExtName + ", sourceVideoCodec=" + sourceVideoCodec + ", sourceAudioCodec=" + sourceAudioCodec+ ", sourceFormat=" + sourceFormat + ", shotExists=" + shotExists + ", targetShotPath=" + targetShotPath+ ", targetShotName=" + targetShotName + ", videoExists=" + videoExists + ", targetVideoPath="+ targetVideoPath + ", targetVideoName=" + targetVideoName + ", soundExists=" + soundExists+ ", targetSoundPath=" + targetSoundPath + ", targetSoundName=" + targetSoundName + "]";}}

核心类

Video.class

package com.videotest.video;import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;import javax.imageio.ImageIO;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 org.bytedeco.javacv.Java2DFrameConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public final class Video<T> {private static final Logger logger = LoggerFactory.getLogger(Video.class);private static final String DEFAULT_VIDEO_EXTNAME = "mp4";private static final String DEFAULT_FORMAT = "mov,mp4,m4a,3gp,3g2,mj2";private VideoInfo<T> videoInfo;private File sourceFile;private TargetShot targetShot;private TargetVideo targetVideo;private TargetSound targetSound;private Video (T id) {this.videoInfo = new VideoInfo<T>(id);}public static <T> Video<T> getInstance(T id) {return new Video<T>(id);}public Video<T> sourceFile (String sourceAbsolutePath) {return this.sourceFile(new File(sourceAbsolutePath));}public Video<T> sourceFile (String sourceParentPath, String sourceName) {return this.sourceFile(new File(sourceParentPath, sourceName));}public Video<T> sourceFile (File sourceFile) {this.sourceFile = sourceFile;return this;}/*** 开启截图功能* @return*/public Video<T> enableShot () {this.targetShot = new TargetShot();return this;}public Video<T> enableShot (TargetShot targetShot) {this.targetShot = targetShot;return this;}/*** 开启转码功能* @return*/public Video<T> enableVideo () {this.targetVideo = new TargetVideo();return this;}public Video<T> enableVideo (TargetVideo targetVideo) {this.targetVideo = targetVideo;return this;}/*** 开启提取音频功能* @return*/public Video<T> enableSound () {this.targetSound = new TargetSound();return this;}public Video<T> enableSound (TargetSound targetSound) {this.targetSound = targetSound;return this;}/*** 开始转码截图* @return*/public VideoInfo<T> start () {avutil.av_log_set_level(avutil.AV_LOG_INFO);FFmpegLogCallback.set();VideoInfo<T> videoInfo = this.videoInfo;File sourceFile = this.sourceFile;TargetVideo targetVideo = this.targetVideo;TargetShot targetShot = this.targetShot;TargetSound targetSound = this.targetSound;FFmpegFrameGrabber frameGrabber = null;try {videoInfo.setSourceExists(sourceFile.exists());videoInfo.setSourceIsFile(sourceFile.isFile());videoInfo.setSourceAbsolutePath(sourceFile.getAbsolutePath().replace("\\", "/"));videoInfo.setSourceParentPath(sourceFile.getParent().replace("\\", "/"));if (targetVideo != null && targetVideo.getTargetParentPath() == null) {targetVideo.setTargetParentPath(videoInfo.getSourceParentPath());}if (targetShot != null && targetShot.getTargetParentPath() == null) {targetShot.setTargetParentPath(videoInfo.getSourceParentPath());}if (targetSound != null && targetSound.getTargetParentPath() == null) {targetSound.setTargetParentPath(videoInfo.getSourceParentPath());}videoInfo.setSourceName(sourceFile.getName());if (!sourceFile.isFile()) {return videoInfo;}int dotLastIndex = videoInfo.getSourceName().lastIndexOf(".");if (dotLastIndex > 0 && dotLastIndex < videoInfo.getSourceName().length() - 1) {videoInfo.setSourceSimpleName(videoInfo.getSourceName().substring(0, dotLastIndex));videoInfo.setSourceExtName(videoInfo.getSourceName().substring(dotLastIndex + 1));} else {videoInfo.setSourceSimpleName(videoInfo.getSourceName());}frameGrabber = FFmpegFrameGrabber.createDefault(sourceFile);frameGrabber.start();videoInfo.setSourceVideoCodec(frameGrabber.getVideoCodec());videoInfo.setSourceAudioCodec(frameGrabber.getAudioCodec());videoInfo.setSourceFormat(frameGrabber.getFormat());if (!this.isVideo()) {throw new org.bytedeco.javacv.FrameGrabber.Exception("[" + videoInfo.getSourceAbsolutePath() + "] 不是视频文件");}if (targetShot != null) {this.shot(frameGrabber);}} catch (Exception e) {logger.warn(sourceFile.getAbsolutePath() + " -> error", e);} finally {if (frameGrabber != null) {try {frameGrabber.close();} catch (org.bytedeco.javacv.FrameGrabber.Exception e) {logger.warn("frameGrabber.close异常", e);}frameGrabber = null;}}if (targetVideo != null) {this.convert2Mp4();}if (targetSound != null && this.hasAudio()) {this.extractSound();}return videoInfo;}private void shot (FFmpegFrameGrabber frameGrabber) throws Exception {TargetShot targetShot = this.targetShot;VideoInfo<T> videoInfo = this.videoInfo;Frame frame = null;int i = 0;int fps = (int) frameGrabber.getFrameRate();int lengthInFrames = frameGrabber.getLengthInFrames();int frameNum = targetShot.getFrameNum();BufferedImage buffer = null;while (i < lengthInFrames) {frame = frameGrabber.grabImage();if (frameNum <= 1|| i >= fps && i % (fps * frameNum) == 0|| i == (lengthInFrames - 1) / fps * fps) {Java2DFrameConverter converter = new Java2DFrameConverter();buffer = converter.getBufferedImage(frame);File file = new File(targetShot.getTargetParentPath(), targetShot.getPrefix() + videoInfo.getSourceSimpleName() + targetShot.getSuffix() + "." + targetShot.getExtName());Files.deleteIfExists(file.toPath());ImageIO.write(buffer, targetShot.getExtName(), file);videoInfo.setShotExists(true);videoInfo.setTargetShotPath(file.getAbsolutePath().replace("\\", "/"));videoInfo.setTargetShotName(file.getName());logger.info(videoInfo.getTargetShotPath() + " -> 截图完成");break;}i++;}frameGrabber.stop();}private void convert2Mp4 () {VideoInfo<T> videoInfo = this.videoInfo;TargetVideo targetVideo = this.targetVideo;File sourceFile = this.sourceFile;FFmpegFrameGrabber frameGrabber = null;FFmpegFrameRecorder recorder = null;try {File videoOutFile = new File(targetVideo.getTargetParentPath());if (videoOutFile.isFile()) {throw new FileAlreadyExistsException("[" + targetVideo.getTargetParentPath() + "] 是文件并且已存在");}if (!videoOutFile.exists()) {videoOutFile.mkdirs();}File file = new File(targetVideo.getTargetParentPath(), targetVideo.getPrefix() + videoInfo.getSourceSimpleName() + targetVideo.getSuffix() + "." + DEFAULT_VIDEO_EXTNAME);String videoOutFilePath = file.getAbsolutePath().replace("\\", "/");if (this.canPlayInH5IgnoreExtName() && (!targetVideo.isCloseSound() || !this.hasAudio())) {Files.copy(new File(videoInfo.getSourceParentPath(), videoInfo.getSourceName()).toPath(), new File(videoOutFilePath).toPath(), StandardCopyOption.REPLACE_EXISTING);} else {frameGrabber = FFmpegFrameGrabber.createDefault(sourceFile);frameGrabber.start();Frame captured_frame = null;recorder = new FFmpegFrameRecorder(videoOutFilePath, frameGrabber.getImageWidth(), frameGrabber.getImageHeight(), frameGrabber.getAudioChannels());recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);recorder.setFormat(DEFAULT_VIDEO_EXTNAME);recorder.setFrameRate(frameGrabber.getFrameRate());int bitrate = Long.valueOf(frameGrabber.getFormatContext().bit_rate()).intValue();if (bitrate > 0) {int videoBitrate = frameGrabber.getVideoBitrate();int audioBitrate = frameGrabber.getAudioBitrate();if (audioBitrate < 1) {recorder.setVideoBitrate(bitrate);} else if (videoBitrate < 1) {recorder.setAudioBitrate(bitrate);} else {double rate = (videoBitrate + audioBitrate) * 1.0 / bitrate;if (rate > 0.95 && rate < 1.05) {recorder.setVideoBitrate(videoBitrate);recorder.setAudioBitrate(audioBitrate);} else {recorder.setVideoBitrate(Math.round(bitrate * 1.0f * videoBitrate / (videoBitrate + audioBitrate)));recorder.setAudioBitrate(Math.round(bitrate * 1.0f * audioBitrate / (videoBitrate + audioBitrate)));}}}recorder.setSampleRate(frameGrabber.getSampleRate());recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);recorder.start();if (targetVideo.isCloseSound()) {while (true) {captured_frame = frameGrabber.grabImage();if (captured_frame == null) {logger.info(videoOutFilePath + " 转码完成");break;}if (frameGrabber.getTimestamp() > -1) {recorder.setTimestamp(frameGrabber.getTimestamp());}recorder.record(captured_frame);}} else {while (true) {captured_frame = frameGrabber.grabFrame();if (captured_frame == null) {logger.info(videoOutFilePath + " 转码完成");break;}if (frameGrabber.getTimestamp() > -1) {recorder.setTimestamp(frameGrabber.getTimestamp());}recorder.record(captured_frame);}}}videoInfo.setVideoExists(true);videoInfo.setTargetVideoPath(videoOutFilePath);videoInfo.setTargetVideoName(file.getName());} catch (Exception e) {logger.warn(sourceFile.getAbsolutePath() + " -> 转码 error", e);} finally {if (recorder != null) {try {recorder.close();} catch (Exception e) {logger.warn("recorder.close异常", e);}}if (frameGrabber != null) {try {frameGrabber.close();} catch (org.bytedeco.javacv.FrameGrabber.Exception e) {logger.warn("frameGrabber.close异常", e);}}}}private void extractSound() {VideoInfo<T> videoInfo = this.videoInfo;TargetSound targetSound = this.targetSound;File sourceFile = this.sourceFile;FFmpegFrameGrabber frameGrabber = null;FFmpegFrameRecorder recorder = null;try {File soundOutFile = new File(targetSound.getTargetParentPath());if (soundOutFile.isFile()) {throw new FileAlreadyExistsException("[" + targetSound.getTargetParentPath() + "] 是文件并且已存在");}if (!soundOutFile.exists()) {soundOutFile.mkdirs();}File file = new File(targetSound.getTargetParentPath(), targetSound.getPrefix() + videoInfo.getSourceSimpleName() + targetSound.getSuffix() + "." + targetSound.getExtName());String soundOutFilePath = file.getAbsolutePath().replace("\\", "/");frameGrabber = FFmpegFrameGrabber.createDefault(sourceFile);frameGrabber.start();Frame captured_frame = null;recorder = new FFmpegFrameRecorder(soundOutFilePath, frameGrabber.getAudioChannels());recorder.setFormat(targetSound.getExtName());recorder.setSampleRate(frameGrabber.getSampleRate());int bitrate = Long.valueOf(frameGrabber.getFormatContext().bit_rate()).intValue();if (bitrate > 0) {int videoBitrate = frameGrabber.getVideoBitrate();int audioBitrate = frameGrabber.getAudioBitrate();if (audioBitrate > 0) {if (videoBitrate < 1) {recorder.setAudioBitrate(bitrate);} else {double rate = (videoBitrate + audioBitrate) * 1.0 / bitrate;if (rate > 0.95 && rate < 1.05) {recorder.setAudioBitrate(audioBitrate);} else {recorder.setAudioBitrate(Math.round(bitrate * 1.0f * audioBitrate / (videoBitrate + audioBitrate)));}}}}recorder.start();while (true) {captured_frame = frameGrabber.grabSamples();if (captured_frame == null) {logger.info(soundOutFilePath + " 音频提取完成");break;}if (frameGrabber.getTimestamp() > -1) {recorder.setTimestamp(frameGrabber.getTimestamp());}recorder.recordSamples(captured_frame.samples);}videoInfo.setTargetSoundPath(soundOutFilePath);videoInfo.setTargetSoundName(file.getName());videoInfo.setSoundExists(true);} catch (Exception e) {logger.warn(sourceFile.getAbsolutePath() + " -> 音频提取 error", e);} finally {if (recorder != null) {try {recorder.close();} catch (Exception e) {logger.warn("recorder.close异常", e);}}if (frameGrabber != null) {try {frameGrabber.close();} catch (org.bytedeco.javacv.FrameGrabber.Exception e) {logger.warn("frameGrabber.close异常", e);}}}}private boolean isVideo () {return this.videoInfo.getSourceVideoCodec() != avcodec.AV_CODEC_ID_NONE;}private boolean hasAudio () {return this.videoInfo.getSourceAudioCodec() != avcodec.AV_CODEC_ID_NONE;}private boolean canPlayInH5IgnoreExtName () {if (!this.isVideo()) {return false;}VideoInfo<T> videoInfo = this.videoInfo;if (this.hasAudio() && videoInfo.getSourceAudioCodec() != avcodec.AV_CODEC_ID_AAC) {return false;}if (videoInfo.getSourceVideoCodec() != avcodec.AV_CODEC_ID_H264) {return false;}if (!DEFAULT_FORMAT.equals(videoInfo.getSourceFormat())) {return false;}return true;}}

怎么使用

package com.videotest;import java.io.File;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.videotest.video.TargetShot;
import com.videotest.video.TargetSound;
import com.videotest.video.TargetVideo;
import com.videotest.video.Video;
import com.videotest.video.VideoInfo;public class Test {private static final Logger logger = LoggerFactory.getLogger(Test.class);public static void main(String[] args) throws JsonProcessingException {File file = new File("D:/data");File[] listFiles = file.listFiles();for (File file2 : listFiles) {VideoInfo<Long> videoInfo = Video.getInstance(4622L)
//              .getInstance("234567765")
//              .sourceFile("D:/案例视频/测试android", "同业36-安卓.mp4")
//              .sourceFile("D:/1607589556364qq.mp4").sourceFile(file2).enableShot(null)
//              .enableShot(new TargetShot())
//              .enableShot(new TargetShot().setExtName("png").setPrefix("tmp_").setTargetParentPath("D:/data")).enableVideo(null)
//              .enableVideo(new TargetVideo())
//              .enableVideo(new TargetVideo().setCloseSound(true)) //关闭音频.enableSound()
//              .enableSound(new TargetSound().setExtName("mp3").setPrefix("tmp_").setSuffix("").setTargetParentPath("D:/data")).start();String writeValueAsString = new ObjectMapper().writeValueAsString(videoInfo);logger.info(writeValueAsString);}}
}

基于javacv的视频截图、转码、提取音频相关推荐

  1. 基于 FFMPEG 的视频编码 源码(libavcodec,C++ Qt)

    基于 FFMPEG 的视频编码 源码(libavcodec,C++ Qt) 昨晚把源代码好好整理了一下,加入了视频时间限制功能.源码放这里,大家随便用. 关于代码的解释可以看我另一篇博客: 基于 FF ...

  2. 基于javacv的视频编码格式判断及转码

    目录 目标 依赖 从网上找的代码 遇到问题 眼前的希望 ~~最终代码~~ 升级代码 目标 将所有格式的视频 转码为mp4格式 升级版 依赖 <!-- 依赖很多,不需要的自行排除 --> & ...

  3. javacv音视频截图,音频抽取汇总

    概述: java 使用 javacv 视频截帧, 跳到指定帧截图, 从视频中抽取音频, 音频分割为多段 1 依赖: <dependency><groupId>org.byted ...

  4. 如何从视频中分离音频/提取音频/提取视频

    我已经做成了在线服务,免费使用:https://www.raoyunsoft.com/videotools/split_video 要想分离音频,提取音频,或者提取视频,那么不得不推荐FFmpeg,F ...

  5. 在直播APP系统源码中基于腾讯视频云SDK制作简易版直播回放播放器

    在直播App系统中,当主播结束之后,我们需要使用播放器观看直播的一些回放片段,在观看回放的过程中,我们会使用到开始,暂停,控制播放位置,进度监听,全屏等功能,然而腾讯点播并没有提供这些简单的控制功能, ...

  6. ffmpeg 截图 java_Java Web 中使用ffmpeg实现视频转码、视频截图

    视频网站中提供的在线视频播放功能,播放的都是FLV格式的文件,它是Flash动画文件,可通过Flash制作的播放器来播放该文件.项目中用制作的player.swf播放器. 多媒体视频处理工具FFmpe ...

  7. JavaCV音视频开发宝典:基于JavaCV实现wav音频直播服务,wav在线FM电台直播服务,无需流媒体服务,浏览器原生audio标签直接播放wav直播音频

    <JavaCV音视频开发宝典>专栏目录导航 <JavaCV音视频开发宝典>专栏介绍和目录 ​ 前言 之前写过了mp3实现FM电台直播服务:<JavaCV音视频开发宝典:J ...

  8. 基于Java毕业设计弹幕视频网站源码+系统+mysql+lw文档+部署软件

    基于Java毕业设计弹幕视频网站源码+系统+mysql+lw文档+部署软件 基于Java毕业设计弹幕视频网站源码+系统+mysql+lw文档+部署软件 开发语言:Java语言 开发软件:idea ec ...

  9. 基于图像识别和文字识别用 Python 提取视频字幕

    基于图像识别和文字识别用 Python 提取视频字幕 本文介绍使用 Python 基于图像识别提取视频中的字幕,并使用文字识别将字幕转为纯文本.本文以权力的游戏第一季第一集作为示例. 本文主要使用 O ...

最新文章

  1. pureftpd + pureftp-user-manager 构建磁盘配额,速率限制,web管理ftpserver
  2. Spring Boot + Elasticsearch
  3. 部署 instance 到 OVS vlan100 - 每天5分钟玩转 OpenStack(138)
  4. 计算机视觉测试数据集 dataset
  5. c语言将0到1十等分放入数组,C语言课程设题计目汇总.doc
  6. SharePoint Search之(七)Search result- 结果源
  7. 2020 年,云游戏将爆发?各大科技公司云游戏布局大曝光!
  8. 创建和管理CVSNT服务器的步骤
  9. 信息安全之程序实现简单替换加密,并用字母频率统计进行破解
  10. 致远OA ajaxAction formulaManager 文件上传漏洞
  11. 使用Androidkiller或APKIDE编译APK文件时出现libpng error: Not a PNG file的错误
  12. 计算机硬盘应该什么格式化,电脑硬盘格式化方法总结 【图文】
  13. iOS 13 苹果登录实践 Sign In with Apple
  14. .Net Self Hosting 的几种方式
  15. 计算机怎样将多行文字转换成表格,怎么把表格里的字变成两行
  16. V-Rep/CoppeliaSim:Steeringwheel_Tutorial手把手教你制作舵轮底盘
  17. 理科生浪漫java表白代码_数学公式表白-2020理科生专属浪漫表白句子大全
  18. 苹果手机数据转移到新手机_怎么把旧手机的东西导入新手机?苹果手机数据迁移的几种方法...
  19. STM32 Cube MX 之hal库软件模拟IIC 可直接移植使用
  20. linux命令和选项作用,linux tar 命令中 -f选项作用

热门文章

  1. [小小项目]背单词的程序---1.0_纯C语言_单文件版本
  2. 西部数据 mycloud 安装svn
  3. mysql建表时数据类型解释_关于数据库建表时字段数据类型
  4. 数据结构:单向链表(SingleLinkedList)删除某一节点
  5. 武术擂台机器人所需传感器_武术擂台机器人设计报告说明书.doc
  6. iOS9 NetworkExtension使用
  7. 测验3: 基本数据类型 (第3周)Python学习记录
  8. 银行招聘计算机技术人员,中国邮政储蓄银行招聘计算机专业人员试题
  9. 零基础入门学习Java,这几本经典的Java学习书籍,可以推荐你看下,绝对受益匪浅!
  10. excel 批量单元格中提取括号前的字符串和括号后的字符串