方法一(Fail)
利用MediaMux实现音视频的合成。
效果:可以实现音视频的合并,利用Android原生的VideoView和SurfaceView播放正常,大部分的播放器也播放正常,但是,但是,在上传Youtube就会出现问题:音频不连续,分析主要是上传Youtube时会被再次的压缩,可能在压缩的过程中出现音频的帧率出现问题。
方法二
利用mp4parser实现
mp4parser是一个视频处理的开源工具箱,由于mp4parser里的方法都依靠工具箱里的一些内容,所以需要将这些内容打包成jar包,放到自己的工程里,才能对mp4parser的方法进行调用。
方法三
利用FFmpeg大法
FFmpeg 由于其丰富的 codec 插件,详细的文档说明,并且与其调试复杂量大的编解码代码(是的,用 MediaCodec 实现起来十分啰嗦和繁琐)还是不如调试一行 ffmpeg 命令来的简单。
implementation 'com.googlecode.mp4parser:isoparser:1.1.21'
2.视频裁剪
/**
* 裁剪视频
* @param srcPath 需要裁剪的原视频路径
* @param outPath 裁剪后的视频输出路径
* @param startTimeMs 裁剪的起始时间
* @param endTimeMs 裁剪的结束时间
*/
public static void clip(String srcPath, String outPath, double startTimeMs, double endTimeMs) throws IOException, IllegalArgumentException {
if (TextUtils.isEmpty(srcPath) || TextUtils.isEmpty(outPath)) {
throw new IllegalArgumentException("file path can't be null!!!!");
}
if (!(new File(srcPath).exists())) {
throw new IllegalArgumentException("the source file is not exist!!!!");
}
if (startTimeMs >= endTimeMs) {
throw new IllegalArgumentException("the startTimeMs is larger than endTimeMs!!!!");
}
Movie movie = MovieCreator.build(srcPath);
List
3.视频合成
/**
* 将 AAC 和 MP4 进行混合[替换了视频的音轨]
*
* @param aacPath .aac
* @param mp4Path .mp4
* @param outPath .mp4
*/
public static boolean muxAacMp4(String aacPath, String mp4Path, String outPath) {
try {
AACTrackImpl aacTrack = new AACTrackImpl(new FileDataSourceImpl(aacPath));
Movie videoMovie = MovieCreator.build(mp4Path);
Track videoTracks = null;// 获取视频的单纯视频部分
for (Track videoMovieTrack : videoMovie.getTracks()) {
if ("vide".equals(videoMovieTrack.getHandler())) {
videoTracks = videoMovieTrack;
}
}
Movie resultMovie = new Movie();
resultMovie.addTrack(videoTracks);// 视频部分
resultMovie.addTrack(aacTrack);// 音频部分
Container out = new DefaultMp4Builder().build(resultMovie);
FileOutputStream fos = new FileOutputStream(new File(outPath));
out.writeContainer(fos.getChannel());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
4.合成音视频长度不一样的问题
/***
* 把视频裁剪15s。然后和音频合并。然后再裁剪15s
* @param sdCardPath
*/
public static void getMergeVideo(String sdCardPath) {
String srcMergePath = sdCardPath + "/4.mp4";//录屏文件
String aacPath = sdCardPath + "/5.aac";
Log.d("peng", "onClick: aacPath" + aacPath);
String outMergePath = sdCardPath + "/6.mp4";//得到临时的合成的视频文件
Log.d("peng", "onClick: outMergePath" + outMergePath);
long startTime = 0;
long endTime = 15 * 1000;
boolean isMux = VideoClipUtils.muxAacMp4(aacPath, srcMergePath, outMergePath);
if (isMux) {
String outMergeClipPath = sdCardPath + "/7.mp4";
Log.d("peng", "onClick: outMergeClipPath" + outMergeClipPath);
try {
VideoClipUtils.clip(outMergePath, outMergeClipPath, startTime, endTime);
Log.d("peng", "OKKKKKKKK");
} catch (IOException e) {
e.printStackTrace();
}
}
}
2017年4月10日更新:
我发现该框架还有诸多问题和BUG,比如无法合并不同格式(帧率,分辨率)的视频,最近已改用MediaCodec,如果需要做一些比较复杂的处理,还是推荐使用MediaCodec和FFmpeg,后面有时间我会写一写相关的内容。