前言:時(shí)隔一年多了,不知不覺博客停更那么久了,那不忘初心還記得嗎?
最近在做音視頻相關(guān)的開發(fā),沒什么資料并且之前也沒有接觸過這方面,
咨詢了T屆的好友,拿到了下面的這張表情包,問題是當(dāng)我百度的時(shí)候才
發(fā)現(xiàn)與我想要知道的相關(guān)文檔是沒有一篇能滿足,東拼西湊的找文檔,可
還是沒辦法實(shí)現(xiàn)想要的功能,于是我陷入了沉思......最終還是輕松搞定
了這個(gè)需求,于是我打開了csdn想給后人留一片樹蔭。
最后奉上工具的學(xué)習(xí)資料(感興趣的可以看看),廢話不多說?。。。。?/strong>
FFmpeg是啥:? ffmpeg(命令行工具) 是一個(gè)快速的音視頻轉(zhuǎn)換工具。
FFmpeg能干啥:如果你用過愛剪輯的話或者其他一些音視頻處理軟件的話,你可以理解他們能做的你用玩意都能做。
為啥要用FFmpeg:開源免費(fèi)啊,你用軟件要收費(fèi)呢,但是這不是關(guān)鍵,核心是你要整合進(jìn)Java,怎么用Java和執(zhí)行它,也就是你咋去寫個(gè)愛剪輯呢(當(dāng)然呢那種東西靠一個(gè)兩個(gè)人也是很難寫出來的,本文結(jié)合實(shí)際情況處理一下小問題還是綽綽有余)。
FFmpeg先去這學(xué)習(xí)一下再來看哦
1、我的需求
需要將mp3,m4a,m4r,wma,amr,aac,ac3,ape,flac,mmf,ogg類型格式的音頻轉(zhuǎn)成wav格式并指定聲道和采樣率;
需要將mp4,3gp,mov,m4v,mkv,flv,vob,wmv,rm,rmvb,dat,asf,asx,avi類型格式的視頻先提取音軌再轉(zhuǎn)成wav格式并指定聲道和采樣率;
2、設(shè)計(jì)&編碼
當(dāng)時(shí)了解到的技術(shù)選型就是ffmpeg工具了,去簡單的學(xué)習(xí)了一下這個(gè)工具的基礎(chǔ)語法以及音視頻開發(fā)的基本規(guī)范和格式。
于是我寫了工具類FFmpegUtils
package com.iflytex.bohai.utils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* 利用ffmpeg進(jìn)行音頻視頻操作,需先下載安裝ffmpeg
*/
@Slf4j
@Data
@Configuration
public class FfmpegUtil {
@Value("${ffmpeg.temppath}")
private String tempPath;//保存音頻、視頻的臨時(shí)文件夾
@Value("${ffmpeg.ffmpeg-util-path}")
private String ffmpegUtilPath;//工具包路徑
/**
* 將音頻統(tǒng)一轉(zhuǎn)成wav格式
* @param inputPath 輸入文件
* @param sampleRate 采樣率
*/
public String transcodeToWav(String inputPath, String sampleRate) throws IOException, InterruptedException {
createTempDir();
List<String> command = new ArrayList<>();
command.add(ffmpegUtilPath);
command.add("-y");
command.add("-i");
command.add(inputPath);
command.add("-async");
command.add("1");
command.add("-ar");
command.add(sampleRate);
command.add("-ac");
command.add("1");
command.add("-f");
command.add("wav");
String outputPath=FilenameUtils.getFullPath(inputPath)+FilenameUtils.getBaseName(inputPath) +".wav";
command.add(outputPath);
commandStart(command);
return outputPath;
}
/**
* 從視頻中提取音頻為wav
* @param inputPath 視頻文件的路徑
* @param sampleRate 采樣率
*/
public String getAudioFromVideo(String inputPath,String sampleRate) throws IOException, InterruptedException {
createTempDir();
List<String> command = new ArrayList<>();
command.add(ffmpegUtilPath);
command.add("-i");
command.add(inputPath);
command.add("-ac");
command.add("1");
command.add("-ar");
command.add(sampleRate);
command.add("-f");
command.add("wav");
command.add("-vn");
String outputPath=FilenameUtils.getFullPath(inputPath)+FilenameUtils.getBaseName(inputPath)+".wav";
command.add(outputPath);
commandStart(command);
return outputPath;
}
/**
* 調(diào)用命令行執(zhí)行
*
* @param command 命令行參數(shù)
*/
public static void commandStart(List<String> command) throws IOException, InterruptedException {
ProcessBuilder builder = new ProcessBuilder();
//正常信息和錯(cuò)誤信息合并輸出
builder.redirectErrorStream(true);
builder.command(command);
log.debug(command.toString());
//開始執(zhí)行命令
Process process;
process = builder.start();
//如果你想獲取到執(zhí)行完后的信息,那么下面的代碼也是需要的
String line = "";
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((line = br.readLine()) != null) {
log.debug(line);
}
process.waitFor();
log.debug("命令執(zhí)行放回code為:"+process.exitValue());
if(process.exitValue()==1){
throw new RuntimeException();
}
}
/*
創(chuàng)建臨時(shí)目錄(用于存儲(chǔ)轉(zhuǎn)換后的音視頻和原音視頻)
每次使用轉(zhuǎn)換功能是都調(diào)用方式目錄被刪除導(dǎo)致的異常
*/
public void createTempDir(){
//如果沒有文件夾,則創(chuàng)建
File tempMediaFile = new File(tempPath);
if (!tempMediaFile.exists() && !tempMediaFile.isDirectory()) {
boolean isSuccess = tempMediaFile.mkdirs();
log.info("初始化音視頻臨時(shí)目錄是否成功:{}",isSuccess);
}
}
// /**
// * 獲取ffmpeg的工具路徑,根據(jù)操作系統(tǒng)去自動(dòng)選擇
// * @return ffmpeg的工具路徑
// */
// private String getFFmpegPath(){ String path = this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
//
// String ffmpegPath ="./ffmpeg";
// String os = System.getProperty("os.name");
// if(os.toLowerCase().startsWith("win")){
// ffmpegPath ="./ffmpeg.exe";
// }
// return ffmpegPath;
// }
}
process.waitFor();
這句要注意,本地不加不報(bào)錯(cuò)因?yàn)楸镜靥幚硭俣瓤?,服?wù)器有內(nèi)耗的話不加這個(gè)偶爾就報(bào)錯(cuò)的
如果需要其他操作直接仿照我的寫法來就好了,具體的命令可以看我上面給點(diǎn)那個(gè)鏈接里面的內(nèi)容,都是從0告訴你。文章來源:http://www.zghlxwxcb.cn/news/detail-433619.html
3、總結(jié)
- 先去簡單了解一下ffmpeg的基礎(chǔ)用法
- 仿照工具類完成一些想要的操作
- 資料我給你們打包好,免費(fèi)奉上(工具包的os\win版本,ffmpeg專業(yè)化文檔)
-
資料都打包在這里了免費(fèi)拿取點(diǎn)個(gè)贊唄
文章來源地址http://www.zghlxwxcb.cn/news/detail-433619.html
到了這里,關(guān)于Java如何整合FFmpeg、FFprobe等音視頻處理工具,零基礎(chǔ)照樣玩的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!