android采用FFmpeg实现音视频合成与分离
程序员文章站
2024-01-15 15:47:46
上一篇文章谈到音频剪切、混音、拼接与转码,也详细介绍cmake配置与涉及ffmpeg文件的导入: android端采用ffmpeg进行音频混合与拼接剪切 。现在接...
上一篇文章谈到音频剪切、混音、拼接与转码,也详细介绍cmake配置与涉及ffmpeg文件的导入: android端采用ffmpeg进行音频混合与拼接剪切 。现在接着探讨音视频的合成与分离。
1、音频提取
从多媒体文件中提取音频,关键命令为“-acodec copy -vn”,其中“-acodec copy”是采用音频编码器拷贝音频流,“-vn”是去掉video视频流:
/** * 使用ffmpeg命令行进行抽取音频 * @param srcfile 原文件 * @param targetfile 目标文件 * @return 抽取后的音频文件 */ public static string[] extractaudio(string srcfile, string targetfile){ //-vn:video not string mixaudiocmd = "ffmpeg -i %s -acodec copy -vn %s"; mixaudiocmd = string.format(mixaudiocmd, srcfile, targetfile); return mixaudiocmd.split(" ");//以空格分割为字符串数组 }
2、视频提取
从多媒体文件中提取视频,关键命令为“-vcodec copy -an”,其中“-vcodec copy”是采用视频编码器拷贝视频流,“-an”是去掉audio音频流:
/** * 使用ffmpeg命令行进行抽取视频 * @param srcfile 原文件 * @param targetfile 目标文件 * @return 抽取后的视频文件 */ public static string[] extractvideo(string srcfile, string targetfile){ //-an audio not string mixaudiocmd = "ffmpeg -i %s -vcodec copy -an %s"; mixaudiocmd = string.format(mixaudiocmd, srcfile, targetfile); return mixaudiocmd.split(" ");//以空格分割为字符串数组 }
3、音视频合成
把音频和视频文件合成多媒体文件,关键命令是“-i %s -i %s -t”,分别代表输入音频、视频和文件时长。需要注意的是,如果原视频文件包含有音频,先把单独视频流抽取出来,然后再使用独立音频和视频进行合成:
/** * 使用ffmpeg命令行进行音视频合成 * @param videofile 视频文件 * @param audiofile 音频文件 * @param duration 视频时长 * @param muxfile 目标文件 * @return 合成后的文件 */ @suppresslint("defaultlocale") public static string[] mediamux(string videofile, string audiofile, int duration, string muxfile){ //-t:时长 如果忽略音视频时长,则把"-t %d"去掉 string mixaudiocmd = "ffmpeg -i %s -i %s -t %d %s"; mixaudiocmd = string.format(mixaudiocmd, videofile, audiofile, duration, muxfile); return mixaudiocmd.split(" ");//以空格分割为字符串数组 }
单独的视频提取出来后,进行音视频合成:
public void handlemessage(message msg) { super.handlemessage(msg); if(msg.what == 100){ string audiofile = path + file.separator + "tiger.mp3";//tiger.mp3 string muxfile = path + file.separator + "media-mux.mp4"; try { //使用mediaplayer获取视频时长 mediaplayer mediaplayer = new mediaplayer(); mediaplayer.setdatasource(videofile); mediaplayer.prepare(); //单位为ms int videoduration = mediaplayer.getduration()/1000; log.i(tag, "videoduration=" + videoduration); mediaplayer.release(); //使用mediametadataretriever获取音频时长 mediametadataretriever mediaretriever = new mediametadataretriever(); mediaretriever.setdatasource(audiofile); //单位为ms string duration = mediaretriever.extractmetadata(mediametadataretriever.metadata_key_duration); int audioduration = (int)(long.parselong(duration)/1000); log.i(tag, "audioduration=" + audioduration); mediaretriever.release(); //如果视频时长比音频长,采用音频时长,否则用视频时长 int mduration = math.min(audioduration, videoduration); //使用纯视频与音频进行合成 string[] commandline = ffmpegutil.mediamux(temp, audiofile, mduration, muxfile); executeffmpegcmd(commandline); ismux = false; } catch (exception e) { e.printstacktrace(); } } }
拼接好ffmpeg命令后,调用native方法去执行:
/** * 调用ffmpeg处理音视频 * @param handletype handletype */ private void dohandlemedia(int handletype){ string[] commandline = null; switch (handletype){ case 0://音视频合成 try { //视频文件有音频,先把纯视频文件抽取出来 commandline = ffmpegutil.extractvideo(videofile, temp); ismux = true; } catch (exception e) { e.printstacktrace(); } break; case 1://提取音频 string extractaudio = path + file.separator + "extractaudio.aac"; commandline = ffmpegutil.extractaudio(srcfile, extractaudio); break; case 2://提取视频 string extractvideo = path + file.separator + "extractvideo.mp4"; commandline = ffmpegutil.extractvideo(srcfile, extractvideo); break; default: break; } executeffmpegcmd(commandline); } ffmpeg执行的回调: /** * 执行ffmpeg命令行 * @param commandline commandline */ private void executeffmpegcmd(final string[] commandline){ if(commandline == null){ return; } ffmpegcmd.execute(commandline, new ffmpegcmd.onhandlelistener() { @override public void onbegin() { log.i(tag, "handle media onbegin..."); } @override public void onend(int result) { log.i(tag, "handle media onend..."); if(ismux){ mhandler.obtainmessage(100).sendtotarget(); }else { runonuithread(new runnable() { @override public void run() { toast.maketext(mediahandleactivity.this, "handle media finish...", toast.length_short).show(); } }); } } }); }
好了,使用ffmpeg进行音视频合成与分离介绍完毕。如果各位有什么问题或者建议,欢迎交流。
源码:链接地址。如果对您有帮助,麻烦fork和star。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。