我尝试使用具有启动停止功能的surfaceview来实现自定义视频录制器。这台录像机工作正常。问题是视频质量很差。当我从默认相机录制10秒视频时,它几乎是12MB。但是当我使用我的代码时,它只有300KB而且质量很差。任何提高视频质量的建议。
我的示例源代码
在xml中:
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<SurfaceView
android:id="@+id/surface_camera"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/buttonstart"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Start"
android:layout_weight="1"/>
<Button
android:id="@+id/buttonstop"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Stop"
android:layout_weight="1" />
</LinearLayout>
<Chronometer
android:id="@+id/chronometer1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/linearLayout1"
android:layout_marginLeft="45dp"
android:text="Chronometer"
android:textSize="25sp"
android:textStyle="bold|italic"
android:typeface="monospace"
android:background="#025076"
/>
</RelativeLayout>
在java类中:
public MediaRecorder mrec = new MediaRecorder();
private Camera mCamera;
protected void startRecording() throws IOException {
recording = true;
mrec = new MediaRecorder(); // Works well
// myChronometer.stop();
mCamera.unlock();
mrec.setCamera(mCamera);
mrec.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mrec.setAudioSource(MediaRecorder.AudioSource.MIC);
mrec.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// mrec.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
// mrec.setPreviewDisplay(surfaceHolder.getSurface());
mrec.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mrec.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
// mCamera.getParameters().getSupportedVideoSizes().get(0);
mrec.setVideoFrameRate(30);
mrec.setVideoSize(1280, 720);
//Just i've try different bitrate
mrec.setVideoEncodingBitRate(100000000);
// mrec.setMaxDuration(10000);
mrec.setPreviewDisplay(surfaceHolder.getSurface());
//output_path is file path
mrec.setOutputFile(output_path);
// mrec.setMaxDuration(10000);
mrec.prepare();
mrec.start();
}
还有更多建议可以提高质量。
答案 0 :(得分:1)
我只是使用以下代码来提高视频质量。这对我有点好看
protected void startRecording() {
try {
recording = true;
mrec = new MediaRecorder();
mCamera.unlock();
mrec.setCamera(mCamera);
//Set audio source
mrec.setAudioSource(MediaRecorder.AudioSource.MIC);
//set video source
mrec.setVideoSource(MediaRecorder.VideoSource.CAMERA);
//set output format
mrec.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
int width = 320;
int height = 240;
try {
//get the available sizes of the video
List<Size> tmpList = getSupportedVideoSizes();
final List<Size> sizeList = new Vector<Size>();
// compare the apsect ratio of the candidate sizes against the
// real ratio
Double aspectRatio = (Double.valueOf(getWindowManager()
.getDefaultDisplay().getHeight()) / getWindowManager()
.getDefaultDisplay().getWidth());
for (int i = tmpList.size() - 1; i > 0; i--) {
Double tmpRatio = Double.valueOf(tmpList.get(i).height)
/ tmpList.get(i).width;
if (EnableLog.LOG_TAG) {
Log.e("Width & height", tmpList.get(i).width + " x "
+ tmpList.get(i).height);
}
if (Math.abs(aspectRatio - tmpRatio) < .15) {
width = tmpList.get(i).width;
height = tmpList.get(i).height;
sizeList.add(tmpList.get(i));
}
}
if (EnableLog.LOG_TAG) {
Log.e("tmpList", tmpList + "*");
}
} catch (Exception e) {
e.printStackTrace();
}
if (EnableLog.LOG_TAG) {
Log.e("set width and height", width + " x " + height);
}
// set the size of video.
// If the size is not applicable then throw the media recorder stop
// -19 error
mrec.setVideoSize(width, height);
// Set the video encoding bit rate this changes for the high, low.
// medium quality devices
mrec.setVideoEncodingBitRate(1700000);
//Set the video frame rate
mrec.setVideoFrameRate(30);
//set audio encoder format
mrec.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
//set video encoder format
mrec.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
//Show the display preview
mrec.setPreviewDisplay(surfaceHolder.getSurface());
//output file path
mrec.setOutputFile(output_path);
mrec.prepare();
mrec.start();
} catch (IllegalStateException e) {
Crashlytics.logException(e);
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
也需要这个:
public List<Size> getSupportedVideoSizes() {
if (params.getSupportedVideoSizes() != null) {
return params.getSupportedVideoSizes();
} else {
// Video sizes may be null, which indicates that all the supported
// preview sizes are supported for video recording.
return params.getSupportedPreviewSizes();
}
}
我希望它会帮助别人。感谢。
答案 1 :(得分:0)
编辑:
@Override
public void surfaceCreated(SurfaceHolder arg0) {
camera = openFrontFacingCamera();
if (camera != null) {
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
camera.release();
camera = null;
}
} else {
Toast.makeText(act, "Problem in opening Camera.", Toast.LENGTH_LONG)
.show();
act.finish();
}
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int format, int height,
int width) {
Camera.Size previewSize = null;
try {
Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> supportSize = parameters
.getSupportedPreviewSizes();
if (supportSize != null) {
previewSize = getOptimalPreviewSize(supportSize, width, height);
}
parameters.setPreviewSize(previewSize.width, previewSize.height);
parameters.set("orientation", "portrait");
camera.setPreviewDisplay(arg0);
camera.setParameters(parameters);
camera.startPreview();
camera.unlock();
mRecorder.setPreviewDisplay(arg0.getSurface());
mRecorder.setCamera(camera);
mRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mRecorder.setMaxDuration(90000);
mRecorder.setOnInfoListener(oninfoLis);
mRecorder.setVideoSize(previewSize.width, previewSize.height);
mRecorder.setVideoFrameRate(30);
mRecorder.setVideoEncodingBitRate(500);
mRecorder.setAudioEncodingBitRate(128);
mRecorder.setOutputFile("/mnt/sdcard/myfile"
+ SystemClock.elapsedRealtime() + ".mp4");
mRecorder.prepare();
mRecorder.start();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.getMessage();
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}