FFmpeg Video Editor

FFmpeg is a tool that can be used to edit or convert videos and audios.It includes libavcodec – the audio/video codec library.
Some of the uses of FFmpeg are:

  • Video Compress
  • Audio Compress
  • Video Cut
  • Video Rotate
  • Video Crop
  • Extract Picture from Video
  • Extract Sound from Video
  • Change Video Resolution
  • Adding filters to videos
  • Creating fast and slow motion video
  • Reverse Video
  • Creating video from images
  • Convert video from one format into another
  • Merge an audio and video

For integrating FFmpeg in android we can use precompiled libraries like ffmpeg-android.
ffmpeg-android is a library by WritingMinds that simplifies your task of using ffmpeg in Android project.

Below post covers integration of following features using FFmpeg-

  • Video Compress
  • Video Cut
  • Extract Picture from Video
  • Extract Audio from Video
  • Add Fade In Fade Out effect to Video
  • Creating Fast Motion Video
  • Creating Slow Motion Video
  • Reverse Video

Besides these following features have been discussed in comments section-

  • Merging audio and video overriding video’s audio if there
  • Adding audio as background music to video keeping video’s audio
  • Speed up video 3x, 4x times
  • Creating video from images
  • Segmenting video
  • Adding watermark
  • Concatenate audio with another audio
  • Concatenate video with another video
  • Adding two watermarks to a video at different times
  • Using URL as an input option

I have used RangeSeekBar to allow user to select the time range for cutting video from original video.

Complete code for the post is uploaded on github at below link-

https://github.com/bhuvnesh123/FFmpeg-Video-Editor-Android

and the demo app is published on play store-

https://play.google.com/store/apps/details?id=videoeditor.bhuvnesh.com.ffmpegvideoeditor

Integrating FFmpeg library

1.Add FFmpeg dependency in app module gradle file and sync project. 

compile ‘com.writingminds:FFmpegAndroid:0.3.2’

2.Load FFMpeg using below code-

FFmpeg ffmpeg;
private void loadFFMpegBinary() {
try {
if (ffmpeg == null) {
Log.d(TAG, “ffmpeg : null”);
ffmpeg = FFmpeg.getInstance(this);
}
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
@Override
public void onFailure() {
showUnsupportedExceptionDialog();
}

@Override
public void onSuccess() {
Log.d(TAG, “ffmpeg : correct Loaded”);
}
});
} catch (FFmpegNotSupportedException e) {
showUnsupportedExceptionDialog();
} catch (Exception e) {
Log.d(TAG, “EXception not supported : ” + e);
}
}

loadBinary copies the ffmpeg binary to device according to device’s architecture. You just need to put this once in your code, whenever you are starting the application or using FFmpeg for the first time.

3.Create a method which will take ffmpeg command as an argument and pass it to execute method of FFMpeg class.

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);
//Perform action on success
}
}

@Override
public void onProgress(String s) {
Log.d(TAG, “progress : ” + s);
}

@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) {

}
}

execute() method of FFmpeg class takes command as parameter and executes it.It has a ResponseHandler which return event on start,progress,finish,success and failure.

Now we will go through the various FFmpeg commands that we can use to perform different operations-

Compress a video

To compress a video we can use below command-

String[] command = {"-y", "-i", inputFileAbsolutePath, "-s", "160x120", "-r", "25", "-vcodec", "mpeg4", "-b:v", "150k", "-b:a", "48000", "-ac", "2", "-ar", "22050", outputFileAbsolutePath};

Here,

-y

Overwrite output files without asking.

-i

ffmpeg reads from an arbitrary number of input “files” specified by the -i option

-s

video output size

-r

Set frame rate

-vcodec

Set the video codec.

-b:v

Set the video bitrate

-b:a

Set the audio bitrate
-ac

Set the number of audio channels.

-ar

sets the sampling rate for audio streams if encoded

Cut a video

To cut a video with re-encoding ,we can use below command-

String[] complexCommand = {"-ss", "" + startMs / 1000, "-y", "-i", inputFileAbsolutePath, "-t", "" + (endMs - startMs) / 1000, "-s", "320x240", "-r", "15", "-vcodec", "mpeg4", "-b:v", "2097152", "-b:a", "48000", "-ac", "2", "-ar", "22050", outputFileAbsolutePath};

Here,

-ss
seeks to position(time from where we want to start cutting video)
-t
limit the duration of data read from the input file(duration from cutting start position time upto which we want to cut video)

Other options already defined in previous command

Remove -s 320×240 if you want to keep the resolution of original video.

To cut a video without re-encoding ,we can use below command-

String[] complexCommand = { "-y", "-i", inputFileAbsolutePath,"-ss", "" + startMs / 1000, "-t", "" + (endMs - startMs) / 1000, "-c","copy", outputFileAbsolutePath};

Here,

-c copy
copies the video, audio and bit stream from the input to the output file without re-encoding them.

Extract images from video

To extract images from a video we can use below command

String[] complexCommand = {"-y", "-i", inputFileAbsolutePath, "-an", "-r", "1/2", "-ss", "" + startMs / 1000, "-t", "" + (endMs - startMs) / 1000, outputFileAbsolutePath};

Here,

-an
Disable audio recording.

