這個是從抖音上學來的,一開始刷抖音,遇到很多字符串跳舞的視頻,所以來實踐一下html
主要用到了FFmpeg這個工具,利用命令對視頻文件進行操做。首先根據本身調的參數進行圖片的截取(本文的是1秒10幀的參數),圖片轉換,而後分離音頻,最後字符圖片和音頻合成目標視頻。java
FFmpeg的代碼庫:git
github.com/FFmpeg/FFmp…github
FFmpeg下載地址:ide
本位使用的版本:測試
blog-lossingdawn.oss-cn-shanghai.aliyuncs.com/img2text/ff…ui
沒作細緻的調整,視頻的轉換能夠調調參數
spa
![Watch the video](https://blog-lossingdawn.oss-cn-shanghai.aliyuncs.com/img2text/123.mp4).net
![Watch the video](https://blog-lossingdawn.oss-cn-shanghai.aliyuncs.com/img2text/1234.mp4)
@Test
public static void videoTest() {
String srcVideoPath = "F:/123/123.mp4";
String tarImagePath = "F:/123/mp/";
String tarAudioPath = "F:/123/mp/audio.aac";
String tarVideoPath = "F:/123/1234.mp4";
VideoUtil.readVideo(srcVideoPath,tarImagePath,tarAudioPath,tarVideoPath);
}複製代碼
主要用到的幾個命令,其餘按幀截圖命令參考文末連接4:
// 截圖
ffmpeg -ss 10 -i input.flv -y -f image2 -vframes 100 -s 352x240 b-%03d.jpg
// 分離音頻
ffmpeg -i 3.mp4 -vn -y -acodec copy 3.aac
// 合成視頻
ffmpeg -threads2 -y -r 10 -i /tmpdir/image%04d.jpg -i audio.mp3 -absf aac_adtstoasc output.mp4複製代碼
JDK 1.8
// ffmpeg -ss 10 -i input.flv -y -f image2 -vframes 100 -s 352x240 b-%03d.jpg
/**
* ffmpeg 截圖,並指定圖片的大小
*
* @param srcVideoPath
* @param tarImagePath
* 截取後圖片路徑
* @param width
* 截圖的寬
* @param hight
* 截圖的高
* @param offsetValue
* 表示相對於文件開始處的時間偏移值 能夠是分秒
* @param vframes
* 表示截圖的楨數
*
* @return
*/
public static boolean processFfmpegImage(String srcVideoPath, String tarImagePath, int width, int hight,
float offsetValue, float vframes) {
if (!checkfile(srcVideoPath)) {
System.out.println("【" + srcVideoPath + "】 不存在 !");
// logger.error("【" + srcVideoPath + "】 不存在 !");
return false;
}
List<String> commend = new java.util.ArrayList<String>();
commend.add(ffmpegPath);
commend.add("-i");
commend.add(srcVideoPath);
commend.add("-y");
commend.add("-f");
commend.add("image2");
commend.add("-ss");
commend.add(offsetValue + ""); // 在視頻的某個插入時間截圖,例子爲5秒後
// commend.add("-vframes");
commend.add("-t");// 添加參數"-t",該參數指定持續時間
commend.add(vframes + ""); // 截圖的楨數,添加持續時間爲1毫秒
commend.add("-s");
commend.add(width + "x" + hight); // 截圖的的大小
commend.add(tarImagePath);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
builder.redirectErrorStream(true);
// builder.redirectOutput(new File("F:/123/log/log.log"));
Process process = builder.start();
doWaitFor(process);
process.destroy();
if (!checkfile(tarImagePath)) {
System.out.println(tarImagePath + " is not exit! processFfmpegImage 轉換不成功 !");
// logger.info(tarImagePath + " is not exit! processFfmpegImage
// 轉換不成功 !");
return false;
}
return true;
} catch (Exception e) {
e.printStackTrace();
System.out.println("【" + srcVideoPath + "】 processFfmpegImage 轉換不成功 !");
// logger.error("【" + srcVideoPath + "】 processFfmpegImage 轉換不成功
// !");
return false;
}
}
public static boolean processFfmpegAudio(String srcVideoPath, String tarAudioPath) {
if (!checkfile(srcVideoPath)) {
System.out.println("【" + srcVideoPath + "】 不存在 !");
// logger.error("【" + srcVideoPath + "】 不存在 !");
return false;
}
// https://blog.csdn.net/xiaocao9903/article/details/53420519
// ffmpeg -i 3.mp4 -vn -y -acodec copy 3.aac
// ffmpeg -i 3.mp4 -vn -y -acodec copy 3.m4a
List<String> commend = new java.util.ArrayList<String>();
commend.add(ffmpegPath);
commend.add("-i");
commend.add(srcVideoPath);
commend.add("-vn");
commend.add("-y");
commend.add("-acodec");
commend.add("copy"); // 在視頻的某個插入時間截圖,例子爲5秒後
commend.add(tarAudioPath);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
builder.redirectErrorStream(true);
Process process = builder.start();
doWaitFor(process);
process.destroy();
if (!checkfile(tarAudioPath)) {
System.out.println(tarAudioPath + " is not exit! processFfmpegAudio 轉換不成功 !");
return false;
}
return true;
} catch (Exception e) {
e.printStackTrace();
System.out.println("【" + srcVideoPath + "】 processFfmpegAudio 轉換不成功 !");
return false;
}
}
/**
* ffmpeg 合成視頻
*
* @param srcVideoPath
* @param tarImagePath
* 截取後圖片路徑
* @param width
* 截圖的寬
* @param hight
* 截圖的高
* @param offsetValue
* 表示相對於文件開始處的時間偏移值 能夠是分秒
* @param vframes
* 表示截圖的楨數
*
* @return
*/
public static boolean processFfmpegVideo(String imagePath, String audioPath, String tarVideoPath, int step) {
// https://blog.csdn.net/wangshuainan/article/details/77914508?fps=1&locationNum=4
// 帶音頻
// ffmpeg -threads2 -y -r 10 -i /tmpdir/image%04d.jpg -i audio.mp3 -absf
// aac_adtstoasc output.mp4
List<String> commend = new java.util.ArrayList<String>();
commend.add(ffmpegPath);
commend.add("-threads");
commend.add("2");
commend.add("-y");
commend.add("-r");
commend.add(step + "");
commend.add("-i");
commend.add(imagePath); // 圖片
commend.add("-i");
commend.add(audioPath);
commend.add("-absf");//
commend.add("aac_adtstoasc"); //
commend.add(tarVideoPath);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
builder.redirectErrorStream(true);
builder.redirectOutput(new File("F:/123/log/log.log"));
Process process = builder.start();
doWaitFor(process);
process.destroy();
if (!checkfile(tarVideoPath)) {
System.out.println(tarVideoPath + " is not exit! processFfmpegVideo 轉換不成功 !");
return false;
}
return true;
} catch (Exception e) {
e.printStackTrace();
System.out.println("【" + tarVideoPath + "】 processFfmpegVideo 轉換不成功 !");
return false;
}
}複製代碼