|
使用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楼: 第二句代码虽然注释掉可以使用,但如果使用,设置的不对就会出现报错了 |