-r 1/2 will extract one image frame from every 2 second of video.Similarly,-r 1/4 will extract one image frame from every 4 seconds of video and -r 1 will extract one image frame from every second of video.

Remove -r option(-r 1/2 in above command) if you want to extract all video frames as images from the specified time duration.

Other options already defined in previous commands

Extract audio from video

To extract audio from a video we can use below command

String[] complexCommand = {"-y", "-i", inputFileAbsolutePath, "-vn", "-ar", "44100", "-ac", "2", "-b:a", "256k", "-f", "mp3", outputFileAbsolutePath};

-vn

Disable video recording

-f

format

Other options already defined in previous commands

Add Fade In Fade Out effect at start and end of video

To add Fade In and Fade Out effect to start and end of video respectively we can use below command

String[] complexCommand = {"-y", "-i", inputFileAbsolutePath, "-acodec", "copy", "-vf", "fade=t=in:st=0:d=5,fade=t=out:st=" + String.valueOf(duration - 5) + ":d=5", outputFileAbsolutePath};

Here,

-acodec

Set the audio codec

vf filtergraph (output)

Create the filtergraph specified by filtergraph and use it to filter the stream.

fade=t=in:st=0:d=5

Fade in first 5 seconds of video
fade=t=out:st=”+String.valueOf(duration-5)+”:d=5″

Fade out last 5 seconds of video

Other options already defined in previous commands

Fast Motion Video

To create fast motion video we can use below command-

String[] complexCommand = {"-y", "-i", inputFileAbsolutePath, "-filter_complex", "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]", "-map", "[v]", "-map", "[a]", "-b:v", "2097k", "-r", "60", "-vcodec", "mpeg4", outputFileAbsolutePath};

-filter_complex filtergraph (global)

Define a complex filtergraph, i.e. one with arbitrary number of inputs and/or outputs.

[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]

The filter works by changing the presentation timestamp (PTS) of each video frame. For example, if there are two succesive frames shown at timestamps 1 and 2, and you want to speed up the video, those timestamps need to become 0.5 and 1, respectively. Thus, we have to multiply them by 0.5.

You can speed up or slow down audio with the atemto audio filter.The atempo filter is limited to using values between 0.5 and 2.0 (so it can slow it down to no less than half the original speed, and speed up to no more than double the input).To speed up the audio to double of its speed we have to use atempo value 2.0 .

-map

-map option is a way to tell FFmpeg which streams do you want to select/copy from input to an output.When you want to control which streams are included then you will need/want to specify the “-map” command manually, and change these parameters.

-map [v] -map [a] – Select the streams labeled v and a
-map 0 -Select all streams from input 0.

Check out this for detailed explanation on map option

Other options already defined in previous commands

Slow Motion Video

To create a slow motion video we can use the below command-

String[] complexCommand = {"-y", "-i", inputFileAbsolutePath, "-filter_complex", "[0:v]setpts=2.0*PTS[v];[0:a]atempo=0.5[a]", "-map", "[v]", "-map", "[a]", "-b:v", "2097k", "-r", "60", "-vcodec", "mpeg4", outputFileAbsolutePath};

The filter works by changing the presentation timestamp (PTS) of each video frame.To slow down your video, you have to use a multiplier greater than 1. For example, if there are two succesive frames shown at timestamps 1 and 2, and you want to slow down the video, those timestamps need to become 2 and 4, respectively.Thus, we have to multiply them by 2.0.

You can speed up or slow down audio with the atemto audio filter.The atempo filter is limited to using values between 0.5 and 2.0 (so it can slow it down to no less than half the original speed, and speed up to no more than double the input).To slow down the audio to half of its speed we have to use atempo value 0.5 .

Other options already defined in previous commands.

Reverse Video

For reversing video,first we need to divide video into segments with duration of 10 seconds or less because reverse video command for ffmpeg will not work for long duration videos unless your device has 32 GB of RAM.

Hence,to reverse a video-

1.Divide video into segments with duration of 10 seconds or less.
2.Reverse the segmented videos
3.Concatenate reversed segmented videos in reverse order.

For dividing video into segments with duration of 6 seconds we can use the below command-

String[] complexCommand = {"-i", inputFileAbsolutePath, "-c:v", "libx264", "-crf", "22", "-map", "0", "-segment_time", "6", "-g", "9", "-sc_threshold", "0", "-force_key_frames", "expr:gte(t,n_forced*6)", "-f", "segment", outputFileAbsolutePath};

-c:v libx264

encodes all video streams with libx264

-crf

Set the quality for constant quality mode.

-segment_time

time for each segment of video

-g

GOP size

-sc_threshold

set scene change threshold.

-force_key_frames expr:gte(t,n_forced*n)

Forcing a keyframe every n seconds

 

After segmenting video,we need to reverse the segmented videos.For that we need to run a loop where each segmented video file will be reversed.

To reverse a video with audio(without removing its audio) we can use the below command-

String command[] = {"-i", inputFileAbsolutePath, "-vf", "reverse", "-af", "areverse", outputFileAbsolutePath};

To reverse a video with audio removing its audio we can use the below command-

String command[] = {"-i", inputFileAbsolutePath, "-an", "-vf", "reverse", outputFileAbsolutePath};

To reverse a video without audio we can use the below command-

