Android 使用mp4parser进行视频的分割与合并

原创 2016年12月26日 15:16:12

mp4parser 是一个优秀的视频处理框架,下面就教大家使用mp4parser在android上进行视频的分割与合并。


2017年4月10日更新:

我发现该框架还有诸多问题和BUG,比如无法合并不同格式(帧率,分辨率)的视频,最近已改用MediaCodec,如果需要做一些比较复杂的处理,还是推荐使用MediaCodec和FFmpeg,后面有时间我会写一写相关的内容。


FFmpeg框架EpMedia



Github:https://github.com/sannies/mp4parser\


Gradle:

dependencies {
    compile 'com.googlecode.mp4parser:isoparser:1.1.21'
}

视频的分割:

public class VideoClip {
	private String filePath;//视频路径
	private String workingPath;//输出路径
	private String outName;//输出文件名
	private double startTime;//剪切起始时间
	private double endTime;//剪切结束时间

	private void clip() {
		try {
			Movie movie = MovieCreator.build(filePath);

			List<Track> tracks = movie.getTracks();
			movie.setTracks(new LinkedList<Track>());
			//移除旧的通道
			boolean timeCorrected = false;

			//计算剪切时间
			for (Track track : tracks) {
				if (track.getSyncSamples() != null
						&& track.getSyncSamples().length > 0) {
					if (timeCorrected) {
						throw new RuntimeException(
								"The startTime has already been corrected by another track with SyncSample. Not Supported.");
					}
					startTime = VideoHelper.correctTimeToSyncSample(track, startTime, false);
					endTime = VideoHelper.correctTimeToSyncSample(track, endTime, true);
					timeCorrected = true;
				}
			}

			for (Track track : tracks) {
				long currentSample = 0;
				double currentTime = 0;
				double lastTime = 0;
				long startSample1 = -1;
				long endSample1 = -1;

				for (int i = 0; i < track.getSampleDurations().length; i++) {
					long delta = track.getSampleDurations()[i];
					if (currentTime > lastTime && currentTime <= startTime) {
						startSample1 = currentSample;
					}
					if (currentTime > lastTime && currentTime <= endTime) {
						endSample1 = currentSample;
					}
					lastTime = currentTime;
					currentTime += (double) delta
							/ (double) track.getTrackMetaData().getTimescale();
					currentSample++;
				}
				movie.addTrack(new CroppedTrack(track, startSample1, endSample1));// new
			}

			//合成视频mp4
			Container out = new DefaultMp4Builder().build(movie);
			File storagePath = new File(workingPath);
			storagePath.mkdirs();
			FileOutputStream fos = new FileOutputStream(new File(storagePath, outName));
			FileChannel fco = fos.getChannel();
			out.writeContainer(fco);
			fco.close();
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


视频的合并:

public class VideoMerge {

	private String workingPath;//输出文件目录
	private ArrayList<String> videosToMerge;//需要合并的视频的路径集合
	private String outName;//输出的视频名称

	private void merge(){
		int count = videosToMerge.size();
		try {
			Movie[] inMovies = new Movie[count];
			for (int i = 0; i < count; i++) {
				inMovies[i] = MovieCreator.build(videosToMerge.get(i));
			}

			List<Track> videoTracks = new LinkedList<>();
			List<Track> audioTracks = new LinkedList<>();

			//提取所有视频和音频的通道
			for (Movie m : inMovies) {
				for (Track t : m.getTracks()) {
					if (t.getHandler().equals("soun")) {
						audioTracks.add(t);
					}
					if (t.getHandler().equals("vide")) {
						videoTracks.add(t);
					}
					if (t.getHandler().equals("")) {

					}
				}
			}

			//添加通道到新的视频里
			Movie result = new Movie();
			if (audioTracks.size() > 0) {
				result.addTrack(new AppendTrack(audioTracks
						.toArray(new Track[audioTracks.size()])));
			}
			if (videoTracks.size() > 0) {
				result.addTrack(new AppendTrack(videoTracks
						.toArray(new Track[videoTracks.size()])));
			}
			Container mp4file = new DefaultMp4Builder()
					.build(result);


			//开始生产mp4文件
			File storagePath = new File(workingPath);
			storagePath.mkdirs();
			FileOutputStream fos =  new FileOutputStream(new File(storagePath,outName));
			FileChannel fco = fos.getChannel();
			mp4file.writeContainer(fco);
			fco.close();
			fos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

里面用到的VideoHelper:

public class VideoHelper {


	//换算剪切时间
	public static double correctTimeToSyncSample(Track track, double cutHere,
												 boolean next) {
		double[] timeOfSyncSamples = new double[track.getSyncSamples().length];
		long currentSample = 0;
		double currentTime = 0;
		for (int i = 0; i < track.getSampleDurations().length; i++) {
			long delta = track.getSampleDurations()[i];
			if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) {
				timeOfSyncSamples[Arrays.binarySearch(track.getSyncSamples(),
						currentSample + 1)] = currentTime;
			}
			currentTime += (double) delta
					/ (double) track.getTrackMetaData().getTimescale();
			currentSample++;
		}
		double previous = 0;
		for (double timeOfSyncSample : timeOfSyncSamples) {
			if (timeOfSyncSample > cutHere) {
				if (next) {
					return timeOfSyncSample;
				} else {
					return previous;
				}
			}
			previous = timeOfSyncSample;
		}
		return timeOfSyncSamples[timeOfSyncSamples.length - 1];
	}
}

视频的分割与合并也可以用其他方法例如:ffmpeg,MediaCodec等。


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

android视频合成相关整理

1, ffmpeg视频转换: http://blog.csdn.net/gobitan/article/details/22750719 2, 视频合成示例代码:http://blog.csdn.n...

Android 视频分离和合成(MediaMuxer和MediaExtractor)

Android 视频的分离和合成这方面的资源网上是少之又少,学习的过程也是各种demo的看,各种demo的实验,各种坑的踩,为了让大家能够android的视频的分离和合成又个了解,写了下面的例子,完整...

android 视频录制,视频拼接

连续录制视频,点击屏幕开始录制,再点击屏幕结束录制,再点击开始录制,拼接多个录制的视频,视频都保存在sd卡。 需要权限 android:name="android.permission.CAMER...

Android MediaCodec实现多段音视频的截取与拼接

视音频编辑中,对多段媒体素材进行截取和拼接是非常常见的操作。截取和拼接实际上是对媒体文件数据重新进行组合的过程。     要实现这些功能,就需要对媒体文件进行编解码操作,即先解码要处理的媒体文件数...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Android实现视频剪切、视频拼接以及音视频合并

因公司项目有需求,要实现视频剪切,音视频合并以及添加弹幕的功能,自己通过在网上查找大量的资料终于把功能实现了,把实现的公共类提取出来,以便以后复习巩固。 工具类 一、视频处理工具类   /...
  • lxy_tap
  • lxy_tap
  • 2017年07月06日 18:10
  • 2300

Android mp4parser 视频拼接

最近项目里面要用到视频拼接,参考网上的资料决定采用mp4parser进行视频拼接,github上有mp4parser的源码。mp4parser项目很大,这里只用到了视频拼接的部分。这里我封装了一个My...

Android(java方法)上实现mp4的分割和拼接 (一)

最近正在处理android上的mp4切割问题。学习了很多mp4的知识,mp4文件按照编码类型,分为mpeg-4,avc这两种;这两种类型的mp4在后面的处理中会有不同的地方。            ...
  • sdvch
  • sdvch
  • 2014年08月02日 15:09
  • 11556

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

基于mp4parser的视频剪切,视频合并,视频转码实例

1.概述 mp4parser是一个视频处理的开源工具箱,我希望在Java工程里使用视频剪切、视频合并、视频转码这3种功能。 由于mp4parser里的方法都依靠工具箱里的一些内容,所以需要将这些内容打...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android 使用mp4parser进行视频的分割与合并
举报原因:
原因补充:

(最多只允许输入30个字)