使用FFmpeg進行視訊抽取音訊,之後進行語音識別轉為文字
阿新 • • 發佈:2018-12-14
package com.my.ai.service; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; @Service public class CutService { public static Logger logger = LoggerFactory.getLogger(CutService.class); public List<String> cutFile(String media_path, String ffmpeg_path) { List<String> audios = new ArrayList<>(); int mediaTime = getMediaTime(media_path, ffmpeg_path); int num = mediaTime / 59; int lastNum = mediaTime % 59; System.out.println(mediaTime +"|" + num + "|"+ lastNum); int length = 59; File file = new File(media_path); String filename = file.getName(); for (int i = 0; i < num; i++) { String outputPath = file.getParent() + File.separator + i + "-"+filename; processCmd(media_path, ffmpeg_path, String.valueOf(length * i) , String.valueOf(length), outputPath); audios.add(outputPath); } if(lastNum > 0) { String outputPath = file.getParent() + File.separator + num + "-"+filename; processCmd(media_path, ffmpeg_path, String.valueOf(length * num) , String.valueOf(lastNum), outputPath); audios.add(outputPath); } return audios; } /** * 獲取視訊總時間 * * @param viedo_path 視訊路徑 * @param ffmpeg_path ffmpeg路徑 * @return */ public int getMediaTime(String video_path, String ffmpeg_path) { List<String> commands = new java.util.ArrayList<String>(); commands.add(ffmpeg_path); commands.add("-i"); commands.add(video_path); try { ProcessBuilder builder = new ProcessBuilder(); builder.command(commands); final Process p = builder.start(); // 從輸入流中讀取視訊資訊 BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream())); StringBuffer sb = new StringBuffer(); String line = ""; while ((line = br.readLine()) != null) { sb.append(line); } System.out.println(sb.toString()); br.close(); // 從視訊資訊中解析時長 String regexDuration = "Duration: (.*?), bitrate: (\\d*) kb\\/s"; Pattern pattern = Pattern.compile(regexDuration); Matcher m = pattern.matcher(sb.toString()); if (m.find()) { int time = getTimelen(m.group(1)); System.out .println(video_path + ",視訊時長:" + time + ",位元率:" + m.group(2) + "kb/s"); return time; } } catch (Exception e) { e.printStackTrace(); } return 0; } // 格式:"00:00:10.68" public int getTimelen(String timelen) { int min = 0; String strs[] = timelen.split(":"); if (strs[0].compareTo("0") > 0) { min += Integer.valueOf(strs[0]) * 60 * 60;// 秒 } if (strs[1].compareTo("0") > 0) { min += Integer.valueOf(strs[1]) * 60; } if (strs[2].compareTo("0") > 0) { min += Math.round(Float.valueOf(strs[2])); } return min; } //D:\ffmpeg4.2\bin\ffmpeg.exe -i 123.pcm -ss 0 -t 59 1-123.wav public String processCmd(String inputPath,String ffmpegPath, String startTime,String length,String outputPath) { List<String> commend = new java.util.ArrayList<String>(); commend.add(ffmpegPath); commend.add("-i"); commend.add(inputPath); commend.add("-ss"); commend.add(startTime); commend.add("-t"); commend.add(length); commend.add(outputPath); try { ProcessBuilder builder = new ProcessBuilder(); builder.command(commend); builder.redirectErrorStream(true); Process p = builder.start(); // 1. start BufferedReader buf = null; // 儲存ffmpeg的輸出結果流 String line = null; // read the standard output buf = new BufferedReader(new InputStreamReader(p.getInputStream())); StringBuffer sb = new StringBuffer(); while ((line = buf.readLine()) != null) { System.out.println(line); sb.append(line); continue; } p.waitFor();// 這裡執行緒阻塞,將等待外部轉換程序執行成功執行結束後,才往下執行 // 1. end return sb.toString(); } catch (Exception e) { System.out.println(e); return null; } } //ffmpeg -y -i 16k.wav -acodec pcm_s16le -f s16le -ac 1 -ar 16000 16k.pcm public static String processWavToPcm(String inputPath,String ffmpegPath,String outputPath) { List<String> commend = new java.util.ArrayList<String>(); commend.add(ffmpegPath); commend.add("-i"); commend.add(inputPath); commend.add("-acodec"); commend.add("pcm_s16le"); commend.add("-f"); commend.add("s16le"); commend.add("-ac"); commend.add("1"); commend.add("-ar"); commend.add("16000"); commend.add(outputPath); try { ProcessBuilder builder = new ProcessBuilder(); builder.command(commend); builder.redirectErrorStream(true); Process p = builder.start(); // 1. start BufferedReader buf = null; // 儲存ffmpeg的輸出結果流 String line = null; // read the standard output buf = new BufferedReader(new InputStreamReader(p.getInputStream())); StringBuffer sb = new StringBuffer(); while ((line = buf.readLine()) != null) { System.out.println(line); sb.append(line); continue; } p.waitFor();// 這裡執行緒阻塞,將等待外部轉換程序執行成功執行結束後,才往下執行 // 1. end return outputPath; //sb.toString(); } catch (Exception e) { System.out.println(e); return null; } } public static void main(String[] args) { List<String> audios = new CutService().cutFile( "E:\\QLDownload\\氧化還原反應中電子轉移的方向和數目的表示方法\\氧化還原反應中電子轉移的方向和數目的表示方法.wav", "D:\\ffmpeg4.2\\bin\\ffmpeg.exe"); System.out.println(audios.size()); for (String wavPath : audios) { String out = wavPath.substring(0,wavPath.lastIndexOf(".")) + ".pcm"; processWavToPcm(wavPath, "D:\\ffmpeg4.2\\bin\\ffmpeg.exe", out); } } }