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

来源:互联网 发布:淘宝助理无法图片搬家 编辑:程序博客网 时间:2024/04/28 13:48

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


2017年4月10日更新:

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


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}//合成视频mp4Container 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等。


1 1