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

1.概述

mp4parser是一个视频处理的开源工具箱,我希望在Java工程里使用视频剪切、视频合并、视频转码这3种功能。

由于mp4parser里的方法都依靠工具箱里的一些内容,所以需要将这些内容打包成jar包,放到自己的工程里,才能对mp4parser的方法进行调用。

2.打包jar包

1)下载mp4parser:https://github.com/sannies/mp4parser (我下载的版本是:mp4parser-mp4parser-project-1.9.27),解压。

2)在eclipse-java里,以工程形式导入mp4parser-mp4parser-project-1.9.27文件夹。

3)如下图,在isoparser文件夹和muxer文件夹下面分别都有一个pom.xml的文件,先后在这两个xml文件上进行操作:右键->Debug As->Maven install,在eclipse的console工作台上能看到安装进程,如果安装成功,最后会提示SUCCESS INSTALL

成功安装后,isoparser文件夹和muxer文件夹下都会出现一个名为target的文件夹,target文件夹里会有打包好的jar包。

我打包好的jar包已上传到CSDN下载页面,可直接下载使用,下载传送门:http://download.csdn.net/detail/u014691453/9688573

基于mp4parser的视频剪切,视频合并,视频转码实例_第1张图片

3.在eclipse里建立工程

1)配置好jdk,加载jar包

在工程名字上进行操作:右键->Properties->Java Build Path->Libraries->Add External JARs,把打包好的jar包加载进来。

基于mp4parser的视频剪切,视频合并,视频转码实例_第2张图片

2)AppendVideo.java,ShortenVideo.java,H264ToMp4.java

在工程的src文件夹下建立以上3个java文件,大部分代码源自mp4parser工具箱。

AppendVideo.java 视频合并

import org.mp4parser.Container;
import org.mp4parser.muxer.Movie;
import org.mp4parser.muxer.Track;
import org.mp4parser.muxer.builder.DefaultMp4Builder;
import org.mp4parser.muxer.container.mp4.MovieCreator;
import org.mp4parser.muxer.tracks.AppendTrack;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class AppendVideo {
    public static void main(String[] args) throws IOException {


        String[] srcVideoPath = new String[]{
        		"v1.mp4",
        		"v1.mp4",
                        "v1.mp4"
        };
        String dstVideoPath = "";
        videoMerge(srcVideoPath, dstVideoPath);
    }
    
    public static void videoMerge(String[] srcVideoPath, String dstVideoPath) throws IOException {

        List inMovies = new ArrayList();
        for (String videoUri : srcVideoPath) {
            inMovies.add(MovieCreator.build(videoUri));
        }

        List videoTracks = new LinkedList();
        List 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);
                }
            }
        }

        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 out = new DefaultMp4Builder().build(result);

        FileChannel fc = new RandomAccessFile(String.format(dstVideoPath+"mergeOutput.mp4"), "rw").getChannel();
        out.writeContainer(fc);
        fc.close();
    }
}

ShortenVideo.java 视频剪切

import org.mp4parser.Container;
import org.mp4parser.muxer.Movie;
import org.mp4parser.muxer.Track;
import org.mp4parser.muxer.builder.DefaultMp4Builder;
import org.mp4parser.muxer.container.mp4.MovieCreator;
import org.mp4parser.muxer.tracks.AppendTrack;
import org.mp4parser.muxer.tracks.ClippedTrack;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;


public class ShortenVideo {
	
	public static void main(String[] args) throws IOException{
		double [] times = {1,4,2,6,9,16};  //剪切1~4秒,2~6秒,9~16秒
		String srcVideoPath = "test.mp4";
		String dstVideoPath = "";
		videoCut(srcVideoPath, dstVideoPath, times);
	}


    public static void videoCut(String srcVideoPath, String dstVideoPath, double [] times) throws IOException {
    	int dstVideoNumber = times.length/2;
		String [] dstVideoPathes = new String[dstVideoNumber];
		for(int i=0; i tracks = movie.getTracks();
        movie.setTracks(new LinkedList());
        // remove all tracks we will create new tracks from the old

        
        double startTime1 = times[timesCount];
        double endTime1 = times[timesCount+1];
        timesCount = timesCount + 2;

        boolean timeCorrected = false;

        // Here we try to find a track that has sync samples. Since we can only start decoding
        // at such a sample we SHOULD make sure that the start of the new fragment is exactly
        // such a frame
        for (Track track : tracks) {
            if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) {
                if (timeCorrected) {
                    // This exception here could be a false positive in case we have multiple tracks
                    // with sync samples at exactly the same positions. E.g. a single movie containing
                    // multiple qualities of the same video (Microsoft Smooth Streaming file)

                    throw new RuntimeException("The startTime has already been corrected by another track with SyncSample. Not Supported.");
                }
                startTime1 = correctTimeToSyncSample(track, startTime1, false);
                endTime1 = correctTimeToSyncSample(track, endTime1, true);
                
                timeCorrected = true;
            }
        }

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

            for (int i = 0; i < track.getSampleDurations().length; i++) {
                long delta = track.getSampleDurations()[i];


                if (currentTime > lastTime && currentTime <= startTime1) {
                    // current sample is still before the new starttime
                    startSample1 = currentSample;
                }
                if (currentTime > lastTime && currentTime <= endTime1) {
                    // current sample is after the new start time and still before the new endtime
                    endSample1 = currentSample;
                }
                
                lastTime = currentTime;
                currentTime += (double) delta / (double) track.getTrackMetaData().getTimescale();
                currentSample++;
            }
            //movie.addTrack(new AppendTrack(new ClippedTrack(track, startSample1, endSample1), new ClippedTrack(track, startSample2, endSample2)));
            movie.addTrack(new ClippedTrack(track, startSample1, endSample1));
        }
        long start1 = System.currentTimeMillis();
        Container out = new DefaultMp4Builder().build(movie);
        long start2 = System.currentTimeMillis();
        FileOutputStream fos = new FileOutputStream(String.format(dstVideoPathes[idst]));
        FileChannel fc = fos.getChannel();
        out.writeContainer(fc);

        fc.close();
        fos.close();
        long start3 = System.currentTimeMillis();
        
    	}
    }


    private 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) {
                // samples always start with 1 but we start with zero therefore +1
                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];
    }
}

H264ToMp4.java 视频转码H264转mp4

import org.mp4parser.Container;
import org.mp4parser.muxer.FileDataSourceImpl;
import org.mp4parser.muxer.Movie;
import org.mp4parser.muxer.builder.DefaultMp4Builder;
import org.mp4parser.muxer.tracks.h264.H264TrackImpl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;


public class H264ToMp4 {
	
    public static void main(String[] args) throws IOException {
    	String srcVideoPath = "count.h264";
    	String dstVideoPath = "";
    	videoToVideo(srcVideoPath, dstVideoPath);
    }
    public static void videoToVideo(String srcVideoPath, String dstVideoPath) throws IOException {
    	H264TrackImpl h264Track = new H264TrackImpl(new FileDataSourceImpl(srcVideoPath));
        //AACTrackImpl aacTrack = new AACTrackImpl(new FileInputStream("/home/sannies2/Downloads/lv.aac").getChannel());
        Movie m = new Movie();
        m.addTrack(h264Track);
        //m.addTrack(aacTrack);

        Container out = new DefaultMp4Builder().build(m);
        FileOutputStream fos = new FileOutputStream(new File(dstVideoPath+"h264_output.mp4"));
        FileChannel fc = fos.getChannel();
        out.writeContainer(fc);
        fos.close();
        
    }
}

你可能感兴趣的:(Java)