10

I have made an imageView animate from one side to the other side of the screen. Here is the java code:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ImageView imageView = findViewById(R.id.imageView);
        Button button = findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                handleAnimation(imageView);
            }
        });
    }
    public void handleAnimation(View view) {
        ObjectAnimator animatorX = ObjectAnimator.ofFloat(view, "x", 1000f);
        animatorX.setDuration(2000);
        animatorX.start();
    }
}

And this is what we see when user clicks on the ANIMATE button: enter image description here

Now my question is that how I can make a video file by capturing the animated imageView ?

EDIT:

What I need is: I want to make an app which takes some photos from the user and make some animations on the photos and some effects and also mix them with a desired sound and at the end exports a video clip. And of course if I can I would rather make all these things hidden.

Community
  • 1
  • 1
Hossein Seifi
  • 1,380
  • 11
  • 29

2 Answers2

6

You have to record your screen and then crop the video using your view's xy coordinates. You can record your screen using the MediaProject API on android (5) and above.

 private VirtualDisplay mVirtualDisplay;
    private MediaRecorder mMediaRecorder;
    private MediaProjection mMediaProjection;
    private MediaProjectionCallback callback;

 MediaProjectionManager projectionManager = (MediaProjectionManager) 
        context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        mMediaProjection.registerCallback(callback, null);
        initRecorder();
        mMediaRecorder.prepare();
        mVirtualDisplay = createVirtualDisplay();
        mMediaRecorder.start();


public void initRecorder() {
        path = "/sdcard/Record/video" + ".mp4";
        recId = "capture-" + System.currentTimeMillis() + ".mp4";
        File myDirectory = new File(Environment.getExternalStorageDirectory(), "Record");

            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            mMediaRecorder.setVideoEncodingBitRate(MainFragment.bitRate);          
            mMediaRecorder.setVideoFrameRate(30);
            mMediaRecorder.setVideoSize(MainFragment.DISPLAY_WIDTH,
            MainFragment.DISPLAY_HEIGHT);
            mMediaRecorder.setOutputFile(path);
    }


    private VirtualDisplay createVirtualDisplay() {
        return mMediaProjection.createVirtualDisplay("MainActivity",
                MainFragment.DISPLAY_WIDTH, MainFragment.DISPLAY_HEIGHT, MainFragment.screenDensity,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                mMediaRecorder.getSurface(), null /*Callbacks*/, null /*Handler*/);
    }

public class MediaProjectionCallback extends MediaProjection.Callback {
        @Override
        public void onStop() {
            mMediaRecorder.stop();
            // mMediaRecorder.reset();
            mMediaRecorder.release();
            mMediaProjection.unregisterCallback(callback);
            mMediaProjection = null;
            mMediaRecorder = null;
        }

Once done simply call mMediaProjection.stop() to finish the recording and save the video as tmp After which you can crop the video at the xy coordinates that your view is position using FFmpeg

ffmpeg -i in.mp4 -filter:v "crop=out_w:out_h:x:y" out.mp4

Where the options are as follows:

out_w is the width of the output rectangle

out_h is the height of the output rectangle

x and y specify the top left corner of the output rectangle

so in your case

String cmd ="-i '"+ tmpVideoPath+"' -filter:v "+"'crop="+view.getWidth()+":"+view.getHeight()+":"+view.getX()+":"+view.getY()+"'"+" -c:a copy "+outVideoPath
FFmpeg ffmpeg = FFmpeg.getInstance(context);
  // to execute "ffmpeg -version" command you just need to pass "-version"
ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {

    @Override
    public void onStart() {}

    @Override
    public void onProgress(String message) {}

    @Override
    public void onFailure(String message) {}

    @Override
    public void onSuccess(String message) {}

    @Override
    public void onFinish() {}

});
Niza Siwale
  • 2,390
  • 1
  • 18
  • 20
  • Thank you. But this is not what I need. I want to record a particular layout with its all child views as the same size as device's screen. So this way I can omit the other views. – Hossein Seifi Jul 05 '18 at 13:46
  • What do you mean? – Niza Siwale Jul 05 '18 at 14:07
  • 1
    Why can't you simply change the alpha of those other views – Niza Siwale Jul 05 '18 at 14:08
  • Or you can change the location where you crop the video from – Niza Siwale Jul 05 '18 at 14:08
  • What I need is: I want to make an app which takes some photos from the user and make some animations on the photos and some effects and also mix them with a desired sound and at the end exports a video clip. And of course if I can I would rather make all these things hidden. – Hossein Seifi Jul 07 '18 at 11:05
  • You should have mentioned that beforehand. You can create animations from images using `FFmpeg`. As you haven't mentioned what kind of animations you want to create, you can start here https://superuser.com/questions/833232/create-video-with-5-images-with-fadein-out-effect-in-ffmpeg – Niza Siwale Jul 07 '18 at 11:55
  • No, those are `FFmpeg` commands you can execute them in Java using the wrapper I posted in the answer. PS what you're looking for is called a photo montage and not animation. You can Google how to create different types of montages in FFmpeg – Niza Siwale Jul 10 '18 at 18:55
0

There are two possible approaches to archive this.

1- You can acchive this by using the javacv library (FFmpeg) to combine a set of bitmaps taken from the view

FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("/sdcard/test.mp4",256,256);
try {
    recorder.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4);
    recorder.setFormat("mp4");
    recorder.setFrameRate(30);
    recorder.setPixelFormat(avutil.PIX_FMT_YUV420P10);
    recorder.setVideoBitrate(1200);
    recorder.startUnsafe();
    for (int i=0;i< 5;i++)
    {
        view.setDrawingCacheEnabled(true);
        Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
        view.setDrawingCacheEnabled(false);
        recorder.record(bitmap);
    }
    recorder.stop();
}
catch (Exception e){
    e.printStackTrace();
}  

all the code of using this library is here

2- You can use this link for record the screen and use as per your need.
Screen Recorder

Maraj Hussain
  • 1,580
  • 10
  • 26
  • Thank you. As I want to capture just the image's animation and not all the views, so I think I should use the first approach. But I don't know how to integrate FFmpeg library into android studio. Would you help me please – Hossein Seifi Jun 29 '18 at 14:04
  • I see that link, but I understand nothing!! – Hossein Seifi Jun 29 '18 at 14:10
  • This won't work well as you are doing everything on the main thread. Your video will appear laggy as the drawing cache isn't drawn every second – Niza Siwale Jul 01 '18 at 09:33
  • @ Niza Siwale You are right. Have any idea for solving my problem? – Hossein Seifi Jul 02 '18 at 21:14
  • The problem with screen recording is the app has to be in foreground and the whole animation has to be played. Lets say if you want to download it as video and put the app in background, this might not work, depends on usecase thoe. – Praveen Pandey Nov 26 '19 at 06:09