안 드 로 이 드 는 FFmpeg 를 사용 하여 오디 오 혼합 과 조합 절 체 를 실현 합 니 다.

FFmpeg 을 접 한 지 오래 되 었 습 니 다.이 는 음성 영상 개발 의 소스 라 이브 러 리 로 거의 모든 플레이어,생방송 플랫폼 은 FFmpeg 를 바탕 으로 2 차 개발 을 했 습 니 다.이 글 은 다음 과 같이 FFmpeg 를 이용 하여 오디 오 처 리 를 한다.오디 오 혼합,오디 오 절단,오디 오 조합 과 오디 오 변환 이다.
android studio 를 사용 하여 개발 하고 build.gradle 파일 을 설정 합 니 다.

defaultConfig {
 ......
 externalNativeBuild {
  cmake {
  cppFlags ""
  }
 }
 ndk {
  abiFilters "armeabi-v7a"
 }
 }
cmake 파일 경 로 를 지정 합 니 다:

externalNativeBuild {
 cmake {
  path "CMakeLists.txt"
 }
 }
 sourceSets {
 main {
  jniLibs.srcDirs = ['libs']
  jni.srcDirs = []
 }
 }
FFmpeg 홈 페이지 에서 원본 코드 를 다운로드 하여 ffmpeg.so 동적 라 이브 러 리 로 컴 파일 하고 관련 원본 파일 과 헤더 파일 을 가 져 옵 니 다.

그리고 cMakeLists 파일 을 설정 합 니 다:

add_library( # Sets the name of the library.
  audio-handle
 
  # Sets the library as a shared library.
  SHARED
 
  # Provides a relative path to your source file(s).
  src/main/cpp/ffmpeg_cmd.c
  src/main/cpp/cmdutils.c
  src/main/cpp/ffmpeg.c
  src/main/cpp/ffmpeg_filter.c
  src/main/cpp/ffmpeg_opt.c)
add_library( ffmpeg
  SHARED
  IMPORTED )
set_target_properties( ffmpeg
   PROPERTIES IMPORTED_LOCATION
   ../../../../libs/armeabi-v7a/libffmpeg.so )
include_directories(src/main/cpp/include)
find_library( log-lib
  log )
target_link_libraries( audio-handle
   ffmpeg
   ${log-lib} )
  FFmpeg         :
 /**
 *   ffmpeg    
 * @param handleType handleType
 */
 private void doHandleAudio(int handleType){
 String[] commandLine = null;
 switch (handleType){
  case 0://  
  String transformFile = PATH + File.separator + "transform.aac";
  commandLine = FFmpegUtil.transformAudio(srcFile, transformFile);
  break;
  case 1://  
  String cutFile = PATH + File.separator + "cut.mp3";
  commandLine = FFmpegUtil.cutAudio(srcFile, 10, 15, cutFile);
  break;
  case 2://  
  String concatFile = PATH + File.separator + "concat.mp3";
  commandLine = FFmpegUtil.concatAudio(srcFile, appendFile, concatFile);
  break;
  case 3://  
  String mixFile = PATH + File.separator + "mix.aac";
  commandLine = FFmpegUtil.mixAudio(srcFile, appendFile, mixFile);
  break;
  default:
  break;
 }
 executeFFmpegCmd(commandLine);
 }
그 중에서 오디 오 믹스,병합,잘라 내기,코드 를 바 꾸 는 FFmpeg 명령 행 의 조합 은 다음 과 같 습 니 다.

/**
 *   ffmpeg         
 * @param srcFile    
 * @param targetFile     (        )
 * @return       
 */
 public static String[] transformAudio(String srcFile, String targetFile){
 String transformAudioCmd = "ffmpeg -i %s %s";
 transformAudioCmd = String.format(transformAudioCmd, srcFile, targetFile);
 return transformAudioCmd.split(" ");//           
 }
 
 /**
 *   ffmpeg         
 * @param srcFile    
 * @param startTime        (    )
 * @param duration     (    )
 * @param targetFile     
 * @return       
 */
 @SuppressLint("DefaultLocale")
 public static String[] cutAudio(String srcFile, int startTime, int duration, String targetFile){
 String cutAudioCmd = "ffmpeg -i %s -ss %d -t %d %s";
 cutAudioCmd = String.format(cutAudioCmd, srcFile, startTime, duration, targetFile);
 return cutAudioCmd.split(" ");//           
 }
 
 /**
 *   ffmpeg         
 * @param srcFile    
 * @param appendFile       
 * @param targetFile     
 * @return       
 */
 public static String[] concatAudio(String srcFile, String appendFile, String targetFile){
 String concatAudioCmd = "ffmpeg -i concat:%s|%s -acodec copy %s";
 concatAudioCmd = String.format(concatAudioCmd, srcFile, appendFile, targetFile);
 return concatAudioCmd.split(" ");//           
 }
 
 /**
 *   ffmpeg         
 * @param srcFile    
 * @param mixFile      
 * @param targetFile     
 * @return       
 */
 public static String[] mixAudio(String srcFile, String mixFile, String targetFile){
 String mixAudioCmd = "ffmpeg -i %s -i %s -filter_complex amix=inputs=2:duration=first -strict -2 %s";
 mixAudioCmd = String.format(mixAudioCmd, srcFile, mixFile, targetFile);
 return mixAudioCmd.split(" ");//           
 }
