12

I'm recording a video with the camera, using the MediaRecorder class, after following a tutorial similiar to this

http://androidcookbook.com/Recipe.seam;jsessionid=40151FCD26222877E151C3EEFB406EED?recipeId=1375&recipeFrom=ViewTOC

And I want while recording, to be able to mute / unmute the microphone. How's that possible?

I'm setting the audio source at start

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

But what if I want to record without sound at some point?

Boldijar Paul
  • 5,405
  • 9
  • 46
  • 94
  • doesn't AudioManager.setMicrophoneMute(boolean) work for you ? – Gilad Eshkoli Dec 15 '16 at 08:16
  • @Gil no. Not working on Note 4. – Boldijar Paul Dec 19 '16 at 07:28
  • @BoldijarPaul **record without sound at some point?** so you want like first 5 seconds with sound from 6 to 10 mute video ? – user1140237 Dec 19 '16 at 14:23
  • @user1140237 I just want to be able to mute or unmute the microphone while recording video, doesn't matter when. – Boldijar Paul Dec 20 '16 at 08:44
  • Check if you added permission android:name="android.permission.MODIFY_AUDIO_SETTINGS", it is required for changing audio settings – Noorul Dec 21 '16 at 05:02
  • I think you have to consider ndk. Tweak https://android.googlesource.com/platform/frameworks/base/+/b267554/media/jni/android_media_MediaRecorder.cpp to change audio input channel durring recording – Qamar Dec 21 '16 at 12:26

3 Answers3

4

Try the following code:

private void setMicMuted(boolean state){
    AudioManager myAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);

    // get the working mode and keep it
    int workingAudioMode = myAudioManager.getMode();

    myAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);

    // change mic state only if needed
    if (myAudioManager.isMicrophoneMute() != state) {
        myAudioManager.setMicrophoneMute(state);
    }

    // set back the original working mode
    myAudioManager.setMode(workingAudioMode);
}
dogood
  • 331
  • 2
  • 5
  • This worked for me. Tested on Samsung Note 4 & Htc M8 – Boldijar Paul Jan 05 '17 at 12:42
  • Code is working with default video recorder intent ACTION_VIDEO_CAPTURE ? I try but it is not work. I want to make video with no sound with default video recorder intent which is ACTION_VIDEO_CAPTURE. Please help me. – Sohel S9 Apr 13 '19 at 05:57
2

To handle videos with Sound(Mic) or without sound (Mic) record video clips with AudioSource in mediaRecorder and without it if dont required sound. Merge all the clips using mp4 parser .

To record video with AudioSource and AudioEncoder its required to get camera parameters , fetch the profile and set parameters to MediaRecorder.

Here I've given code which may help to record video with sound and without sound (Video recording may strech as I've taken from the link which is gven in your question But mute and unmute will work fine)

Activity

