- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个程序将用户输入的声音记录为PCM
(我需要单独执行以“播放”声音),然后我还有一个自定义音轨,位于MP3
格式,我想将其与 PCM
文件合并。
首先,我将它们分别转换为 WAV
,然后合并 2 个 WAV
文件,最后将结果转换为 AAC
> 因为稍后我还需要将音频与视频合并。
我尝试合并 2 个 AAC
文件,但这对我来说没有成功。
对于音频转换,我使用 FFmpeg-Android 。
问题是整个转换需要很长时间,大约需要 1-2 分钟,因此我需要一种新的方法来完成这一切。我研究过其他库,但这是我唯一可以使用的库。
有人可以推荐一些可以更快地完成整个过程的东西吗?
这是我合并所有文件的代码:
public class AudioProcessor {
private Context context;
private FFmpeg ffmpeg;
private AudioProcessorListener listener;
private File micPcmFile;
private File backgroundMp3File;
private File pcmtowavTempFile;
private File mp3towavTempFile;
private File combinedwavTempFile;
private File outputFile;
private File volumeChangedTempFile;
private FFtask currentTask;
private int videoRecordingLength = 0;
TextView extensionDownload, percentProgress;
private static final String TAG = "FFMPEG AV Processor";
public AudioProcessor(Context context, Activity activity) {
ffmpeg = null;
ffmpeg = FFmpeg.getInstance(context);
percentProgress = activity.findViewById(R.id.percentProgress);
percentProgress.setSingleLine(false);
this.context = context;
prepare();
}
/**
* Program main method. Starts running program
* @throws Exception
*/
public void process() throws Exception {
if (!ffmpeg.isSupported()) {
Log.e(TAG, "FFMPEG not supported! Cannot convert audio!");
throw new RuntimeException("FFMPeg has to be supported");
}
if (!checkIfAllFilesPresent()) {
Log.e(TAG, "All files are not set yet. Please set file first");
throw new RuntimeException("Files are not set!");
}
Log.e(TAG, "Start processing audio!");
listener.onStart();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
convertPCMToWav();
}
}, 200);
}
/**
* Prepares program
*/
private void prepare() {
Log.d(TAG, "Preparing everything...");
prepareTempFiles();
}
/**
* Converts PCM to wav file. Automatically create new file.
*/
private void convertPCMToWav() {
Log.d(TAG, "Convert PCM TO Wav");
//ffmpeg -f s16le -ar 44.1k -ac 2 -i file.pcm file.wav
String[] cmd = { "-f" , "s16le", "-ar", "44.1k", "-i", micPcmFile.toString(), "-y", pcmtowavTempFile.toString()};
currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
@Override
public void onStart() {
super.onStart();
percentProgress.setVisibility(View.VISIBLE);
percentProgress.setText("Converting your recording\n"+"1/5");
}
@Override
public void onSuccess(String message) {
super.onSuccess(message);
convertMP3ToWav();
}
@Override
public void onFailure(String message) {
super.onFailure(message);
onError(message);
convertPCMToWav();
}
});
}
/**
* Converts mp3 file to wav file.
* Automatically creates Wav file
*/
private void convertMP3ToWav() {
Log.e(TAG, "Convert MP3 TO Wav");
//ffmpeg -ss 0 -t 30 -i file.mp3 file.wav
//String[] cmd = { "-ss", "0", "-t", Integer.toString(videoRecordingLength), "-i" , backgroundMp3File.toString(), "-y", mp3towavTempFile.toString() };
String[] cmd = { "-i" , backgroundMp3File.toString(), "-y", mp3towavTempFile.toString() };
currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
@Override
public void onStart() {
super.onStart();
percentProgress.setText("Converting background audio\n"+"2/5");
Log.d(TAG, "Convert MP3 TO Wav");
}
@Override
public void onSuccess(String message) {
super.onSuccess(message);
changeMicAudio();
}
@Override
public void onFailure(String message) {
super.onFailure(message);
Log.e(TAG, "Failed to convert MP3 TO Wav");
onError(message);
throw new RuntimeException("Failed to convert MP3 TO Wav");
}
});
}
/**
* Combines 2 wav files into one wav file. Overlays audio
*/
private void combineWavs() {
Log.e(TAG, "Combine wavs");
//ffmpeg -i C:\Users\VR1\Desktop\_mp3.wav -i C:\Users\VR1\Desktop\_pcm.wav -filter_complex amix=inputs=2:duration=first:dropout_transition=3 C:\Users\VR1\Desktop\out.wav
String[] cmd = { "-i" , pcmtowavTempFile.toString(), "-i", volumeChangedTempFile.toString(), "-filter_complex", "amix=inputs=2:duration=first:dropout_transition=3", "-y",combinedwavTempFile.toString()};
currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
@Override
public void onStart() {
super.onStart();
percentProgress.setText("Combining the two audio files\n"+"4/5");
}
@Override
public void onSuccess(String message) {
super.onSuccess(message);
encodeWavToAAC();
}
@Override
public void onFailure(String message) {
super.onFailure(message);
onError(message);
}
});
}
private void changeMicAudio(){
Log.e(TAG, "Change audio volume");
//ffmpeg -i input.wav -filter:a "volume=1.5" output.wav
String[] cmdy = { "-i", mp3towavTempFile.toString(), "-af", "volume=0.9", "-y",volumeChangedTempFile.toString()};
currentTask = ffmpeg.execute(cmdy, new ExecuteBinaryResponseHandler() {
@Override
public void onStart() {
super.onStart();
percentProgress.setText("Normalizing volume\n"+"3/5");
}
@Override
public void onSuccess(String message) {
combineWavs();
super.onSuccess(message);
}
@Override
public void onFailure(String message) {
super.onFailure(message);
Log.e("AudioProcessor", message);
}
});
}
/**
* Do something on error. Releases program data (deletes files)
* @param message
*/
private void onError(String message) {
completed();
if (listener != null) {
//listener.onError(message);
}
}
/**
* Encode to AAC
*/
private void encodeWavToAAC() {
Log.d(TAG, "Encode Wav file to AAC");
//ffmpeg -i file.wav -c:a aac -b:a 128k -f adts output.m4a
String[] cmd = { "-i" , combinedwavTempFile.toString(), "-c:a", "aac", "-b:a", "128k", "-f", "adts", "-y",outputFile.toString()};
currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
@Override
public void onStart() {
super.onStart();
percentProgress.setText("Normalizing volume\n"+"3/5");
}
@Override
public void onSuccess(String message) {
super.onSuccess(message);
if (listener != null) {
listener.onSuccess(outputFile);
}
completed();
}
@Override
public void onFailure(String message) {
super.onFailure(message);
onError(message);
encodeWavToAAC();
}
});
}
/**
* Uninitializes class
*/
private void completed() {
if (listener != null) {
listener.onFinish();
}
Log.d(TAG, "Process completed successfully!");
destroyTempFiles();
}
/**
* Prepares temp required files by deleteing them if they exsist.
* Files cannot exists before ffmpeg actions. FFMpeg automatically creates those files.
*/
private void prepareTempFiles() {
Log.d(TAG, "Preparing Temp files...");
pcmtowavTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_pcm.wav");
mp3towavTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_mp3.wav");
combinedwavTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_combined.wav");
volumeChangedTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_volumeChanged.wav");
}
/**
* Destroys temp required files
*/
private void destroyTempFiles() {
Log.d(TAG, "Destroying Temp files...");
pcmtowavTempFile.delete();
mp3towavTempFile.delete();
combinedwavTempFile.delete();
volumeChangedTempFile.delete();
Log.d(TAG, "Destroying files completed!");
}
/**
* Checks if all files are set, so we can process them
* @return - all files ready
*/
private boolean checkIfAllFilesPresent() {
if(micPcmFile == null || backgroundMp3File == null || outputFile == null) {
Log.e(TAG, "All files are not set! Set all files!");
throw new RuntimeException("Output file is not present!");
}
Log.d(TAG, "All files are present!");
return true;
}
public void setOutputFile(File outputFile) {
this.outputFile = outputFile;
}
public void setListener(AudioProcessorListener listener) {
this.listener = listener;
}
public void setMicPcmFile(File micPcmFile) {
this.micPcmFile = micPcmFile;
}
public void setBackgroundMp3File(File backgroundMp3File) {
this.backgroundMp3File = backgroundMp3File;
}
public void setVideoRecordingLength(int seconds) {
this.videoRecordingLength = seconds;
}
/**
* Quits current processing ffmpeg task
*/
public void killCurrentTask() {
if (currentTask != null) {
currentTask.killRunningProcess();
}
}
public interface AudioProcessorListener {
void onStart();
void onSuccess(File output);
void onError(String message);
void onFinish();
}
}
最佳答案
您可以将所有命令合并为一个:
String[] cmd = { "-f" , "s16le", "-ar", "44.1k", "-i", micPcmFile.toString(), "-i" , backgroundMp3File.toString(), "-filter_complex", "[1]volume=0.9[a];[0][a]amix=inputs=2:duration=first:dropout_transition=3", "-c:a", "aac", "-b:a", "128k", "-f", "adts", "-y", "-vn", outputFile.toString()};
关于java - Android 将 PCM 和 MP3 合并为 AAC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54508686/
我有几个长度不等的 vector ,我想对其进行cbind。我将 vector 放入列表中,并尝试结合使用do.call(cbind, ...): nm <- list(1:8, 3:8, 1:5)
合并(合并)两个 JSONObjects 的最佳方式是什么? JSONObject o1 = { "one": "1", "two": "2", "three": "3" }
我在一个表中有许多空间实体,其中有一个名为 Boundaries 的 geometry 字段。我想生成一个具有简化形状/几何图形的 GeoJson 文件。 这是我的第一次尝试: var entitie
谁能说出为什么这个选择返回 3.0 而不是 3.5: SELECT coalesce(1.0*(7/2),0) as foo 这个返回 3: SELECT coalesce(7/2,0) as foo
首先抱歉,也许这个问题已经提出,但我找不到任何可以帮助我的东西,可能是因为我对 XSLT 缺乏了解。 我有以下 XML: 0 OK
有时用户会使用 Windows 资源管理器复制文件并在他们应该执行 svn 存储库级别的复制或合并时提交它们。因此,SVN 没有正确跟踪这些变化。一旦我发现这一点,损坏显然已经完成,并且可能已经对相关
我想组合/堆叠 2 个不同列的值并获得唯一值。 如果范围相邻,则可以正常工作。例如: =UNIQUE(FILTERXML(""&SUBSTITUTE(TEXTJOIN(",",TRUE,TRANSPO
使用iTextSharp,如何将多个PDF合并为一个PDF,而又不丢失每个PDF中的“表单字段”及其属性? (我希望有一个使用来自数据库的流的示例,但文件系统也可以) 我发现this code可以正常
是否有一个合并函数可以优先考虑公共(public)变量中的非缺失值? 考虑以下示例。 首先,我们生成两个 data.frames,它们具有相同的 ID,但在特定变量上有互补的缺失值: set.seed
我们正在尝试实现 ALM Rangers 在最新的 Visual Studio TFS Branching and Merging Guide 中描述的“基本双分支计划”。 .从指导: The bas
我在不同目录(3个不同名称)中有很多(3个只是一个例子)文本文件,如下所示: 目录:A,文件名:run.txt 格式:txt制表符分隔 ; file one 10 0.2 0.5 0.
我有一张包含学生等级关系的表: Student Grade StartDate EndDate 1 1 09/01/2009 NULL 2
我在学习 https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/working-with-associatio
我觉得我有世界上最简单的 SVN 用例: 我有一个文件,Test.java在 trunk SVN的。 我分行trunk至 dev-branch . 我搬家Test.java进入 com/mycompa
我有两个数据框,其中一些列名称相同,而另一些列名称不同。数据框看起来像这样: df1 ID hello world hockey soccer 1 1 NA NA
Elasticsearch 中是否缺少以扁平化形式(多个子/子aggs)返回结果的方法? 例如,当前我正在尝试获取所有产品类型及其状态(在线/离线)。 这就是我最终得到的: aggs [ { key:
如何合并如下所示的 map : Map1 = Map(1 -> Class1(1), 2 -> Class1(2)) Map2 = Map(2 -> Class2(1), 3 -> Class2(2)
我试图通过从netezza服务器导入数据来合并两个数据集。 以下是数据集,其数字为,ID为,字母为,名称为: 下表都是使用命令从netezza导入的: sqoop import --connect n
我有两个数组 $array1 = array('first', 'second', 'third', 'fourth'); $array2 = array('first', 'third', 'fou
我正在 SQL Server 中运行合并。在我的更新中,我只想在值发生更改时更新该行。有一个版本行在每次更新时都会递增。下面是一个例子: MERGE Employee as tgt USING (SE
我是一名优秀的程序员,十分优秀!