使用MediaRecorder類、Camera開發基於Android系統手機的錄像功能 獲得的視頻文件十分模糊,無法達到系統再帶的相機所錄製的效果 經過分析后,發現在錄像的時候沒有使用自動聚焦功能,從而導致視頻效果極差 但是添加了自動對焦的代碼后,SurfaceView中的預覽已經達到預期效果,但是問題是錄製的視頻卻是花屏 已經糾結了好幾天了,希望Android開發的大牛能給予幫助 下面是代碼片段 public class MainActivity extends Activity implements OnClickListener { private Button video_record, video_stop; private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; private Camera camera; private MediaRecorder mediaRecorder; private boolean isCard, isFocus, isRecord; private String sdCard, recordPath, recordFormat = ".mp4"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFormat(PixelFormat.TRANSLUCENT); setContentView(R.layout.activity_main); init(); setListener(); } private void init() { video_record = (Button) findViewById(R.id.video_record); video_stop = (Button) findViewById(R.id.video_stop); surfaceView = (SurfaceView) findViewById(R.id.video_surface); surfaceHolder = surfaceView.getHolder(); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceHolder.addCallback(new CustomCallBack()); video_stop.setEnabled(false); isCard = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); isFocus = false; isRecord = false; if (isCard) { sdCard = SDCardUtils.getExternalPath(); } } private void setListener() { video_record.setOnClickListener(this); video_stop.setOnClickListener(this); } @Override public void onClick(View v) { if (!isCard) { toast("SDCard is Invalid"); return; } switch (v.getId()) { case R.id.video_record: record(); break; case R.id.video_stop: stop(); break; } } private void record() { isRecord = true; try { initCamera(); initRecord(); } catch (IOException e) { e.printStackTrace(); } referenceView(); } private void stop() { isRecord = false; freeRecordResource(); freeCameraResource(); referenceView(); } private void referenceView() { if (isRecord) { video_record.setEnabled(false); video_stop.setEnabled(true); } else { video_record.setEnabled(true); video_stop.setEnabled(false); recordPath = null; } } private void initCamera() throws IOException { if (camera != null) { freeCameraResource(); } try { camera = Camera.open(); } catch (Exception e) { e.printStackTrace(); } setCameraParams(); camera.setDisplayOrientation(90); camera.setPreviewDisplay(surfaceHolder); camera.startPreview(); if (isFocus) { camera.autoFocus(null); } camera.unlock(); } private void initRecord() throws IOException { if (mediaRecorder != null) { freeRecordResource(); } File file = createFile(); mediaRecorder = new MediaRecorder(); mediaRecorder.setCamera(camera); mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface()); mediaRecorder.setVideoSource(VideoSource.CAMERA); mediaRecorder.setAudioSource(AudioSource.MIC); mediaRecorder.setOutputFormat(OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(AudioEncoder.AMR_NB); // mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); mediaRecorder.setVideoFrameRate(16); mediaRecorder.setVideoEncodingBitRate(3000000); // mediaRecorder.setOrientationHint(90); mediaRecorder.setVideoEncoder(VideoEncoder.MPEG_4_SP); // mediaRecorder.setMaxDuration(Constant.MAXVEDIOTIME * 1000); mediaRecorder.setOutputFile(file.getAbsolutePath()); mediaRecorder.prepare(); mediaRecorder.start(); } private File createFile() throws IOException { if (recordPath == null) { recordPath = sdCard + File.separator + System.currentTimeMillis() + recordFormat; } File file = new File(recordPath); if (!file.exists()) { File parent = file.getParentFile(); if (!parent.exists()) { parent.mkdirs(); } file.createNewFile(); } return file; } private void freeCameraResource() { if (camera != null) { camera.setPreviewCallback(null); camera.stopPreview(); camera.lock(); camera.release(); camera = null; } } private void freeRecordResource() { if (mediaRecorder != null) { mediaRecorder.stop(); mediaRecorder.reset(); mediaRecorder.release(); mediaRecorder = null; } } public void setCameraParams() { if (camera != null) { Parameters params = camera.getParameters(); List<String> list = params.getSupportedFocusModes(); if (list.contains(Parameters.FOCUS_MODE_AUTO)) { isFocus = true; params.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); } params.set("orientation", "portrait"); camera.setParameters(params); } } @Override protected void onStop() { stop(); super.onStop(); } @Override protected void onDestroy() { stop(); super.onDestroy(); } private void toast(String text) { Log.e("custom", text); Toast.makeText(this, text, Toast.LENGTH_LONG).show(); } public class CustomCallBack implements Callback { @Override public void surfaceCreated(SurfaceHolder holder) { if (camera == null) { try { camera = Camera.open(); camera.setDisplayOrientation(90); camera.setPreviewDisplay(holder); // camera.startPreview(); } catch (IOException e) { freeCameraResource(); e.printStackTrace(); } } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (camera != null) { setCameraParams(); camera.startPreview(); if (isFocus) { camera.autoFocus(null); } camera.unlock(); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (camera != null) { freeCameraResource(); } } } } <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.camera" /> 因為功能還沒有完成,所以沒有註釋,肯請看到的大牛能幫幫忙 |
|
10分
#1 |
会不会你设置的profile不好呢?
加上你注释掉的mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));也不行么? 你把mediaRecorder.setVideoFrameRate(16);改成30试试 |
#2 |
測試的時候和這兩處代碼沒有關係的
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); mediaRecorder.setVideoFrameRate(16); 如果將自動對焦的方法去掉,是可以錄製出可以播放的視頻的,但是清晰度方面極差 而且網絡上的一些博客中的關於手機錄製視頻的操作也是這種效果 再加上了自動對焦操作后才錄製出花屏了的視頻 |
#3 |
回复1楼:
測試的時候和這兩處代碼沒有關係的
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); mediaRecorder.setVideoFrameRate(16); 如果將自動對焦的方法去掉,是可以錄製出可以播放的視頻的,但是清晰度方面極差 而且網絡上的一些博客中的關於手機錄製視頻的操作也是這種效果 再加上了自動對焦操作后才錄製出花屏了的視頻 |
10分
#4 |
学习了。后面怎么处理清晰率和压缩率的?
|
10分
#5 |
自动对焦的代码?是这个吗?
if (list.contains(Parameters.FOCUS_MODE_AUTO)) { isFocus = true; params.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); } 有没有把这个list打出来看看?这个代码判断是当前对焦模式是否支持自动,但设置的值却是连续自动对焦啊 |
#6 |
回复5楼: 我已经放弃了 …… |
10分
#7 |
你的花屏,是第二次点击录制按钮才出现的吗?还是一开始录制就出现了花屏的?
|
#8 |
你还是不能清晰录制吗?跟手机本身的摄像功能相比,你用的聚焦功能,也不能达到清晰的效果吗?
|
#9 |
回复8楼: SurfaceView中的显示内容和手机自带的没有什么差距 但是录制出来的文件是花屏 现在我是使用手机自带的录像功能,获取录制时返回的Uri操作 |
#10 |
你花屏是因为你写的camera.startPreview();,把这句话换成camera.stopPreview();就OK了
|
#11 |
LZ解决了么?
|
#12 |
我也遇到了这个问题,视频的大小和调用本地相机一样,但是不能在录制过程中聚焦,清晰度较差。请问有人解决了这个问题吗?
|
#13 |
mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
将上面的这一句放到mediaRecorder.setOutputFile(file.getAbsolutePath());后面试试; |
#14 |
是否是聚焦的问题呢
|
#15 |
楼主现在有思路了吗,解决了跟大家分享一下啊!
|
#16 |
我自己解决了,给大家分享一下我得方法:其他的基本是一样的,只是更改了编码率,我现在也没太弄明白编码率到底是怎么回事!
|
#17 |
我这里设置的分辨率:
mMediaRecorder.setVideoSize(640, 480); 这个我把它去掉了,感觉没什么用 //mMediaRecorder.setVideoFrameRate(16); 在这里我提高了帧频率,然后就清晰了 mMediaRecorder.setVideoEncodingBitRate(5*1024*1024); |
#18 |
回复17楼: 这样设置后竟然解决在三星手机上拍摄视频后的播放花屏问题!感谢 |
#19 |
回复17楼:
感谢
十分感谢 的确清晰了 |
#20 |
回复17楼: 也解决了我在平板上花屏、绿屏的问题,非常感谢谢! |
#21 |
mMediaRecorder.setVideoEncodingBitRate(5*1024*1024);
给力啊!终于解决了!感谢啊~~~~~~! 不过我适当调小了点,要不生成的文件太大了 |
#22 |
这位大哥, 我今天也遇到这个问题了。用了你的方法解决了,感谢你啊!
|
#24 |
我用了也清晰很多了 谢谢了。
|
#25 |
回复17楼: 第二句代码虽然注释掉可以使用,但如果使用,设置的不对就会出现报错了 |