Raupp
Raupp

Reputation: 31

Android ffmpeg video cut

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

Answers (4)

gpuser
gpuser

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

AngryCubeDev
AngryCubeDev

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:

  • -i: Input file
  • -ss: This is placed before the input file as it seeks to this position in the input file for speed.
  • -t: The position of where the command is going to cut to.
  • -noaccurate_seek: Preserves the the frames between -ss and the next keyframe other wise they are dropped by default.
  • -codec copy: This copies the video and audio codecs as they are for speed.
  • -avoid_negative_ts 1: Sets the first timestamp as 1 and avoids it becoming a negative
  • -The output file is the last part of the command

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

Muhamed Riyas M
Muhamed Riyas M

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

Juan Felippo
Juan Felippo

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

Related Questions