String command[] = {"-i",inputFileAbsolutePath, "-vf", "reverse", outputFileAbsolutePath};

 

After reversing segmented videos,we need to concatenate reversed segmented videos in reverse order.For that we sort videos on the basis of last modified file using Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE).

Then, to concatenate  reversed segmented videos(with audio) we can use the below command-

String command[] = {"-i",inputFile1AbsolutePath,"-i",inputFile2AbsolutePath .....,"-i",inputFileNAbsolutePath,"-filter_complex","[0:v0] [0:a0] [1:v1] [1:a1]...[N:vN] concat=n=N:v=1:a=1 [v] [a],"-map","[v]","-map","[a]", outputFileAbsolutePath};

To concatenate  reversed segmented videos(without audio) we can use the below command-

String command[] = {"-i",inputFile1AbsolutePath,"-i",inputFile2AbsolutePath .....,"-i",inputFileNAbsolutePath,"-filter_complex","[0:0] [1:0] [2:0]...[N:0] concat=n=N:v=1:a=0",outputFileAbsolutePath};

 

-filter_complex [0:v0] [0:a0] [1:v1] [1:a1]…[N:vN] tells ffmpeg what streams to send to the concat filter.In the above case, video stream 0 [0:v0] and audio stream 0 [0:a0] from input 0,video stream 1 [1:v1] and audio stream 1 [1:v1] from input 1 and so on.

concat filter is used to concatenate audio and video streams, joining them together one after the other.The filter accepts the following options:

n

Set the number of segments. Default is 2.
v

Set the number of output video streams, that is also the number of video streams in each segment. Default is 1.
a

Set the number of output audio streams, that is also the number of audio streams in each segment. Default is 0.

Adding presets

FFmpeg provides certain presets which are collection of options that provide certain speed to the process. Presets in descending order of speed are: ultrafast,superfast, veryfast, faster, fast, medium, slow, slower, veryslow. The default preset is medium.Utrafast preset is specially useful where command is taking too much time to execute and you want to speed up the process.Example while compressing,fading or reversing large size videos.To use preset just add “-preset”, “ultrafast” to the command.
Example-
String command[] = {“-i”, inputFileAbsolutePath,”-preset”, “ultrafast”, “-vf”, “reverse”, “-af”, “areverse”, outputFileAbsolutePath};

The general guideline is to use the slowest preset that you have patience for.
Please check out here for detailed explanation on choosing a preset.

 

If you like my post please rate it as it will mean a lot to me!

Advertisements

132 thoughts on “FFmpeg Video Editor

    • Hi Omi,

      For merging audio and video where input video file contains audio ,you can use below command-

      String command[] = {"-i",videoFileAbsolutePath,"-i",audioFileAbsolutePath, "-c:v", "copy", "-c:a", "aac","-map", "0:v:0", "-map", "1:a:0","-shortest", destinationAbsolutePath};

      For merging audio and video where input video file does not contain any audio stream ,you can use below command-

      String command[] = {"-i",videoFileAbsolutePath,"-i",audioFileAbsolutePath, "-c:v", "copy", "-c:a", "aac","-shortest", destinationAbsolutePath};

      Like

      • how can we merge video and audio , when audio is shorter , put it in a loop, and change volume of both audio and video file

        Like

      • 1.Get the duration of audio file and video file using MediaMetadataRetriever.
        2.When audio is shorter,calculate how many times we need to concatenate audio so that its duration is equal or more than video.For example if audio is 30 seconds and video is of 2 minutes we need to concatenate audio 4 times.
        3.Run concatenate audio ffmpeg command.
        4.Merge the concatenated audio with video.

        Like

      • String command[] = {“-i”, stringExtra, “-i”, path + “/” + “songs1.mp3”, “-c:v”, “copy”, “-c:a”, “aac”, “-shortest”, stringExtra};

        m10730a(command);

        private void m10730a(final String[] strArr) {
        try {
        this.f6386t.execute(strArr, new ExecuteBinaryResponseHandler() {
        @Override
        public void onStart() {
        super.onStart();
        Log.e(“BHUVNESH”, “Started command : ffmpeg ” + strArr);
        }

        @Override
        public void onProgress(String str) {
        super.onProgress(str);
        Log.e(“BHUVNESH”, “Started command : ffmpeg ” + strArr);
        }

        @Override
        public void onFailure(String str) {
        super.onFailure(str);

        Log.e(“BHUVNESH”, “FAILED with output : ” + str);
        }

        @Override
        public void onFinish() {
        super.onFinish();
        Log.e(“BHUVNESH”, “Finished command : ffmpeg ” + strArr);
        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), “videoffmeg” + “.txt”);
        if (file.exists()) {
        file.delete();
        }
        }

        @Override
        public void onSuccess(String message) {
        super.onSuccess(message);

        Log.e(“BHUVNESH”, “SUCCESS with output : ” + message);
        }

        });
        } catch (Exception e) {
        }
        }

        // tired to do
        audio with video mereg

        Like

      • Hi,Please make sure the path for video and audio file is correct.Please refer to my sample project on github to check how I have got the absolute file path.If problem persist please share the log you are getting inside onFailure.

        Like

      • thnak u for replay….i solve this prob.

        but one more Question please :

        for fad-in and fad-out : String[] command = {“-y”, “-i”, file.getAbsolutePath(), “-acodec”, “copy”, “-vf”, “fade=t=in:st=0:d=5,fade=t=out:st=” + String.valueOf((total_image * 3 )- 5) + “:d=5”, file1.getAbsolutePath()};

        3 => 3sec
        file.getAbsolutePath() => input Video path
        file1.getAbsolutePath() => output path

        but cant to create fad in and fad out video.
        please help me.
        thanku.

        Like

      • // fad-in and fad-out // String[] command = {“-y”, “-i”, file.getAbsolutePath(), “-acodec”, “copy”, “-vf”, “fade=t=in:st=0:d=5,fade=t=out:st=” + String.valueOf((Share.size_of_images * 3) – 5) + “:d=5”, file1.getAbsolutePath()};

        Share.size_of_images => total image (ex : 10 images)
        3 => 3sec
        file.getAbsolutePath() => input Video path
        file1.getAbsolutePath() => output path

        -> not getting any error in onFailure but fad in and fade out transition effect not display.
        only play simple video.

        ///////////////////////////////////// log //////////////////////////////////////////////////
        SUCCESS with output : ffmpeg version n3.0.1 Copyright (c) 2000-2016 the FFmpeg developers
        built with gcc 4.8 (GCC)
        configuration: –target-os=linux –cross-prefix=/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/bin/arm-linux-androideabi- –arch=arm –cpu=cortex-a8 –enable-runtime-cpudetect –sysroot=/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/sysroot –enable-pic –enable-libx264 –enable-libass –enable-libfreetype –enable-libfribidi –enable-libmp3lame –enable-fontconfig –enable-pthreads –disable-debug –disable-ffserver –enable-version3 –enable-hardcoded-tables –disable-ffplay –disable-ffprobe –enable-gpl –enable-yasm –disable-doc –disable-shared –enable-static –pkg-config=/home/vagrant/SourceCode/ffmpeg-android/ffmpeg-pkg-config –prefix=/home/vagrant/SourceCode/ffmpeg-android/build/armeabi-v7a –extra-cflags=’-I/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/include -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fstack-protector-all’ –extra-ldflags=’-L/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/lib -Wl,-z,relro -Wl,-z,now -pie’ –extra-libs=’-lpng -lexpat -lm’ –extra-cxxflags=
        libavutil 55. 17.103 / 55. 17.103
        libavcodec 57. 24.102 / 57. 24.102
        libavformat 57. 25.100 / 57. 25.100
        libavdevice 57. 0.101 / 57. 0.101
        libavfilter 6. 31.100 / 6. 31.100
        libswscale 4. 0.100 / 4. 0.100
        libswresample 2. 0.101 / 2. 0.101
        libpostproc 54. 0.100 / 54. 0.100
        Input #0, mov,mp4,m4a,3gp,3g2,mj2, from ‘/storage/emulated/0/Movies/slideshow_video.mp4’:
        Metadata:
        major_brand : isom
        minor_version : 512
        compatible_brands: isomiso2avc1mp41
        encoder : Lavf57.25.100
        Duration: 00:00:18.04, start: 0.000000, bitrate: 206 kb/s
        Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuvj420p(pc), 1280×720 [SAR 3206:3205 DAR 51296:28845], 205 kb/s, SAR 16032:16027 DAR 85504:48081, 0.33 fps, 1 tbr, 12800 tbn, 50 tbc (default)
        Metadata:
        handler_name : VideoHandler
        No pixel format specified, yuvj420p for H.264 encoding chosen.
        Use -pix_fmt yuv420p for compatibility with outdated media players.
        [libx264 @ 0xb7ce2d00] using SAR=3206/3205
        [libx264 @ 0xb7ce2d00] using cpu capabilities: none!
        [libx264 @ 0xb7ce2d00] profile High, level 3.1
        [libx264 @ 0xb7ce2d00] 264 – core 148 – H.264/MPEG-4 AVC codec – Copyleft 2003-2015 – http://www.videolan.org/x264.html – options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=1 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
        Output #0, mp4, to ‘/storage/emulated/0/Movies/slideshow_videoAB.mp4’:
        Metadata:
        major_brand : isom
        minor_version : 512
        compatible_brands: isomiso2avc1mp41
        encoder : Lavf57.25.100
        Stream #0:0(und): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuvj420p(pc), 1280×720 [SAR 16032:16027 DAR 85504:48081], q=-1–1, 1 fps, 16384 tbn, 1 tbc (default)
        Metadata:
        handler_name : VideoHandler
        encoder : Lavc57.24.102 libx264
        Side data:
        unknown side data type 10 (24 bytes)
        Stream mapping:
        Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
        Press [q] to stop, [?] for help
        frame= 19 fps=0.0 q=0.0 size= 0kB time=00:00:00.00 bitrate=N/A dup=13 drop=0 speed= 0x
        frame= 20 fps=4.3 q=-1.0 Lsize= 364kB time=00:00:18.00 bitrate= 165.6kbits/s dup=14 drop=0 speed=3.89x
        video:363kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.293044%
        [libx264 @ 0xb7ce2d00] frame I:5 Avg QP: 4.94 size: 74065
        [libx264 @ 0xb7ce2d00] frame
        01-04 15:42:36.924 19059-19059/com.swiitt.pixgram E/BHUVNESH: Finished command : ffmpeg [Ljava.lang.String;@4ed8215

        Like

      • Check ‘(Share.size_of_images * 3) – 5’…It should be the time from where you want to start fade out effect.For example if you want to fade out last 5 seconds of video then ‘totalDuration -5’ should be the starting time for fadeout

        Liked by 1 person

      • (Share.size_of_images * 3) – 5 same thing ‘totalDuration -5’
        ex :
        Share.size_of_images = 10 images.
        now : (10 * 3sec) – 5 = 25
        or
        totalDuration – 5 = 25

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        first i am create video using multiple images like :

        new String[]{“-y”, “-f”, “concat”, “-safe”, “0”, “-i”, file2.getAbsolutePath(), “-preset”, “ultrafast”, “-vsync”, “vfr”, “-vf”, “scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2”, file.getAbsolutePath()}

        after try to add fade in and fade out in created video

        String[] command = {“-y”, “-i”, file.getAbsolutePath(), “-acodec”, “copy”, “-vf”, “fade=t=in:st=0:d=5,fade=t=out:st=” + String.valueOf((Share.size_of_images * 3) – 5) + “:d=5”, file1.getAbsolutePath()};

        or

        at a time create video with audio with effect ? possible or not ?

        Like

      • Are you running multiple commands at a same time or one command in response of another?Are you running both merging audio with video and adding fading effect commands at same time with same destination file?

        Like

    • You can use below command to create a slow motion video removing audio from original video-

      String[] complexCommand = {"-y", "-i", inputFileAbsolutePath,"-an", "-filter:v", "setpts=2.0*PTS", "-b:v", "2097k", "-r", "60", "-vcodec", "mpeg4", outputFileAbsolutePath}

      Here -an removes audio

      Liked by 1 person

  1. Hi, How can i combine two commands to run one after the other before getting the output file. I have a working code for cutting a video and a separate code for decreasing speed, but i want them to run together so that when the command is invoked, a selected section of the video is cut and then its speed reduced before saving the final output.

    Also is there a code to convert video to gif format using ffmpeg?

    Thanks for your response in advance.

    Like

  2. Hello!
    What is the best way to compress the video? What parameters should I use?
    I tried to do it your way and I can’t open the file when I search it in my phone. I get Cannot play video…..Unsupported file type

    Code:
    String[] command = {“-y”, “-i”, filePath, “-s”, “640×480”, “-r”, “25”, “-vcodec”,
    “mpeg4”, “-b:v”, “150k”, “-b:a”, “48000”, “-ac”, “2”, “-ar”, “22050”, compressedFilePath};
    executeFFmpegBinary(command);

    Liked by 1 person

    • You cant do anything about that.. i searched about that… But you can add in string this “-preset”, “ultrafast”
      this will make conversion a lot faster!!

      Liked by 1 person

    • To speed up video 4x times use-

      [0:v]setpts=0.25*PTS[v];[0:a]atempo=2.0[2a];[2a]atempo=2.0[4a]

      The atempo filter is limited to using values between 0.5 and 2.0 (so it can slow it down to no less than half the original speed, and speed up to no more than double the original speed in single atempo filter). To get around this limitation we need to use multiple atempo filter.

      Similarly to speed up video 3x times use-

      [0:v]setpts=0.33*PTS[v];[0:a]atempo=2.0[2a];[2a]atempo=1.5[3a]

      Remember to change -map option accordingly.
      Example-

      String[] complexCommand = {"-y", "-i", inputFileAbsolutePath, "-filter_complex", "[0:v]setpts=0.33*PTS[v];[0:a]atempo=2.0[2a];[2a]atempo=1.5[3a]", "-map", "[v]", "-map", "[3a]", "-b:v", "2097k", "-r", "60", "-vcodec", "mpeg4", outputFileAbsolutePath};

      Now you can calculate for 5x times!

      Like

  3. I’m currently using your FFmpeg-Video-Editor-Android-master Application, I’d like to know i could change the complexCommand such that i can extract every frame image from the last 45 frames of a 30fps video.

    Current Complex Command:
    String[] complexCommand = {“-y”, “-i”, yourRealPath, “-an”, “-r”, “1/2”, “-ss”, “” + startMs / 1000, “-t”, “” + (endMs – startMs) / 1000, dest.getAbsolutePath()};

    Like

    • Remove “-r”, “1/2” if you want to extract all video frames as images.Since your video is 30 fps video and you want to extract last 45 frames..that means you want to extract all frames of last 1.5 second video(1500 milliseconds).So ,your startMs should be equal to total duration of video in milliseconds – 1500 milliseconds and endMs should be equal to total duration of video in milliseconds.

      Like

  4. unable to use backpress with ffmpeg

    when use this code in an activity and the ffmpeg.execute() is called it disables onBackPressed() , since there is a progress dialog and it is set to alog.setCancelable(false); there is no way to stop the command

    ffmpeg can be disabled

    this is the command I am trying

    @Override
    public void onBackPressed() {
    Toast.makeText(videStickerTryAct.this, “back press”, Toast.LENGTH_SHORT).show();

    if(ffmpeg!= null) {
    if (ffmpeg.isFFmpegCommandRunning()) {
    ffmpeg.killRunningProcesses();
    }
    if (progressDialog!= null)
    {
    progressDialog.cancel();
    }
    }
    }

    but back press is not called at all?

    Liked by 1 person

    • Set

      progressDialog.setCancelable(true)

      if you want to dismiss dialog on backpress while command is running.Use

      progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                  @Override
                  public void onCancel(DialogInterface dialog) {
                      if(ffmpeg.isFFmpegCommandRunning())
                      ffmpeg.killRunningProcesses();
                  }
              });
      

      to kill running processes while dismissing dialog.

      Like

  5. unable to use backpress with ffmpeg

    when use this code in an activity and the ffmpeg.execute() is called it disables onBackPressed() , since there is a progress dialog and it is set to alog.setCancelable(false); there is no way to stop the command

    ffmpeg can be disabled

    this is the command I am trying

    @Override
    public void onBackPressed() {
    Toast.makeText(tryer.this, “back press”, Toast.LENGTH_SHORT).show();

    if(ffmpeg!= null) {
    if (ffmpeg.isFFmpegCommandRunning()) {
    ffmpeg.killRunningProcesses();
    }
    if (progressDialog!= null)
    {
    progressDialog.cancel();
    }
    }
    }

    but back press is not called at all?

    Like

    • Set

      progressDialog.setCancelable(true)

      if you want to dismiss dialog on backpress while command is running.Use

      progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                  @Override
                  public void onCancel(DialogInterface dialog) {
                      if(ffmpeg.isFFmpegCommandRunning())
                      ffmpeg.killRunningProcesses();
                  }
              });
      

      to kill running processes while dismissing dialog.

      Like

      • unfortuantely there is an error in the writingminds code according to this (there is no proper support aswell, they updated the code but not the gradle, giving out old code instead )

        https://github.com/WritingMinds/ffmpeg-android-java/issues/79

        I downlaoded and tried the writingmids code as normal android files, but It gives me error of device not supported, any idea how we can use the JNI , Obj and Libs that they have provided, in our code directly (I mean just download the code and build an app with it, like we do with other projects on github, instead of using gradle )

        Liked by 1 person

    • Use below command to create video from images placed in same folder

      String command[]={"-y", "-r","1/5" ,"-i",src.getAbsolutePath(),
          "-c:v","libx264","-vf", "fps=25","-pix_fmt","yuv420p", dest.getAbsolutePath()};

      Here ,

      src.getAbsolutePath() is the absolute path of all your input images.

      For example,
      If all your images are stored in Images folder inside Pictures directory with names
      **extract_picture001.jpg,extract_picture002.jpg,extract_picture003.jpg……**

      .
      Then,

          String filePrefix = "extract_picture";
          String fileExtn = ".jpg";
          File picDir = Environment.getExternalStoragePublicDirectory(
          Environment.DIRECTORY_PICTURES);
          File dir = new File(picDir, "Images");
          File src = new File(dir, filePrefix + "%03d" + fileExtn);
      

      For creating video from images placed in different folder you
      have to create a text file and add image paths to it and then specify
      the path of that text file as an input option.
      Example,

      Text File

          file '/storage/emulated/0/DCIM/Camera/P_20170807_143916.jpg'
          duration 2
          file '/storage/emulated/0/DCIM/Pic/P_20170305_142948.jpg'
          duration 5
          file '/storage/emulated/0/DCIM/Camera/P_20170305_142939.jpg'
          duration 6
          file '/storage/emulated/0/DCIM/Pic/P_20170305_142818.jpg'
          duration 2
      

      Command

          String command[] = {"-y", "-f", "concat", "-safe", "0", "-i", textFile.getAbsolutePath(), "-vsync", "vfr", "-pix_fmt", "yuv420p", dest.getAbsolutePath()};
      

      where textFile.getAbsolutePath() is the absolute path of your text file

      After video is created you can use merge audio and video command which i previously posted in a comment to add audio to it.

      Like

  6. Hi,
    Thanks a lot’s for posting this tutorial it’s very useful for me.One more things i want to create video from images with effects and Audio so what is the command for that.

    Like

    • Use below command to create video from images placed in same folder

      String command[]={"-y", "-r","1/5" ,"-i",src.getAbsolutePath(),
          "-c:v","libx264","-vf", "fps=25","-pix_fmt","yuv420p", dest.getAbsolutePath()};

      Here ,

      src.getAbsolutePath() is the absolute path of all your input images.

      For example,
      If all your images are stored in Images folder inside Pictures directory with names
      **extract_picture001.jpg,extract_picture002.jpg,extract_picture003.jpg……**
      Then,

          String filePrefix = "extract_picture";
          String fileExtn = ".jpg";
          File picDir = Environment.getExternalStoragePublicDirectory(
          Environment.DIRECTORY_PICTURES);
          File dir = new File(picDir, "Images");
          File src = new File(dir, filePrefix + "%03d" + fileExtn);
      

      For creating video from images placed in different folder you
      have to create a text file and add image paths to it and then specify
      the path of that text file as an input option.
      Example,

      Text File

          file '/storage/emulated/0/DCIM/Camera/P_20170807_143916.jpg'
          duration 2
          file '/storage/emulated/0/DCIM/Pic/P_20170305_142948.jpg'
          duration 5
          file '/storage/emulated/0/DCIM/Camera/P_20170305_142939.jpg'
          duration 6
          file '/storage/emulated/0/DCIM/Pic/P_20170305_142818.jpg'
          duration 2
      

      Command

          String command[] = {"-y", "-f", "concat", "-safe", "0", "-i", textFile.getAbsolutePath(), "-vsync", "vfr", "-pix_fmt", "yuv420p", dest.getAbsolutePath()};
      

      where textFile.getAbsolutePath() is the absolute path of your text file

      After video is created you can use merge audio and video command which i previously posted in a comment to add audio to it.

      Like

  7. Thanks a lot for building this. Had a veryyy Hard time to find some new & fresh implementation of FFMpeg – Android.. You Saved my life. I have a Nougat device for which I had to modify the gradle and after that everything works like a charm.

    Liked by 1 person

  8. Hi!
    Thanks a lot for posting this tutorial it’s very useful for me 🙂 ı have a question,I want to shred a video in 10 seconds and I should record them.
    Please help me, thank you 🙂

    Like

    • By what I understand you want to replace audio of a recorded video.

      For replacing audio of video with another audio ,you can use below command-

      String command[] = {"-i",videoFileAbsolutePath,"-i",audioFileAbsolutePath, "-c:v", "copy", "-c:a", "aac","-map", "0:v:0", "-map", "1:a:0","-shortest", destinationAbsolutePath};

      The -shortest option will make output of the same duration as the shortest input.

      You can customize the command as per your requirement.

      Like

      • For segmenting video, you can use below command-

        String[] complexCommand = {"-i", inputFileAbsolutePath, "-c:v", "libx264", "-crf", "22", "-map", "0", "-segment_time", "10", "-g", "9", "-sc_threshold", "0", "-force_key_frames", "expr:gte(t,n_forced*10)", "-f", "segment", dest.getAbsolutePath()};

        Please go thorugh my sample project code at below link and check out splitVideoCommand() method where I have segmented video.You can do in same way.

        https://github.com/bhuvnesh123/FFmpeg-Video-Editor-Android/blob/master/app/src/main/java/videoeditor/bhuvnesh/com/ffmpegvideoeditor/activity/MainActivity.java

        Like

      • With this command, cant able to have video audio. Means audio file overriding the video audio. Actually, i m trying to background music to video which is having audio. What exact output i need is have to get both audio’s(background music and video audio) but i m getting only background music. Can you help me what is happening here.

        Like

      • Use below command to add audio as background music to video keeping video’s audio-

        String[] complexCommand = {"-i",audioFileAbsolutePath, "-i", videoFileAbsolutePath, "-filter_complex","[0:a][1:a]amerge,pan=stereo:c0<c0+c2:c1<c1+c3[out]","-map", "1:v", "-map", "[out]" ,"-c:v", "copy", "-c:a", "aac", "-shortest", outputFileAbsolutePath};

        Liked by 1 person

      • String[] complexCommand = {“-i”,audioFileAbsolutePath, “-i”, videoFileAbsolutePath, “-filter_complex”,”[0:a][1:a]amerge,pan=stereo:c0<c0+c2:c1<c1+c3[out]","-map", "1:v", "-map", "[out]" ,"-c:v", "copy", "-c:a", "aac", "-shortest", outputFileAbsolutePath};

        This command working for to keep both audio's(video's audio and background music). But, If i dont have any audio stream to video, am getting error like

        Stream specifier ':a' in filtergraph description [0:a][1:a]amerge,pan=stereo:c0<c0+c2:c1<c1+c3[out] matches no streams.(This error especially raising when i concat images into video and adding background music to this video). So, How to achieve for both cases(with audio stream and without audio stream).

        Like

      • Now that you know how to handle both the cases individually, I would like you to do some homework and figure out how to handle both cases together which will be good for your understanding and learning

        Like

  9. Oh well i work a lot with ffmpeg lately.. one thing that bothers me and cant really fix yet is that when proccess is running (ffmpeg cutting or etc.) if i close app from recents.. it doesnt clear any data or whatever.. and when i go to do an edit again it doesnt really work.. i really think the problem is in the data that dont clear..
    if someone can help me it would be great

    Like

    • Whenever you create destination file,do check if a file with same name and extension at same path already exists and if same file is already there then either delete that old file first or name the new file in such a way that no other file with same name exists at that path as done in my sample project.Secondly,inside onpause and onstop you can check if your application/activity is being destroyed and in that case if your process is not yet completed delete the destination file which you created since your process is incomplete and getting destroyed.

      Like

  10. Hi,
    I am getting error “call requires API level19(current min is 19) :android .provider.DocumentsContract.isDocumentUri” in getPath function.
    please help me.

    Like

    • I hope by combine music u mean to concatenate music.To concatenate audio with another audio use below command-

      String command[] = {"-i",inputAudioFileAbosolutePath1,"-i",inputAudioFileAbsolutePath2,"-filter_complex","[0:0] [1:0]concat=n=2:v=0:a=1[out]","-map","[out]",outputFileAbsolutePath()};

      For merging resultant audio with video where input video file does not contain any audio stream ,you can use below command-

      String command[] = {"-i",videoFileAbsolutePath,"-i",audioFileAbsolutePath, "-c:v", "copy", "-c:a", "aac","-shortest", destinationAbsolutePath};

      Here, -shortest is for finishing encoding when the shortest input stream ends.

      Like

      • Thanks for your help! I didn’t properly describe what I meant:
        1. I split video into audio and silent video,and then combine audio and other music(The music time is greater than 3 minutes),
        2. Combine the above silent video with the first step Synthesized audio.

        Thanks a lot!

        Like

      • Point 1 can be achieved by extracting audio from video(command shared on blog post) and then concatenate extracted audio with music.To create silent video you can disable audio recording using -an as done in some commands on my blog post.
        Point 2 can be achieved by merging resultant audio with resultant video.

        Like

  11. Hello Can you please help me with the command to remove audio from a video also can you provide link to resource where i can understand about the parameters of ffmpeg command

    Like

  12. Also FFMPEG takes a lot of processing time , whereas i can see with some app on the play store these tasks are done in 1/10th of the time FFMPEG is taking , can you please let me know how may i increase the performance of my app while using FFMPEG or is there any other alternative for the same ,
    thanks in advance.

    Like

    • FFmpeg provides certain presets which are collection of options that provide certain speed to the process. Presets in descending order of speed are: ultrafast,superfast, veryfast, faster, fast, medium, slow, slower, veryslow. Utrafast preset is specially useful where command is taking too much time to execute and you want to speed up the process.Please check out below link for detailed explanation on choosing a preset-
      https://trac.ffmpeg.org/wiki/Encode/H.264

      Like

  13. When I tried to use your code to make a video from images, i got the error CANNOT LINK EXECUTABLE, has text relocations. Did you come across this error and how did you solve it

    Like

  14. Hii after searching 1 week i find this guide of ffmpeg and successfully accomplish my task. thank you very much. but i stuck in one command. i want to draw text on video but its gives me error `Error initializing filter ‘drawtext’ with args ‘text=Stack Overflow`
    im using this command:

    >{“-i”,g,”-vf drawtext=’text=Stack Overflow: fontcolor=white: fontsize=24: box=1: boxcolor=black@0.5: \boxborderw=5: x=(w-text_w)/2: y=(h-text_h)/2’ -codec:a copy”,f}

    in terminal its successfully generated the video output but when i tried in android studio by concatinating then it gives error.
    Please can you tell me the command to draw text on video so that i use that in this project, im waiting for your help..thank you!!

    Like

      • yes i have achieved. thank you very much . i had gone through so many tutorials, nobody explained as you . loved your coding standard .
        I have another question i have one URL something like this “http://viraltube.co.in/vt/zbVideo.mp4”. How can i use it for video editing ? i am not suppose to download , is there any possibilities to achieve?

        Like

      • Yes,you can use ffmpeg with url.You have to specify url as an input option.
        For example-

        String[] complexCommand = {"-y", "-i", "http://viraltube.co.in/vt/zbVideo.mp4", "-s", "320x240", "-r", "25", "-vcodec", "mpeg4", "-b:v", "150k", "-b:a", "48000", "-ac", "2", "-ar", "22050", outputFileAbsolutePath};

        Liked by 1 person

  15. Hi,
    I have to merge 5 videos.
    1. Intro.mp4
    2.capture_video_cut1.mp4
    3.capture_video_cut2.mp4
    4.capture_video_cut3.mp4
    5.last.mp4
    The total duration of merge output is 30 seconds.
    And at the end of the video, I want to display 3 videos in parallel(2,3,4).
    And I also want to add a caption to the video.
    Could you please any guide?
    Thanks!

    Like

      • Thanks for the reply , i checked the comment and got it but unable to get exact result
        i am creating video using two images
        String originalPath= “file “+”‘”+picturePath1+”‘”+”\n”+ “duration 3 \n”+”file “+”‘”+picturePath2+”‘”+”\n”+ “duration 3”;
        File myFile= generateTextFile(“MyTextFile”,originalPath); // here i convert into text file
        After that executing command
        String command[] = {“-y”, “-f”, “concat”, “-safe”, “0”, “-i”,
        myFile.getAbsolutePath(), “-vsync”, “vfr”, “-pix_fmt”, “yuv420p”, VideoSavePath};

        successfully creating video but showing one image for long time and another one just blinking sometime

        Like

      • Due to a quirk, the last image has to be specified twice – the 2nd time without any duration directive.
        So it should be String originalPath= “file “+”‘”+picturePath1+”‘”+”\n”+ “duration 3 \n”+”file “+”‘”+picturePath2+”‘”+”\n”+ “duration 3 \n”+”file “+”‘”+picturePath2+”‘”;

        Liked by 1 person

    • Creating video from images and concatenating video with another video has already been discussed in comments section.Now that you know how to handle both the cases individually, I would like you to do some homework and figure out how to handle both cases together which will be good for your understanding and learning.

      Liked by 1 person

  16. String[] cmd1={“-i”, yourRealPath_s ,”-i”, img_path ,”-i”, img_path2,”-filter_complex”,”overlay=x=-16:y=H-h-300,overlay=x=W-w-16:y=H-h-10″,filePath};
    How to add first image on top center and second image at bottom center by changing overlay

    Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s