android将pcm和mp3合并到aac中

qltillow  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(670)

我有一个程序,记录用户输入的声音 PCM (我需要单独做才能“播放”声音),然后我还有一个自定义的音频曲目,它在 MP3 格式,我想和 PCM 文件。
首先我把他们两个都变成 WAV 分开,然后我把2 WAV 文件,最后将结果转换为 AAC 因为我以后还需要把音频和视频合并。
我试过合并2 AAC 档案,但这对我来说不合适。
对于音频转换,我使用ffmpeg android。
问题是,它需要太长的时间,大约1-2分钟来做整个转换,正因为如此,我需要一个新的方式来做这一切。我查过其他图书馆,但这是我唯一能去工作的图书馆。
有人能推荐一些能加快整个过程的东西吗?
下面是我合并所有文件的代码:

  1. public class AudioProcessor {
  2. private Context context;
  3. private FFmpeg ffmpeg;
  4. private AudioProcessorListener listener;
  5. private File micPcmFile;
  6. private File backgroundMp3File;
  7. private File pcmtowavTempFile;
  8. private File mp3towavTempFile;
  9. private File combinedwavTempFile;
  10. private File outputFile;
  11. private File volumeChangedTempFile;
  12. private FFtask currentTask;
  13. private int videoRecordingLength = 0;
  14. TextView extensionDownload, percentProgress;
  15. private static final String TAG = "FFMPEG AV Processor";
  16. public AudioProcessor(Context context, Activity activity) {
  17. ffmpeg = null;
  18. ffmpeg = FFmpeg.getInstance(context);
  19. percentProgress = activity.findViewById(R.id.percentProgress);
  20. percentProgress.setSingleLine(false);
  21. this.context = context;
  22. prepare();
  23. }
  24. /**
  25. * Program main method. Starts running program
  26. * @throws Exception
  27. */
  28. public void process() throws Exception {
  29. if (!ffmpeg.isSupported()) {
  30. Log.e(TAG, "FFMPEG not supported! Cannot convert audio!");
  31. throw new RuntimeException("FFMPeg has to be supported");
  32. }
  33. if (!checkIfAllFilesPresent()) {
  34. Log.e(TAG, "All files are not set yet. Please set file first");
  35. throw new RuntimeException("Files are not set!");
  36. }
  37. Log.e(TAG, "Start processing audio!");
  38. listener.onStart();
  39. Handler handler = new Handler();
  40. handler.postDelayed(new Runnable() {
  41. @Override
  42. public void run() {
  43. convertPCMToWav();
  44. }
  45. }, 200);
  46. }
  47. /**
  48. * Prepares program
  49. */
  50. private void prepare() {
  51. Log.d(TAG, "Preparing everything...");
  52. prepareTempFiles();
  53. }
  54. /**
  55. * Converts PCM to wav file. Automatically create new file.
  56. */
  57. private void convertPCMToWav() {
  58. Log.d(TAG, "Convert PCM TO Wav");
  59. //ffmpeg -f s16le -ar 44.1k -ac 2 -i file.pcm file.wav
  60. String[] cmd = { "-f" , "s16le", "-ar", "44.1k", "-i", micPcmFile.toString(), "-y", pcmtowavTempFile.toString()};
  61. currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
  62. @Override
  63. public void onStart() {
  64. super.onStart();
  65. percentProgress.setVisibility(View.VISIBLE);
  66. percentProgress.setText("Converting your recording\n"+"1/5");
  67. }
  68. @Override
  69. public void onSuccess(String message) {
  70. super.onSuccess(message);
  71. convertMP3ToWav();
  72. }
  73. @Override
  74. public void onFailure(String message) {
  75. super.onFailure(message);
  76. onError(message);
  77. convertPCMToWav();
  78. }
  79. });
  80. }
  81. /**
  82. * Converts mp3 file to wav file.
  83. * Automatically creates Wav file
  84. */
  85. private void convertMP3ToWav() {
  86. Log.e(TAG, "Convert MP3 TO Wav");
  87. //ffmpeg -ss 0 -t 30 -i file.mp3 file.wav
  88. //String[] cmd = { "-ss", "0", "-t", Integer.toString(videoRecordingLength), "-i" , backgroundMp3File.toString(), "-y", mp3towavTempFile.toString() };
  89. String[] cmd = { "-i" , backgroundMp3File.toString(), "-y", mp3towavTempFile.toString() };
  90. currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
  91. @Override
  92. public void onStart() {
  93. super.onStart();
  94. percentProgress.setText("Converting background audio\n"+"2/5");
  95. Log.d(TAG, "Convert MP3 TO Wav");
  96. }
  97. @Override
  98. public void onSuccess(String message) {
  99. super.onSuccess(message);
  100. changeMicAudio();
  101. }
  102. @Override
  103. public void onFailure(String message) {
  104. super.onFailure(message);
  105. Log.e(TAG, "Failed to convert MP3 TO Wav");
  106. onError(message);
  107. throw new RuntimeException("Failed to convert MP3 TO Wav");
  108. }
  109. });
  110. }
  111. /**
  112. * Combines 2 wav files into one wav file. Overlays audio
  113. */
  114. private void combineWavs() {
  115. Log.e(TAG, "Combine wavs");
  116. //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
  117. String[] cmd = { "-i" , pcmtowavTempFile.toString(), "-i", volumeChangedTempFile.toString(), "-filter_complex", "amix=inputs=2:duration=first:dropout_transition=3", "-y",combinedwavTempFile.toString()};
  118. currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
  119. @Override
  120. public void onStart() {
  121. super.onStart();
  122. percentProgress.setText("Combining the two audio files\n"+"4/5");
  123. }
  124. @Override
  125. public void onSuccess(String message) {
  126. super.onSuccess(message);
  127. encodeWavToAAC();
  128. }
  129. @Override
  130. public void onFailure(String message) {
  131. super.onFailure(message);
  132. onError(message);
  133. }
  134. });
  135. }
  136. private void changeMicAudio(){
  137. Log.e(TAG, "Change audio volume");
  138. //ffmpeg -i input.wav -filter:a "volume=1.5" output.wav
  139. String[] cmdy = { "-i", mp3towavTempFile.toString(), "-af", "volume=0.9", "-y",volumeChangedTempFile.toString()};
  140. currentTask = ffmpeg.execute(cmdy, new ExecuteBinaryResponseHandler() {
  141. @Override
  142. public void onStart() {
  143. super.onStart();
  144. percentProgress.setText("Normalizing volume\n"+"3/5");
  145. }
  146. @Override
  147. public void onSuccess(String message) {
  148. combineWavs();
  149. super.onSuccess(message);
  150. }
  151. @Override
  152. public void onFailure(String message) {
  153. super.onFailure(message);
  154. Log.e("AudioProcessor", message);
  155. }
  156. });
  157. }
  158. /**
  159. * Do something on error. Releases program data (deletes files)
  160. * @param message
  161. */
  162. private void onError(String message) {
  163. completed();
  164. if (listener != null) {
  165. //listener.onError(message);
  166. }
  167. }
  168. /**
  169. * Encode to AAC
  170. */
  171. private void encodeWavToAAC() {
  172. Log.d(TAG, "Encode Wav file to AAC");
  173. //ffmpeg -i file.wav -c:a aac -b:a 128k -f adts output.m4a
  174. String[] cmd = { "-i" , combinedwavTempFile.toString(), "-c:a", "aac", "-b:a", "128k", "-f", "adts", "-y",outputFile.toString()};
  175. currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
  176. @Override
  177. public void onStart() {
  178. super.onStart();
  179. percentProgress.setText("Normalizing volume\n"+"3/5");
  180. }
  181. @Override
  182. public void onSuccess(String message) {
  183. super.onSuccess(message);
  184. if (listener != null) {
  185. listener.onSuccess(outputFile);
  186. }
  187. completed();
  188. }
  189. @Override
  190. public void onFailure(String message) {
  191. super.onFailure(message);
  192. onError(message);
  193. encodeWavToAAC();
  194. }
  195. });
  196. }
  197. /**
  198. * Uninitializes class
  199. */
  200. private void completed() {
  201. if (listener != null) {
  202. listener.onFinish();
  203. }
  204. Log.d(TAG, "Process completed successfully!");
  205. destroyTempFiles();
  206. }
  207. /**
  208. * Prepares temp required files by deleteing them if they exsist.
  209. * Files cannot exists before ffmpeg actions. FFMpeg automatically creates those files.
  210. */
  211. private void prepareTempFiles() {
  212. Log.d(TAG, "Preparing Temp files...");
  213. pcmtowavTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_pcm.wav");
  214. mp3towavTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_mp3.wav");
  215. combinedwavTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_combined.wav");
  216. volumeChangedTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_volumeChanged.wav");
  217. }
  218. /**
  219. * Destroys temp required files
  220. */
  221. private void destroyTempFiles() {
  222. Log.d(TAG, "Destroying Temp files...");
  223. pcmtowavTempFile.delete();
  224. mp3towavTempFile.delete();
  225. combinedwavTempFile.delete();
  226. volumeChangedTempFile.delete();
  227. Log.d(TAG, "Destroying files completed!");
  228. }
  229. /**
  230. * Checks if all files are set, so we can process them
  231. * @return - all files ready
  232. */
  233. private boolean checkIfAllFilesPresent() {
  234. if(micPcmFile == null || backgroundMp3File == null || outputFile == null) {
  235. Log.e(TAG, "All files are not set! Set all files!");
  236. throw new RuntimeException("Output file is not present!");
  237. }
  238. Log.d(TAG, "All files are present!");
  239. return true;
  240. }
  241. public void setOutputFile(File outputFile) {
  242. this.outputFile = outputFile;
  243. }
  244. public void setListener(AudioProcessorListener listener) {
  245. this.listener = listener;
  246. }
  247. public void setMicPcmFile(File micPcmFile) {
  248. this.micPcmFile = micPcmFile;
  249. }
  250. public void setBackgroundMp3File(File backgroundMp3File) {
  251. this.backgroundMp3File = backgroundMp3File;
  252. }
  253. public void setVideoRecordingLength(int seconds) {
  254. this.videoRecordingLength = seconds;
  255. }
  256. /**
  257. * Quits current processing ffmpeg task
  258. */
  259. public void killCurrentTask() {
  260. if (currentTask != null) {
  261. currentTask.killRunningProcess();
  262. }
  263. }
  264. public interface AudioProcessorListener {
  265. void onStart();
  266. void onSuccess(File output);
  267. void onError(String message);
  268. void onFinish();
  269. }
  270. }
wqsoz72f

wqsoz72f1#

可以将所有命令组合在一个命令中:

  1. 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()};

相关问题