這個是從抖音上學來的,一開始刷抖音,遇到很多字符串跳舞的視頻,所以來實踐一下html
主要用到了FFmpeg這個工具,利用命令對視頻文件進行操做。首先根據本身調的參數進行圖片的截取(本文的是1秒10幀的參數),圖片轉換,而後分離音頻,最後字符圖片和音頻合成目標視頻。java
FFmpeg的代碼庫:git
https://github.com/FFmpeg/FFmpeggithub
FFmpeg下載地址:segmentfault
https://ffmpeg.org/download.htmlide
本位使用的版本:工具
沒作細緻的調整,視頻的轉換能夠調調參數 ui
@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:spa
// 截圖 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; } }
https://github.com/Ruffianjiang/java4fun/tree/master/img2text