android采用FFmpeg实现音视频合成与分离

  

上一篇文章谈到音频剪切,混音,拼接与转码,也详细介绍cMake配置与涉及FFmpeg文件的导入:android端采用FFmpeg进行音频混合与拼接剪切,。现在接着探讨音视频的合成与分离。

  

<强> 1,音频提取

  

从多媒体文件中提取音频,关键命令为“vn -acodec副本”,其中“-acodec复制”是采用音频编码器拷贝音频流,“vn”是去掉视频视频流:

     /* *   *使用ffmpeg命令行进行抽取音频   * @param srcFile原文件   * @param targetFile目标文件   * @return抽取后的音频文件   */公共静态String [] extractAudio (srcFile的字符串,字符串targetFile) {//vn:视频   字符串mixAudioCmd=" ffmpeg vn % s - i % s -acodec副本”;   mixAudioCmd=字符串。格式(mixAudioCmd srcFile targetFile);   mixAudioCmd返回。分割(" ");//以空格分割为字符串数组   }      

<强> 2,视频提取

  

从多媒体文件中提取视频,关键命令为“-vcodec复制——”,其中“-vcodec复制”是采用视频编码器拷贝视频流,”——“是去掉音频音频流:

     /* *   *使用ffmpeg命令行进行抽取视频   * @param srcFile原文件   * @param targetFile目标文件   * @return抽取后的视频文件   */公共静态String [] extractVideo (srcFile的字符串,字符串targetFile) {//羝?   字符串mixAudioCmd=" ffmpeg我% s -vcodec副本——% s”;   mixAudioCmd=字符串。格式(mixAudioCmd srcFile targetFile);   mixAudioCmd返回。分割(" ");//以空格分割为字符串数组   }      

<强> 3、音视频合成

  

把音频和视频文件合成多媒体文件,关键命令是“我% s - i % s - t”,分别代表输入音频,视频和文件时长。需要注意的是,如果原视频文件包含有音频,先把单独视频流抽取出来,然后再使用独立音频和视频进行合成:

     /* *   *使用ffmpeg命令行进行音视频合成   * @param videoFile视频文件   * @param audioFile音频文件   * @param持续时间视频时长   * @param muxFile目标文件   * @return合成后的文件   */@SuppressLint (“DefaultLocale”)   videoFile公共静态String [] mediaMux(字符串,字符串audioFile, int,字符串muxFile) {//- t:时长如果忽略音视频时长,则把“- t % d”去掉   字符串mixAudioCmd=" ffmpeg我% s - i % s - t % d % s”;   mixAudioCmd=字符串。格式(mixAudioCmd、videoFile audioFile、持续时间、muxFile);   mixAudioCmd返回。分割(" ");//以空格分割为字符串数组   }   之前      

单独的视频提取出来后,进行音视频合成:

        公共空间handleMessage(消息味精){   super.handleMessage(味精);   如果(味精。什么==100){   字符串audioFile=路径+文件。分离器+“tiger.mp3”;//tiger.mp3   字符串muxFile=路径+文件。分离器+“media-mux.mp4”;      尝试{//使用媒体播放器获取视频时长   媒体播放器媒体播放器=新媒体播放器();   mediaPlayer.setDataSource (videoFile);   mediaPlayer.prepare ();//单位为ms   int videoDuration=mediaPlayer.getDuration ()/1000;   日志。我(标签,“videoDuration=" + videoDuration);   mediaPlayer.release ();//使用MediaMetadataRetriever获取音频时长   MediaMetadataRetriever mediaRetriever=new MediaMetadataRetriever ();   mediaRetriever.setDataSource (audioFile);//单位为ms   字符串时间=mediaRetriever.extractMetadata (MediaMetadataRetriever.METADATA_KEY_DURATION);   int audioDuration=(int) (Long.parseLong(持续时间)/1000);   日志。我(标签,“audioDuration=" + audioDuration);   mediaRetriever.release ();//如果视频时长比音频长,采用音频时长,否则用视频时长   int mDuration=数学。min (audioDuration videoDuration);//使用纯视频与音频进行合成   String[]命令行=FFmpegUtil。mediaMux(临时、audioFile mDuration muxFile);   executeFFmpegCmd(命令行);   isMux=false;   }捕捉(异常e) {   e.printStackTrace ();   }   }   }      

拼接好FFmpeg命令后,调用本机方法去执行:

     /* *   *调用ffmpeg处理音视频   * @param handleType handleType   */私人空间doHandleMedia (int handleType) {   String[]命令行=零;   开关(handleType) {   例0://音视频合成   尝试{//视频文件有音频,先把纯视频文件抽取出来   命令行=FFmpegUtil。extractVideo (videoFile、临时);   isMux=true;   }捕捉(异常e) {   e.printStackTrace ();   }   打破;   案例1://提取音频   字符串extractAudio=路径+文件。分离器+“extractAudio.aac”;   命令行=FFmpegUtil。extractAudio (srcFile extractAudio);   打破;   案例2://提取视频   字符串extractVideo=路径+文件。分离器+“extractVideo.mp4”;   命令行=FFmpegUtil。extractVideo (srcFile extractVideo);   打破;   默认值:   打破;   }   executeFFmpegCmd(命令行);   }   FFmpeg执行的回调:/* *   *执行ffmpeg命令行   * @param命令行命令行   */私人空间executeFFmpegCmd(最后一个String[]命令行){   如果(命令行==null) {   返回;   }   FFmpegCmd。执行(命令行,新FFmpegCmd.OnHandleListener () {   @Override   公共空间onBegin () {   日志。我(标签,“处理媒体onBegin…”);   }      @Override   公共空间竖着(int) {   日志。我(标签,“处理媒体竖着…”);   如果(isMux) {   mHandler.obtainMessage (100) .sendToTarget ();   其他}{   runOnUiThread(新Runnable () {   @Override   公共空间run () {   Toast.makeText (MediaHandleActivity。这个,”处理媒体完成……”Toast.LENGTH_SHORT),告诉();   }   });   }   }   });   }

android采用FFmpeg实现音视频合成与分离