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?
If you have an Android phone, you can mute your phone from the call screen. Your call screen has different buttons including a mute button (circled below). It is a microphone with a slash line through it.
Click on the gear icon on your screen to find the "Settings" menu. Step 3. Tap the "Audio source" option and select "No audio" to record your screen without sound.
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);
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With