import android.app.Activity;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.googlecode.mp4parser.BasicContainer;
import com.googlecode.mp4parser.authoring.Movie;
import com.googlecode.mp4parser.authoring.Track;
import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder;
import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator;
import com.googlecode.mp4parser.authoring.tracks.AppendTrack;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class MediaRecorderRecipe extends Activity implements SurfaceHolder.Callback {
    private MediaRecorder mMediaRecorder;
    private Camera mCamera;
    private SurfaceView mSurfaceView;
    private SurfaceHolder mHolder;
    private View mToggleButton;
    private ToggleButton togglemute;
    private boolean mInitSuccesful;
    private File videoDirectory;
    private Button btn;
    private File mainDirectory, clipsDir, mergedDir;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test);
        videoDirectory = new File(Environment.getExternalStorageDirectory() + File.separator + "MuteUnMuteVideos");
        clipsDir = new File(videoDirectory.getAbsolutePath(), "Clips");
        clipsDir.mkdirs();
        mergedDir = new File(videoDirectory.getAbsolutePath(), "FinalMerged");
        mergedDir.mkdirs();
        deleteFilesDir(clipsDir.getAbsolutePath());
        // we shall take the video in landscape orientation

        mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        togglemute = (ToggleButton) findViewById(R.id.togglemute);
        mToggleButton = (ToggleButton) findViewById(R.id.toggleRecordingButton);
        btn = (Button) findViewById(R.id.doneRecording);
        mToggleButton.setOnClickListener(new OnClickListener() {
            @Override
            // toggle video recording
            public void onClick(View v) {

                if (((ToggleButton) v).isChecked()) {
                    try {
                        if (!mInitSuccesful)
                            initRecorder(mHolder.getSurface());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    mMediaRecorder.start();
                    togglemute.setEnabled(false);
                    btn.setEnabled(false);
                } else {
                    mMediaRecorder.stop();
                    mMediaRecorder.reset();
                    togglemute.setEnabled(true);
                    btn.setEnabled(true);
                    mInitSuccesful = false;

                }
            }
        });
        btn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                new MergeVideosTask(MediaRecorderRecipe.this).execute();
            }
        });

    }

    private File outputFile;

    class MergeVideosTask extends AsyncTask {
        Activity activity;

        public MergeVideosTask(Activity activity) {
            this.activity = activity;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            /**
             * Show Progressbar
             */
        }

        @Override
        protected Object doInBackground(Object[] objects) {
            mergeVideos();
            return null;
        }

        @Override
        protected void onPostExecute(Object o) {
            super.onPostExecute(o);
            /**
             * Dismiss Progress
             */
            Toast.makeText(MediaRecorderRecipe.this, "Save Video : " + outputFile.getAbsolutePath(), Toast.LENGTH_LONG).show();
        }

        public void mergeVideos() {
            try {
                File parentDir = new File(clipsDir.getAbsolutePath());
                List<String> videosPathList = new ArrayList<>();
                File[] files = parentDir.listFiles();
                for (File file : files) {
                    videosPathList.add(file.getAbsolutePath());
                }

                List<Movie> inMovies = new ArrayList<>();
                for (int i = 0; i < videosPathList.size(); i++) {
                    String filePath = videosPathList.get(i);
                    try {
                        Movie movie = MovieCreator.build(filePath);
                        if (movie != null)
                            inMovies.add(movie);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                List<Track> videoTracks = new LinkedList<Track>();
                List<Track> audioTracks = new LinkedList<Track>();
                for (Movie m : inMovies) {
                    for (Track t : m.getTracks()) {
                        try {
                            if (t.getHandler().equals("soun")) {
                                audioTracks.add(t);
                            }
                            if (t.getHandler().equals("vide")) {
                                videoTracks.add(t);
                            }
                        } catch (Exception e) {

                        }
                    }
                }
                Movie result = new Movie();
                if (audioTracks.size() > 0) {
                    result.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()])));
                }
                if (videoTracks.size() > 0) {
                    result.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()])));
                }
                BasicContainer out = (BasicContainer) new DefaultMp4Builder().build(result);
                File f = null;
                String finalVideoPath;
                try {
                    f = setUpVideoFile(mergedDir.getAbsolutePath());
                    finalVideoPath = f.getAbsolutePath();

                } catch (IOException e) {
                    e.printStackTrace();
                    f = null;
                    finalVideoPath = null;
                }
                WritableByteChannel fc = new RandomAccessFile(finalVideoPath, "rw").getChannel();
                out.writeContainer(fc);
                fc.close();
                outputFile = new File(finalVideoPath);
