Reputation: 31
I´m trying to edit some videos in my Android app using FFmpeg, but I´m facing some problems when I tried to take just a part of the video.
I´m using this ffmpeg compilation/lib https://github.com/WritingMinds/ffmpeg-android-java
I tried to use this command to trim/cut the video
"-y -i input.mp4 -ss 00:00:01.00 -t 00:00:15.000 -c copy output.mp4"
But with some videos I´m getting a black screen or the video just freezes. The sound works fine in all my tests.
With this command
"-y -i input.mp4 -ss 00:00:01.000 -t 00:00:15.000 -async 1 output.mp4"
Everything works fine in all my tests (video/sound) but takes too much time to generate the output file, this 15s file takes more than 2 minutes to be generated.
I tried other variations of these commands, but I always get problems with the video stream (with black screen or freezing) or takes too much time to generate the output (the user can only select 15s of the videos to send to my server)
Thanks by the help!
EDIT:
this is the part of the code that is trimming the video
String[] cmd = new String[]{"-y","-i",input,"-ss","00:00:05.000","-vcodec","copy",
"-acodec","copy","-t","00:00:15.00","-strict","-2",output };
final FFmpeg ffmpeg = FFmpeg.getInstance(this);
try {
ffmpeg.execute(cmd, new FFmpegExecuteResponseHandler() {
@Override
public void onSuccess(String message) {
Log.i("VideoEditActivity", "Success " + message);
is_video_generated_ = true;
}
@Override
public void onProgress(String message) {
Log.i("VideoEditActivity", "Progress updated " + message);
}
@Override
public void onFailure(String message) {
Log.e("VideoEditActivity", "ERROR! " + message);
}
@Override
public void onStart() {
progress_dialog_.setMessage(getString(R.string.str_video_generating));
progress_dialog_.show();
}
@Override
public void onFinish() {
Log.i("VideoEditActivity", "Finished");
progress_dialog_.hide();
Intent intent = new Intent(getApplicationContext(), VideoPlayActivity.class);
intent.putExtra("media", edited_video_path_);
startActivity(intent);
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
e.printStackTrace();
}
This is the original file: [https://drive.google.com/file/d/0BzqJL_nNetbRYmxvcTljanJwR00/view?usp=sharing][1]
And this the output: 0BzqJL_nNetbReENjRGMtVXQ5VHM/view?usp=sharing (stack overflow does not allow me to add more than 2 links)
Upvotes: 3
Views: 7918
Reputation: 1183
Please try the below ffmpeg command of trim with start and end point
fun trim(): Array<String?>{
val cmdList = ArrayList<String>()
var cmds: Array<String?>? = null
try{
cmdList.add("-y")
cmdList.add("-ss")
cmdList.add(startduration.toString())
cmdList.add("-t")
cmdList.add(endduration.toString())
cmdList.add("-i")
cmdList.add(sourcevideopath)
cmdList.add("-vcodec")
cmdList.add("copy")
cmdList.add("-movflags")
cmdList.add("faststart")
cmdList.add("-preset")
cmdList.add("ultrafast")
cmdList.add(outputvideopath)
cmds = arrayOfNulls<String>(cmdList.size)
cmdList.toArray(cmds)
}catch (e:Exception){
e.printStackTrace()
}
return cmds!!
}
Upvotes: 0
Reputation: 175
I'm a bit late to the party but this might help people in the future. I encountered a lot of issues using the trimming function within FFMEPG especially when dealing with accuracy and speed. The best solution I found is the command below.
-ss 00:00:00.00 -t 00:00:00.00 -noaccurate_seek -i input.mp4 -codec copy -avoid_negative_ts 1 output.mp4
Here's an explanation of what's going on:
After testing many commands this was the one that gave the fastest and most accurate results without any black screens, missing frames or taking too long to execute.
Upvotes: 3
Reputation: 5173
I had faced the same problem, After digging lot, I have found a perfect solution.
/**
* Command for cutting video
*/
private void executeCutVideoCommand(long startMs, long endMs) {
String destPath = "/storage/emulated/0/DCIM/test/";//Replace ypur dest Path
File externalStoragePublicDirectory = new File(destPath);
if (!externalStoragePublicDirectory.exists() ? externalStoragePublicDirectory.mkdir() : true) {
String yourRealPath = "YOUR INPUT PATH";//getPath(MainActivity.this, selectedVideoUri);
String filePrefix = yourRealPath.substring(yourRealPath.lastIndexOf("."));
String destFileName = "cut_video";
boolean isFastMode = false;
File dest = (filePrefix.equals(".webm") || filePrefix.equals(".mkv")) ? new File(externalStoragePublicDirectory, destFileName + ".mp4") : new File(externalStoragePublicDirectory, destFileName + filePrefix);
int fileNo = 0;
while (dest.exists()) {
fileNo++;
dest = (filePrefix.equals(".webm") || filePrefix.equals(".mkv")) ? new File(externalStoragePublicDirectory, destFileName + fileNo + ".mp4") : new File(externalStoragePublicDirectory, destFileName + fileNo + filePrefix);
}
Log.d(TAG, "startTrim: src: " + yourRealPath);
Log.d(TAG, "startTrim: dest: " + dest.getAbsolutePath());
Log.d(TAG, "startTrim: startMs: " + startMs);
Log.d(TAG, "startTrim: endMs: " + endMs);
filePath = dest.getAbsolutePath();
final String[] complexCommand = isFastMode ?
(filePrefix.equals(".webm") || filePrefix.equals(".mkv") || filePrefix.equals(".m4v") || filePrefix.equals(".mov")) ?
new String[]{"-ss", "" + (startMs / 1000), "-y", "-i", yourRealPath, "-preset", "ultrafast", "-t", "" + ((endMs - startMs) / 1000), "-vcodec", "mpeg4", "-b:v", "2097152", "-b:a", "48000", "-ac", "2", "-ar", "22050", "-strict", "-2", filePath}
: new String[]{"-y", "-i", yourRealPath, "-preset", "ultrafast", "-ss", "" + (startMs / 1000), "-t", "" + ((endMs - startMs) / 1000), "-c", "copy", filePath}
: (filePrefix.equals(".webm") || filePrefix.equals(".mkv") || filePrefix.equals(".m4v") || filePrefix.equals(".mov")) ?
new String[]{"-ss", "" + (startMs / 1000), "-y", "-i", yourRealPath, "-t", "" + ((endMs - startMs) / 1000), "-vcodec", "mpeg4", "-b:v", "2097152", "-b:a", "48000", "-ac", "2", "-ar", "22050", "-strict", "-2", filePath} :
new String[]{"-y", "-i", yourRealPath, "-ss", "" + (startMs / 1000), "-t", "" + ((endMs - startMs) / 1000), "-c", "copy", filePath};
execFFmpegBinary(complexCommand);
}
}
where execFFmpegBinary(complexCommand)
is
private void execFFmpegBinary(final String[] command) {
try {
ffmpeg.execute(command, new ExecuteBinaryResponseHandler() {
@Override
public void onFailure(String s) {
Log.d(TAG, "FAILED with output : " + s);
}
@Override
public void onSuccess(String s) {
Log.d(TAG, "SUCCESS with output : " + s);
}
@Override
public void onProgress(String s) {
Log.d(TAG, "Started command : ffmpeg " + command);
}
@Override
public void onStart() {
Log.d(TAG, "Started command : ffmpeg " + command);
}
@Override
public void onFinish() {
Log.d(TAG, "Finished command : ffmpeg " + command);
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
// do nothing for now
}
}
Upvotes: 6
Reputation: 224
try:
-y -i -ss 00:00:00.00 input_path -vcodec copy -acodec copy -t 00:00:00.00 -strict -2 output_path
-ss is the starttime and -t the duration. HH:MM:SS.SS
its fast as hell. does the trimming without reencoding
Upvotes: 1