上一篇文章谈到音频剪切,混音,拼接与转码,也详细介绍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实现音视频合成与分离