//                deleteFilesDir(getExternalFilesDir(null).getAbsolutePath());

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

                finish();
            }
        }

        File setUpVideoFile(String directory) throws IOException {
            File videoFile = null;
            if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
                File storageDir = new File(directory);
                if (storageDir != null) {
                    if (!storageDir.mkdirs()) {
                        if (!storageDir.exists()) {
                            Log.d("CameraSample", "failed to create directory");
                            return null;
                        }
                    }
                }
                videoFile = File.createTempFile("video_" + System.currentTimeMillis() + "_", ".mp4", storageDir);
            }
            return videoFile;
        }


    }

    private void deleteFilesDir(String path) {
        File dir = new File(path);
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i = 0; i < children.length; i++) {
                new File(dir, children[i]).delete();
            }
        }
    }

    /* Init the MediaRecorder, the order the methods are called is vital to
     * its correct functioning */
    private void initRecorder(Surface surface) throws IOException {
        // It is very important to unlock the camera before doing setCamera
        // or it will results in a black preview
        if (mCamera == null) {
            mCamera = Camera.open();
        }
        if (mMediaRecorder != null) {
            mMediaRecorder.reset();   // clear recorder configuration
            mMediaRecorder.release(); // release the recorder object
            mMediaRecorder = null;
        }
        mMediaRecorder = new MediaRecorder();
        mMediaRecorder.setPreviewDisplay(surface);


        CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_720P);
        Camera.Parameters parameters = mCamera.getParameters();
        List<Camera.Size> mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
        List<Camera.Size> mSupportedVideoSizes = parameters.getSupportedVideoSizes();
        Camera.Size optimalSize = getOptimalVideoSize(mSupportedVideoSizes,
                mSupportedPreviewSizes, profile.videoFrameWidth, profile.videoFrameHeight);
        /**
         * Prepare video with proper size. Preview and video size
         */
        profile.videoFrameWidth = optimalSize.width;
        profile.videoFrameHeight = optimalSize.height;
        mCamera.unlock();
        mMediaRecorder.setCamera(mCamera);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        if (!togglemute.isChecked()) {
            /**
             * Add Audio Source if video required with sound
             */
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);

        }
        mMediaRecorder.setOutputFormat(profile.fileFormat);
        mMediaRecorder.setVideoEncoder(profile.videoCodec);
        if (!togglemute.isChecked()) {
            /**
             * Add Audio Encoder if video required with sound
             */
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
        }
        mMediaRecorder.setVideoEncodingBitRate(profile.videoBitRate);
        mMediaRecorder.setVideoFrameRate(profile.videoFrameRate);
        mMediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
        File file = new File(clipsDir.getAbsolutePath(), System.currentTimeMillis() + ".mp4");
        // "touch" the file
        if (!file.exists()) {
            File parent = file.getParentFile();
            if (parent != null)
                if (!parent.exists())
                    if (!parent.mkdirs())
                        throw new IOException("Cannot create " +
                                "parent directories for file: " + file);

            file.createNewFile();
        }

        mMediaRecorder.setOutputFile(file.getAbsolutePath());
        mMediaRecorder.setPreviewDisplay(surface);

        try {
            mMediaRecorder.prepare();
        } catch (IllegalStateException e) {
            // This is thrown if the previous calls are not called with the
            // proper order
            e.printStackTrace();
        }

        mInitSuccesful = true;
    }

    public static Camera.Size getOptimalVideoSize(List<Camera.Size> supportedVideoSizes,
                                                  List<Camera.Size> previewSizes, int w, int h) {
        // Use a very small tolerance because we want an exact match.
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;

        // Supported video sizes list might be null, it means that we are allowed to use the preview
        // sizes
        List<Camera.Size> videoSizes;
        if (supportedVideoSizes != null) {
            videoSizes = supportedVideoSizes;
        } else {
            videoSizes = previewSizes;
        }
        Camera.Size optimalSize = null;

        // Start with max value and refine as we iterate over available video sizes. This is the
        // minimum difference between view and camera height.
        double minDiff = Double.MAX_VALUE;

        // Target view height
        int targetHeight = h;

        for (Camera.Size size : videoSizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                continue;
            if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : videoSizes) {
                if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            if (!mInitSuccesful)
                initRecorder(mHolder.getSurface());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        shutdown();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
    }


    private void shutdown() {
        // Release MediaRecorder and especially the Camera as it's a shared
        // object that can be used by other applications
        mMediaRecorder.reset();
        mMediaRecorder.release();
        mCamera.release();

        // once the objects have been released they can't be reused
        mMediaRecorder = null;
        mCamera = null;
    }
}

Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <ToggleButton
        android:id="@+id/toggleRecordingButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textOff="Start Recording"
        android:textOn="Stop Recording" />
    <ToggleButton
        android:id="@+id/togglemute"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textOff="Mute Recording"
        android:textOn="UnMute Recording" />

    <Button
        android:id="@+id/doneRecording"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Finish Recording" />

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <SurfaceView
            android:id="@+id/surfaceView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"></SurfaceView>

    </FrameLayout>
</LinearLayout>

build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
    compile 'com.googlecode.mp4parser:isoparser:1.1.21' ///To MergeVideos
}

Need to create every time new MediaRecorder instance before recording start. And release after recodring stops.

If video required with Sound(Mic) add Audio Source and Audio Encoder in MediaRecorder as given below.

mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);

mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);

As i've not much time so hve not make proper code to remove video streching part but mute/unmute will work fine as per your question.

for video recording please refere this

Let me know if anything

Community
  • 1
  • 1
user1140237
  • 5,015
  • 1
  • 28
  • 56
0
((AudioManager)context.getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_SYSTEM,true);

Try,That mute all sounds.

Rishabh Mahatha
  • 1,251
  • 9
  • 19