业务场景
只需要音频,但是有一些用户将视频格式的文件修改后缀名后提交了上来,现在需要去读取文件头判断文件的真实类型,并将视频格式的文件中的音频提取出来
解决方案
首先读取文件文件头判断文件真实类型
private static HashMap<String,String> fileHeadMap = new HashMap<>();
static {
//音频
fileHeadMap.put("494433030000","mp3");
fileHeadMap.put("664c61430000","flac");//网易云无损音频文件
//视频
fileHeadMap.put("52494646d07d","avi");
fileHeadMap.put("000000206674","mp4");
}
/**
* 获取文件类型
* @param filePath 文件路径
* @return 文件类型
* @throws IOException
*/
public static String getFileHead(String filePath)throws IOException{
//获取文件头
File file = new File(filePath);
FileReader reader = new FileReader(file);
BufferedReader br = new BufferedReader(reader);
StringBuffer fileHead = new StringBuffer();
for(int i = 0 ; i<=5;i++ ){
int flag = br.read();
if(Integer.toHexString(flag).length()==1){
fileHead = fileHead.append(0);
}
fileHead = fileHead.append(Integer.toHexString(flag));
}
br.close();
//查询文件类型
return fileHeadMap.get(fileHead.toString());
}
然后将视频格式文件的文件中的音频提取出来
网上查了基本都是使用的ffmpeg
先需要下载:官网地址 csdn
下载解压
然后编写代码,基本思路就是在java代码中调用ffmpeg的可执行文件去处理视频文件
/**
* 利用ffmpeg提取视频中的音频
* @param vedioUrl 视频文件地址
* @param ffmpegUrl ffmpeg应用地址
* @throws InterruptedException
* @throws IOException
*/
public static void vedioToPcm(String vedioUrl,String ffmpegUrl) throws InterruptedException, IOException {
List<String> commend = new ArrayList<String>();
//ffmpegUrl -i vedioUrl -vn mp3Url -vn
commend.add(ffmpegUrl);
commend.add("-i");
commend.add(vedioUrl);
commend.add("-vn");
//处理MP4地址
StringBuffer mp3Adress = new StringBuffer(vedioUrl.substring(0,vedioUrl.length()-4));
mp3Adress.append("(copy).mp3");
commend.add(mp3Adress.toString());
commend.add("-vn");
commend.add("-y");
ProcessBuilder builder = new ProcessBuilder();
builder.command(commend);
builder.redirectErrorStream(true);
Process process = builder.start();
process.waitFor();// 等待进程执行结束
}
因为ffmpeg不支持直接替换掉原文件所以还需要处理下
/**
* 修改文件名
* @param fileName 需要修改的文件全名(带路径)
* @param newName 需要修改为什么文件名(全名,带路径)
* @return 是否修改成功
*/
public static boolean rename(final String fileName, final String newName) {
File file = new File(fileName);
//非空判定
if (file == null) return false;
if (!file.exists()) return false;
if ("".equals(newName)) return false;
//新老名称相同时直接返回
if (newName.equals(file.getName())) return true;
File newFile = new File(newName);
// 文件的新名称存在,然后返回false
return !newFile.exists() && file.renameTo(newFile);
}
/**
* 删除单个文件
*
* @param fileName 要删除的文件的文件名
* @return 单个文件删除成功返回true,否则返回false
*/
public static boolean deleteFile(String fileName) {
File file = new File(fileName);
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
if (file.exists() && file.isFile()) {
if (file.delete()) {
System.out.println("删除单个文件" + fileName + "成功!");
return true;
} else {
System.out.println("删除单个文件" + fileName + "失败!");
return false;
}
} else {
System.out.println("删除单个文件失败:" + fileName + "不存在!");
return false;
}
}
完成