Ketan Patel
Ketan Patel

Reputation: 2215

How to add filter on video in android..?

How to add filtering on video while recording and after saved too in android..?

mediaRecorder = new MediaRecorder();

mCamera.unlock();
mediaRecorder.setCamera(mCamera);

mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

mediaRecorder.setProfile(
    CamcorderProfile.get(CamcorderProfile.QUALITY_LOW)
);
mediaRecorder.setVideoEncodingBitRate(6000000);

demoVideoFolder = Environment.getExternalStorageDirectory().getAbsolutePath() + "/videokit/";
demoVideoPath = demoVideoFolder + "in.mp4";

File storagePath2 = new File(demoVideoFolder);
storagePath2.mkdir();

mediaRecorder.setOutputFile("/sdcard/videokit/in.mp4");
rotateBackVideo(mediaRecorder);

try {
    mediaRecorder.prepare();
} catch (IllegalStateException e) {
    releaseMediaRecorder();    
} catch (IOException e) {
    releaseMediaRecorder();    
}

I want to add multiple filter in my video while recording using MediaRecorder and also add filter after saved video. How can achieved second scenario..?

Upvotes: 0

Views: 5714

Answers (2)

Ketan Patel
Ketan Patel

Reputation: 2215

public class CameraPreview1 extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
    String filter_effect;

    public CameraPreview1(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        try {
            // create the surface and start camera preview
            if (mCamera == null) {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            }
        } catch (IOException e) {
            Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    @SuppressWarnings("deprecation")
    public void refreshCamera(Camera camera,String effect) {
        filter_effect=effect;
        if (mHolder.getSurface() == null) {
            // preview surface does not exist
            return;
        }
        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            // ignore: tried to stop a non-existent preview
        }
        // set preview size and make any resize, rotate or
        // reformatting changes here
        // start preview with new settings
        setCamera(camera);
        try {
            Camera.Parameters params = mCamera.getParameters();
            if(filter_effect.equals("none"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_NONE);
            }
            else if(filter_effect.equals("mono"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_MONO);
            }
            else if(filter_effect.equals("negative"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_NEGATIVE);
            }
            else if(filter_effect.equals("solarize"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_SOLARIZE);
            }
            else if(filter_effect.equals("sepia"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_SEPIA);
            }
            else if(filter_effect.equals("posterize"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_POSTERIZE);
            }
            else if(filter_effect.equals("whiteboard"))
            {
               params.setColorEffect(Camera.Parameters.EFFECT_WHITEBOARD);
            }
            else if(filter_effect.equals("blackboard"))
            {
                params.setColorEffect(Camera.Parameters.EFFECT_BLACKBOARD);
            }
            else if(filter_effect.equals("aqua"))
            {
                params.setColorEffect(Camera.Parameters.EFFECT_AQUA);
            }
            mCamera.setParameters(params);
            mCamera.setPreviewDisplay(mHolder);

            mCamera.setDisplayOrientation(90);
            mCamera.startPreview();
        } catch (Exception e) {
            Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

        refreshCamera(mCamera,filter_effect);
    }

    public void setCamera(Camera camera) {
        //method to set a camera instance
        mCamera = camera;
         Camera.Parameters params = camera.getParameters();
            if (params.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            } else {
                //Choose another supported mode
            }
            camera.setParameters(params);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        // mCamera.release();

    }
}


Class mainActivity

package com.wlc.primetime.camera;

import io.vov.utils.Log;

import java.io.File;
import java.io.IOException;

//import com.google.android.gms.internal.lv;
import com.netcompss.ffmpeg4android.GeneralUtils;
import com.netcompss.ffmpeg4android.Prefs;
import com.netcompss.loader.LoadJNI;
import com.wlc.primetime.R;
import com.wlc.primetime.Events.EventCreateActivity;
import com.wlc.primetime.Events.EventDetailActivity;
import com.wlc.primetime.campus.PostMemoriesActivity2;
import com.wlc.primetime.campus.PostMemoriesActivity3;
import com.wlc.primetime.utils.Common;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.provider.MediaStore;
import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;

public class main_activity extends Activity implements OnClickListener {
    private Camera mCamera;
    private CameraPreview1 mPreview;
    private MediaRecorder mediaRecorder;
    private Button capture, switchCamera;
    private Context myContext;
    private LinearLayout cameraPreview;
    private boolean cameraFront = false;
    RadioGroup rg_filter;
    RadioButton rg_none, rg_mono, rg_negative;
    private TextView tv_appHeader_right = null, tv_timer = null,
            tv_appHeader_left = null, tv_camera_flash = null,
            tv_camera_video = null, tv_camera_capture;
    private ImageView iv_camera_change = null, iv_camera_gallery = null;
    String effect;
    int count = 0;
    Runnable r = null;
    ImageView iv_header_left;
    ImageView iv_appHeader_title;
    String camera_state;
    String workFolder = null;
    String demoVideoFolder = null;
    String demoVideoPath = null;
    String vkLogPath = null;
    private boolean commandValidationFailedFlag = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.video_preview_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        count = 0;
        View customHeaderView = Common
                .getActionBarCustomView(video_preview_post.this);

        iv_header_left = (ImageView) customHeaderView
                .findViewById(R.id.iv_header_left);
        iv_header_left.setImageResource(R.drawable.ic_back);
        iv_header_left.setVisibility(View.VISIBLE);
        iv_header_left.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                finish();
            }
        });

        ImageView iv_header_right = (ImageView) customHeaderView
                .findViewById(R.id.iv_header_right);
        iv_header_right.setImageResource(R.drawable.ic_profile_poster_edit);
        iv_header_right.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

            }
        });

        iv_appHeader_title = (ImageView) customHeaderView
                .findViewById(R.id.iv_header_title);
        iv_appHeader_title.setImageResource(R.drawable.ic_camera_change);
        iv_appHeader_title.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                if (!recording) {
                    int camerasNumber = Camera.getNumberOfCameras();
                    if (camerasNumber > 1) {
                        // release the old camera instance
                        // switch camera, from the front and the back and vice
                        // versa

                        releaseCamera();
                        chooseCamera();
                    } else {
                        Toast toast = Toast.makeText(myContext,
                                "Sorry, your phone has only one camera!",
                                Toast.LENGTH_LONG);
                        toast.show();
                    }
                }

            }
        });

        Intent in = getIntent();
        effect = in.getStringExtra("effect");

        iv_camera_gallery = (ImageView) findViewById(R.id.iv_camera_gallery);

        tv_timer = (TextView) findViewById(R.id.tv_timer);
        tv_camera_capture = (TextView) findViewById(R.id.tv_camera_capture);
        tv_camera_capture.setTextSize(TypedValue.COMPLEX_UNIT_SP, 35);
        tv_camera_video = (TextView) findViewById(R.id.tv_camera_video);
        tv_camera_video.setTextSize(TypedValue.COMPLEX_UNIT_SP, 45);
        // set last taken image from gallery
        setLastTakenImage(iv_camera_gallery);

        iv_camera_gallery.setOnClickListener(this);
        tv_camera_capture.setOnClickListener(this);
        tv_camera_video.setOnClickListener(this);

        Common.setAwasomeFontFamily(this, tv_camera_video);
        Common.setAwasomeFontFamily(this,
                (TextView) findViewById(R.id.tv_camera_capture));

        int screenWidth = Common.getScreenWidth(this);

        cameraPreview = (LinearLayout) findViewById(R.id.camera_preview_ll);

        myContext = this;
        initialize();
    }

    private int findFrontFacingCamera() {
        camera_state = "front";
        int cameraId = -1;
        // Search for the front facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            CameraInfo info = new CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
                cameraId = i;
                cameraFront = true;
                break;
            }
        }
        return cameraId;
    }

    private int findBackFacingCamera() {
        camera_state = "back";
        int cameraId = -1;
        // Search for the back facing camera
        // get the number of cameras
        int numberOfCameras = Camera.getNumberOfCameras();
        // for every camera check
        for (int i = 0; i < numberOfCameras; i++) {
            CameraInfo info = new CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
                cameraId = i;
                cameraFront = false;
                break;
            }
        }
        return cameraId;
    }

    public void onResume() {
        super.onResume();
        if (!hasCamera(myContext)) {
            Toast toast = Toast.makeText(myContext,
                    "Sorry, your phone does not have a camera!",
                    Toast.LENGTH_LONG);
            toast.show();
            finish();
        }
        if (mCamera == null) {
            // if the front facing camera does not exist
            if (findFrontFacingCamera() < 0) {
                Toast.makeText(this, "No front facing camera found.",
                        Toast.LENGTH_LONG).show();
                switchCamera.setVisibility(View.GONE);
            }
            mCamera = Camera.open(findBackFacingCamera());
            mPreview.refreshCamera(mCamera, effect);
        }
    }

    public void initialize() {
        // cameraPreview = (LinearLayout) findViewById(R.id.camera_preview_ll);

        mPreview = new CameraPreview1(myContext, mCamera);
        // mPreview.setRotation(90);
        cameraPreview.addView(mPreview);
    }

    public void chooseCamera() {
        // if the camera preview is the front
        if (cameraFront) {
            int cameraId = findBackFacingCamera();
            if (cameraId >= 0) {
                // open the backFacingCamera
                // set a picture callback
                // refresh the preview

                mCamera = Camera.open(cameraId);
                // mPicture = getPictureCallback();
                mPreview.refreshCamera(mCamera, effect);
            }
        } else {
            int cameraId = findFrontFacingCamera();
            if (cameraId >= 0) {
                // open the backFacingCamera
                // set a picture callback
                // refresh the preview

                mCamera = Camera.open(cameraId);
                // mPicture = getPictureCallback();
                mPreview.refreshCamera(mCamera, effect);
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        // when on Pause, release camera in order to be used from other
        // applications
        releaseCamera();
    }

    private boolean hasCamera(Context context) {
        // check if the device has camera
        if (context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_CAMERA)) {
            return true;
        } else {
            return false;
        }
    }

    boolean recording = false;

    private void releaseMediaRecorder() {
        if (mediaRecorder != null) {
            mediaRecorder.reset(); // clear recorder configuration
            mediaRecorder.release(); // release the recorder object
            mediaRecorder = null;
            mCamera.lock(); // lock camera for later use
        }
    }

    private boolean prepareMediaRecorder() {

        mediaRecorder = new MediaRecorder();

        mCamera.unlock();
        mediaRecorder.setCamera(mCamera);

        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

        mediaRecorder.setProfile(CamcorderProfile
                .get(CamcorderProfile.QUALITY_LOW));
        // mediaRecorder.setVideoEncodingBitRate(690000);
        mediaRecorder.setVideoEncodingBitRate(6000000);
        // mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        // mediaRecorder.setOutputFile("/sdcard/Movie.mp4");

        demoVideoFolder = Environment.getExternalStorageDirectory()
                .getAbsolutePath() + "/videokit/";
        demoVideoPath = demoVideoFolder + "in.mp4";
        // Toast.makeText(getApplicationContext(), ""+demoVideoFolder,
        // 56).show();

        File storagePath2 = new File(demoVideoFolder);
        storagePath2.mkdir();

        mediaRecorder.setOutputFile("/sdcard/videokit/in.mp4");
        rotateBackVideo(mediaRecorder);

        try {
            mediaRecorder.prepare();
        } catch (IllegalStateException e) {
            releaseMediaRecorder();

        } catch (IOException e) {
            releaseMediaRecorder();

        }

        return true;

    }

    private void releaseCamera() {
        // stop and release camera
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }

    private void setLastTakenImage(ImageView iv_gallary_picker) {
        String[] projection = new String[] {
                MediaStore.Images.ImageColumns._ID,
                MediaStore.Images.ImageColumns.DATA,
                MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
                MediaStore.Images.ImageColumns.DATE_TAKEN,
                MediaStore.Images.ImageColumns.MIME_TYPE };
        final Cursor cursor = getApplicationContext().getContentResolver()
                .query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        projection, null, null,
                        MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");

        // Put it in the image view
        if (cursor.moveToFirst()) {
            String imageLocation = cursor.getString(1);
            File imageFile = new File(imageLocation);
            if (imageFile.exists()) {
                Bitmap bm = BitmapFactory.decodeFile(imageLocation);
                iv_gallary_picker.setImageBitmap(bm);
            }
        }
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        if (v.getId() == R.id.tv_camera_video) {
            if (count == 0) {
                iv_header_left.setEnabled(false);
                iv_appHeader_title.setEnabled(false);
                tv_camera_capture.setVisibility(View.GONE);
                iv_camera_gallery.setVisibility(View.GONE);
                tv_camera_video.setTextColor(Color.RED);

                count = 1;
                tv_timer.setVisibility(View.VISIBLE);
                if (count != 11) {
                    tv_timer.setText("00:00:" + count);
                }

                {
                    if (!prepareMediaRecorder()) {
                        Toast.makeText(video_preview_post.this,
                                "Fail in prepareMediaRecorder()!\n - Ended -",
                                Toast.LENGTH_LONG).show();
                        finish();
                    }

                    final Handler handler = new Handler();

                    r = new Runnable() {
                        public void run() {
                            // tv.append("Hello World");
                            Log.d("count" + count, "ok...");
                            if (count > 11) {

                                if (mediaRecorder != null) {

                                    // count=0;01
                                    try {
                                        mediaRecorder.stop(); // stop the
                                                                // recording
                                        releaseMediaRecorder();
                                        handler.removeCallbacks(r);

                                        workFolder = getApplicationContext()
                                                .getFilesDir()
                                                .getAbsolutePath()
                                                + "/";
                                        Log.i(Prefs.TAG,
                                                "workFolder (license and logs location) path: "
                                                        + workFolder);
                                        vkLogPath = workFolder + "vk.log";
                                        Log.i(Prefs.TAG,
                                                "vk log (native log) path: "
                                                        + vkLogPath);

                                        GeneralUtils
                                                .copyLicenseFromAssetsToSDIfNeeded(
                                                        video_preview_post.this,
                                                        workFolder);
                                        GeneralUtils
                                                .copyDemoVideoFromAssetsToSDIfNeeded(
                                                        video_preview_post.this,
                                                        demoVideoFolder);
                                        int rc = GeneralUtils.isLicenseValid(
                                                getApplicationContext(),
                                                workFolder);

                                        if (GeneralUtils
                                                .checkIfFileExistAndNotEmpty(demoVideoPath)) {
                                            new TranscdingBackground(
                                                    video_preview_post.this)
                                                    .execute();
                                        } else {
                                            Toast.makeText(
                                                    getApplicationContext(),
                                                    demoVideoPath
                                                            + " not found",
                                                    Toast.LENGTH_LONG).show();
                                        }

                                    } catch (Exception e) {
                                        // handler.removeCallbacks(r);
                                        // Intent in =new
                                        // Intent(getApplicationContext(),
                                        // PostMemoriesActivity3.class);
                                        // in.putExtra("PATH_MEMORIES_IMG",
                                        // "video");
                                    }

                                }
                            }
                            if (count <= 10) {
                                tv_timer.setText("00:00:" + count);
                            }
                            count++;
                            handler.postDelayed(this, 1000);
                        }
                    };

                    if (count == 1) {
                        mediaRecorder.start();
                    }
                    handler.postDelayed(r, 0);

                    recording = true;
                }
            }
        } else if (R.id.tv_camera_capture == v.getId()) {
            Intent in = new Intent(getApplicationContext(),
                    CameraFragmentActivity.class);
            startActivity(in);
        }
    }

    public MediaRecorder rotateBackVideo(MediaRecorder mMediaRecorder) {

        /**
         * Define Orientation of video in here, if in portrait mode, use value =
         * 90, if in landscape mode, use value = 0
         */

        int rotation = 0;

        if (camera_state.equals("back")) {
            rotation = 0;
            // Toast.makeText(getApplicationContext(), "front", 45).show();
        } else {
            rotation = 180;
            // Toast.makeText(getApplicationContext(), "back", 45).show();
        }

        switch (rotation) {
        case 0:
            mMediaRecorder.setOrientationHint(90);
            break;
        case 90:
            mMediaRecorder.setOrientationHint(180);
            break;
        case 180:
            mMediaRecorder.setOrientationHint(270);
            break;
        case 270:
            mMediaRecorder.setOrientationHint(0);
            break;
        }

        return mMediaRecorder;
    }

    @Override
    public void onBackPressed() {
        // TODO Auto-generated method stub
        Intent in = new Intent(getApplicationContext(),
                CameraFragmentActivity.class);
        finish();
        startActivity(in);

        // super.onBackPressed();
    }

    class TranscdingBackground extends AsyncTask<String, Integer, Integer> {

        ProgressDialog progressDialog;
        Activity _act;

        public TranscdingBackground(Activity act) {
            _act = act;
        }

        @Override
        protected void onPreExecute() {
            progressDialog = new ProgressDialog(_act);
            progressDialog.setMessage("Compressing...");
            progressDialog.show();

        }

        protected Integer doInBackground(String... paths) {
            Log.i(Prefs.TAG, "doInBackground started...");

            // delete previous log
            GeneralUtils.deleteFileUtil(workFolder + "/vk.log");

            PowerManager powerManager = (PowerManager) _act
                    .getSystemService(Activity.POWER_SERVICE);
            WakeLock wakeLock = powerManager.newWakeLock(
                    PowerManager.PARTIAL_WAKE_LOCK, "VK_LOCK");
            Log.d(Prefs.TAG, "Acquire wake lock");
            wakeLock.acquire();

            // /////////// Set Command using code (overriding the UI EditText)
            // /////
            String commandStr = "ffmpeg -y -i /sdcard/videokit/in.mp4 -strict experimental -s 320x240 -r 30 -aspect 3:4 -ab 48000 -ac 2 -ar 22050 -vcodec mpeg4 -b 2097152 /sdcard/videokit/Movie.mp4";// videokit/
            // String[] complexCommand = {"ffmpeg", "-y" ,"-i",
            // "/sdcard/videokit/in.mp4","-strict","experimental","-s",
            // "160x120","-r","25", "-vcodec", "mpeg4", "-b", "150k",
            // "-ab","48000", "-ac", "2", "-ar", "22050",
            // "/sdcard/videokit/out.mp4"};
            // /////////////////////////////////////////////////////////////////////

            LoadJNI vk = new LoadJNI();
            try {

                // complex command
                // vk.run(complexCommand, workFolder, getApplicationContext());

                vk.run(GeneralUtils.utilConvertToComplex(commandStr),
                        workFolder, getApplicationContext());
                GeneralUtils.copyFileToFolder(vkLogPath, demoVideoFolder);

            } catch (Throwable e) {
                Log.e(Prefs.TAG, "vk run exeption.", e);
            } finally {
                if (wakeLock.isHeld())
                    wakeLock.release();
                else {
                    Log.i(Prefs.TAG,
                            "Wake lock is already released, doing nothing");
                }
            }
            Log.i(Prefs.TAG, "doInBackground finished");
            return Integer.valueOf(0);
        }

        protected void onProgressUpdate(Integer... progress) {
        }

        @Override
        protected void onCancelled() {
            Log.i(Prefs.TAG, "onCancelled");
            // progressDialog.dismiss();
            super.onCancelled();
        }

        @Override
        protected void onPostExecute(Integer result) {
            Log.i(Prefs.TAG, "onPostExecute");
            progressDialog.dismiss();
            super.onPostExecute(result);

            // finished Toast
            String rc = null;
            if (commandValidationFailedFlag) {
                rc = "Command Vaidation Failed";
            } else {
                rc = GeneralUtils.getReturnCodeFromLog(vkLogPath);
            }
            final String status = rc;
            video_preview_post.this.runOnUiThread(new Runnable() {
                public void run() {
                    Toast.makeText(video_preview_post.this, status,
                            Toast.LENGTH_LONG).show();

                    // demoVideoPath = demoVideoFolder + "Movie.mp4";

                    if (status.equals("Transcoding Status: Failed")) {
                        Toast.makeText(
                                video_preview_post.this,
                                "Check: " + vkLogPath
                                        + " for more information.",
                                Toast.LENGTH_LONG).show();
                    } else {
                        Intent in = new Intent(getApplicationContext(),
                                PostMemoriesActivity3.class);
                        in.putExtra("PATH_MEMORIES_IMG", "video");
                        startActivity(in);
                    }
                }
            });
        }
    }
}

From Android 4.3 you can use a Surface as the input to your encoder. here

So you can use GLSurfaceView and apply the filters using fragment shaders.

You can find some good examples here.also help this link

Upvotes: 6

OBX
OBX

Reputation: 6114

You can use both openCV and FFmpeg for this purpose . For more info, refer this question. Also, here is how to quickstart to openCV , try this

Also, a ffmpeg github library here.

Upvotes: 1

Related Questions