Reputation: 11
I am currently making an Android app that can Merge Videos. Here is the java class to do so :
public class MergeVideos extends AsyncTask<String, Integer, String> {
// The working path where the video files are located
private String workingPath;
// The files name to merge
private ArrayList<String> videosToMerge;
public MergeVideos(String workingPath, ArrayList<String> videosToMerge) {
this.workingPath=workingPath;
this.videosToMerge=videosToMerge;
}
@Override
protected void onPreExecute() {
}
@Override
protected String doInBackground(String... params) {
int count=videosToMerge.size();
try {
Movie[] inMovies = new Movie[count];
for (int i = 0; i < count; i++) {
File file = new File(workingPath, videosToMerge.get(i));
if (file.exists()) {
FileInputStream fis = new FileInputStream(file);
FileChannel fc = fis.getChannel();
inMovies[i] = MovieCreator.build((DataSource) fc);
fis.close();
fc.close();
}
}
List<Track> videoTracks = new LinkedList<Track>();
List<Track> audioTracks = new LinkedList<Track>();
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()])));
}
IsoFile out = (IsoFile) new DefaultMp4Builder().build(result);
long timestamp = new Date().getTime();
String timestampS = "" + timestamp;
File storagePath = new File(Environment.getExternalStorageDirectory() + "/VideosMerged");
storagePath.mkdirs();
File myMovie = new File(storagePath, String.format("output-%s.mp4", timestampS));
FileOutputStream fos = new FileOutputStream(myMovie);
FileChannel fco = fos.getChannel();
fco.position(0);
out.getBox(fco);
fco.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/output.mp4";
return mFileName;
}
@Override
protected void onPostExecute (String value) {
super.onPostExecute(value);
}
I got this code from Github
And here is how I use it in the main class : In onCreate :
videosList=new ArrayList<String>();
videosList.add("sample_mpeg4.mp4");
videosList.add("big_buck_bunny.mp4");
this.workPath = Environment.getExternalStorageDirectory()+"/com.marakana.android.videocapturedemo";
And then when I click on a Button, it is supposed to merge :
mergeVideos= new MergeVideos(workPath, videosList).execute();
However, when I launch the app, I have the following errors :
02-04 10:59:34.952 32644-32644/com.marakana.android.videocapturedemo E/MediaPlayer﹕ Should have subtitle controller already set 02-04 10:59:34.962 32644-961/com.marakana.android.videocapturedemo E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #2 Process: com.marakana.android.videocapturedemo, PID: 32644 java.lang.RuntimeException: An error occured while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:300) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) at java.util.concurrent.FutureTask.setException(FutureTask.java:222) at java.util.concurrent.FutureTask.run(FutureTask.java:242) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:841) Caused by: java.lang.NullPointerException at com.marakana.android.videocapturedemo.MergeVideos.doInBackground(MergeVideos.java:69) at com.marakana.android.videocapturedemo.MergeVideos.doInBackground(MergeVideos.java:30) at android.os.AsyncTask$2.call(AsyncTask.java:288) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:841)
I tried to look a the lignes 30 and 69 in MergeVideos as it is said, which are :
public class MergeVideos extends AsyncTask<String, Integer, String> {
and
for (Movie m : inMovies) {
but I can't see what is wrong. I'm a beginner in Android, so any help would be very much appreciated !
Thank you
Upvotes: 1
Views: 366
Reputation:
Try adding to your mMovies array like this
inMovies.add( MovieCreator.build((DataSource) fc))
instead of this:
inMovies[i] = MovieCreator.build((DataSource) fc);
Also add a try and catch or if to check that mMovies is empty
if (mMovies.length==0)
//don't proceed with the offending code
for (Movie m : inMovies) {
It is throwing the exception, because it is trying to loop through an empty array, the array is not null, it is empty, so you need to check the length.
Upvotes: 0