FFmpeg 처리 혼 음 공식 은 다음 과 같 습 니 다.그 중에서 sample 1 은 원본 파일 샘플링 율 이 고 sample 2 는 혼합 파일 샘플링 율 입 니 다.
혼 음 공식:value=sample 1+sample 2-(sample 1*sample 2/(pow(2,16-1)-1)
하위 스 레 드 를 열 고 native 방법 으로 오디 오 처 리 를 진행 합 니 다:

public static void execute(final String[] commands, final OnHandleListener onHandleListener){
 new Thread(new Runnable() {
  @Override
  public void run() {
  if(onHandleListener != null){
   onHandleListener.onBegin();
  }
  //  ffmpeg    
  int result = handle(commands);
  if(onHandleListener != null){
   onHandleListener.onEnd(result);
  }
  }
 }).start();
 }
 private native static int handle(String[] commands);
중요 한 native 방법 은 자바 가 들 어 온 문자열 배열 을 2 급 포인터 배열 로 바 꾼 다음 FFmpeg 소스 코드 의 run 방법 을 호출 하 는 것 입 니 다.

JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_FFmpegCmd_handle
(JNIEnv *env, jclass obj, jobjectArray commands){
 int argc = (*env)->GetArrayLength(env, commands);
 char **argv = (char**)malloc(argc * sizeof(char*));
 int i;
 int result;
 for (i = 0; i < argc; i++) {
 jstring jstr = (jstring) (*env)->GetObjectArrayElement(env, commands, i);
 char* temp = (char*) (*env)->GetStringUTFChars(env, jstr, 0);
 argv[i] = malloc(1024);
 strcpy(argv[i], temp);
 (*env)->ReleaseStringUTFChars(env, jstr, temp);
 }
 //  ffmpeg  
 result = run(argc, argv);
 //    
 for (i = 0; i < argc; i++) {
 free(argv[i]);
 }
 free(argv);
 return result;
}
FFmpeg 의 run 방법 에 대한 원본 코드 는 다음 과 같 습 니 다.중간 부분 은 생략 되 었 습 니 다.

int run(int argc, char **argv)
{
 /****************  ********************/
 //      
 avcodec_register_all();
#if CONFIG_AVDEVICE
 avdevice_register_all();
#endif
 avfilter_register_all();
 av_register_all();
 avformat_network_init();
 show_banner(argc, argv, options);
 term_init();
 /****************  ********************/
 //               
 int ret = ffmpeg_parse_options(argc, argv);
 if (ret < 0)
 exit_program(1);
 /****************  ********************/
 //    
 if (transcode() < 0)
 exit_program(1);
 /****************  ********************/
 //      :    、    
 exit_program(received_nb_signals ? 255 : main_return_code);
 ffmpeg_cleanup(0);
}
그 중에서 가장 중요 한 것 은 파일 변환 부분 입 니 다.소스 코드 는 다음 과 같 습 니 다.

static int transcode(void)
{
 int ret, i;
 AVFormatContext *os;
 OutputStream *ost;
 InputStream *ist;
 int64_t timer_start;
 int64_t total_packets_written = 0;
 //       
 ret = transcode_init();
 if (ret < 0)
 goto fail;
 
 if (stdin_interaction) {
 av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help
"); } timer_start = av_gettime_relative(); #if HAVE_PTHREADS if ((ret = init_input_threads()) < 0) goto fail; #endif //transcode while (!received_sigterm) { int64_t cur_time= av_gettime_relative(); // "q" , if (stdin_interaction) if (check_keyboard_interaction(cur_time) < 0) break; // if (!need_output()) { av_log(NULL, AV_LOG_VERBOSE, "No more output streams to write to, finishing.
"); break; } ret = transcode_step(); if (ret < 0 && ret != AVERROR_EOF) { char errbuf[128]; av_strerror(ret, errbuf, sizeof(errbuf)); av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s
", errbuf); break; } // print_report(0, timer_start, cur_time); } #if HAVE_PTHREADS free_input_threads(); #endif // stream, buffer for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; if (!input_files[ist->file_index]->eof_reached && ist->decoding_needed) { process_input_packet(ist, NULL, 0); } } flush_encoders(); term_exit(); // , for (i = 0; i < nb_output_files; i++) { os = output_files[i]->ctx; if ((ret = av_write_trailer(os)) < 0) { av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s", os->filename, av_err2str(ret)); if (exit_on_error) exit_program(1); } } // for (i = 0; i < nb_output_streams; i++) { ost = output_streams[i]; if (ost->encoding_needed) { av_freep(&ost->enc_ctx->stats_in); } total_packets_written += ost->packets_written; } if (!total_packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT)) { av_log(NULL, AV_LOG_FATAL, "Empty output
"); exit_program(1); } // for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; if (ist->decoding_needed) { avcodec_close(ist->dec_ctx); if (ist->hwaccel_uninit) ist->hwaccel_uninit(ist->dec_ctx); } } // return ret; }
자,FFmpeg 를 사용 하여 오디 오 편집,믹스,맞 춤 법 과 코드 소 개 를 마 쳤 습 니 다.만약 여러분 에 게 무슨 문제 나 건의 가 있다 면,교 류 를 환영 합 니 다.
소스 코드:링크 주소.도움 이 된다 면 포크 와 스타 를 귀 찮 게 해 주세요.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기