My original video is 10.3 seconds.
I want to start cutting from sec 2.7 to sec 5.7
public static void startTrim(#NonNull File src, #NonNull String dst, long startMs, long endMs, #NonNull OnTrimVideoListener callback) throws IOException {
final String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
final String fileName = "MP4_" + timeStamp + ".mp4";
final String filePath = dst;
File file = new File(filePath);
file.getParentFile().mkdirs();
Log.d(TAG, "Generated file path " + filePath);
genVideoUsingMp4Parser(src, file, startMs, endMs, callback);
}
private static void genVideoUsingMp4Parser(#NonNull File src, #NonNull File dst, long startMs, long endMs, #NonNull OnTrimVideoListener callback) throws IOException {
// NOTE: Switched to using FileDataSourceViaHeapImpl since it does not use memory mapping (VM).
// Otherwise we get OOM with large movie files.
Movie movie = MovieCreator.build(new FileDataSourceViaHeapImpl(src.getAbsolutePath()));
List<Track> tracks = movie.getTracks();
movie.setTracks(new LinkedList<Track>());
// remove all tracks we will create new tracks from the old
double startTime1 = startMs ; //2.7
double endTime1 = endMs, //5.7
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 CroppedTrack(track, startSample1, endSample1)));
}
dst.getParentFile().mkdirs();
if (!dst.exists()) {
dst.createNewFile();
}
Container out = new DefaultMp4Builder().build(movie);
FileOutputStream fos = new FileOutputStream(dst);
FileChannel fc = fos.getChannel();
out.writeContainer(fc);
fc.close();
fos.close();
if (callback != null)
callback.getResult(Uri.parse(dst.toString()));
}
But after the method correctTimeToSyncSample is finished the startTime1 gets value 2.08... and endTime1 gets value 5.18...
startTime1 = 2.0830555555555557
endTime1 = 5.182877777777778
private static double correctTimeToSyncSample(#NonNull 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];
}
The video is successfully saved but not in the exact time I wanted..
Can anyone please help me with this
Video can only be cut at keyframes (called sync samples in mp4). A key frame is uasually every 1 to 10 seconds. To get an exact frame, you need to transcode using a tool like ffmpeg.
You can add edts/elst/stss/stsh/sdtp box to do it.
add edts/elst box to indicate the media-time and segment-duration, for your case, media-time of 'elst' box is set to the media time of 2.7s, and segment duration is set to 3 seconds with the unit of time-scale of movie.
Of course, you need add Sync Sample box, Shadow Sync Sample Box and Independent and Disposable Samples Box, to specify the dependency of your first frame if it is not a key frame.
The qualified mp4 player will find the dependent sync sample before the frame at your start time, and decode all of frames edited out by means of an edit list which is used for decoding your first dependent frame, but not to present them until the first frame you specified.
I am trying to generate an array with each item in the array being the path of a video located in a folder named raw in resources. However the program crashes when it is run. Here is the code for adding the file names to a String array.
String[] fileArray;
File dir = new File("/res/raw");
File[] files = dir.listFiles();
fileArray = new String[files.length];
for (int i = 0; i < files.length; ++i){
fileArray[i] = files[i].getName();
}
You need this:
Field[] fields = R.raw.class.getFields();
for (int i = 0; i < fields.length - 1; i++) {
String name = fields[i].getName();
//do your thing here
}
I want to read the file names from the default internal storage folder of my app but even if there are some files I get a List of size 0 I use the following to read the file names
File dirFiles = Settings.this.getFilesDir();
File list[] = dirFiles.listFiles();
for( int i=0; i< list.length; i++)
{
myList.add( list[i].getName() );
}
What I am doing wrong here? is the path I get correct? or it needs to have a "/" at the end of it?
/data/data/com.compfrind.contacts/files
Try this way
private File path = new File("/storage/" + "");
File list[] = path.listFiles();
for( int i=0; i< list.length; i++)
{
myList.add( list[i].getName() );
}
Also please have a look at this answer
So I have this simple method that helps list all of the files in a directory (hidden and non-hidden) and I wish to edit it to display only non hidden files.
public ArrayList<String> GetFiles(String DirectoryPath) {
ArrayList<String> MyFiles = new ArrayList<String>();
File file = new File(DirectoryPath);
//You create an array list
//The public final field length, which contains the number of components of the array
file.mkdirs();
File[] files = file.listFiles();
//list all of the files in the array
if (files.length == 0)
//if there are no files, return null
return null;
else {
//if the number of files is greater than 0, add the files and their names
for (int i = 0; i < files.length; i++)
MyFiles.add(files[i].getName());
}
return MyFiles;
How can I modify the above code to only display non hidden files?
By the way, inserting a . in front of a file name hides the file.
Thank you.
You should be able to make use of the isHidden(). Refer to the docs here.
//if the number of files is greater than 0, add the files and their names
for (int i = 0; i < files.length; i++) {
if(!files[i].isHidden())
MyFiles.add(files[i].getName()); // Add non hidden files
}
I am using GridView with camera to show images (maximum 4 images)
i need all the captured images path in ArrayList ,
The problem is when the loop iterates , it give me previous array value along with latest array
Eg:
iteration 1 : [imagepath1]
iteration 2 : [imagepath1,imagepath2]
iteration 3 : [imagepath1,imagepath2,imagepath3]
I need only the latest iterated value
i.e : [imagepath1,imagepath2,imagepath3]
// ArrayList<String> imageList;
private List<String> RetriveCapturedImagePath() {
List<String> tFileList = new ArrayList<String>();
File f = new File(GridViewDemo_ImagePath);
if (f.exists()) {
File[] files = f.listFiles();
Arrays.sort(files);
//Log.e("f.listFiles();", "files "+files);
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isDirectory())
continue;
tFileList.add(file.getPath());
Log.e("file.getPath()", "karfile " + file.getPath());
imageList.add(file.getPath());
Log.e("imageList RetriveCapturedImagePath", "karimageList" + imageList);
}
}
return tFileList;
}