最近写了一个视频录制的例子,做下练习。看似简单的视频录制写起来问题还真不少,网上也有很多关于视频录制的代码,但是在我的手机上总是出错,是不是水土不服?我还试过google SDK文档上的那个录制的例子,不过也没有成功。主要遇到的问题就是只要我在录制前预览,就无法进行录制或者录制出来的视频,声音正常但是图像是花的。试了很多种方法也没有做到预览和录制都正常。
以下是没有预览就录制的例子。在U880上测试是正常的。有需要的可以参考看看,或者帮忙测测在其它型号机器上是否运行正常。
main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<!-- 视频预览窗口 -->
<SurfaceView
android:id="@+id/sv_show"
android:layout_width="720px"
android:layout_height="480px"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" />
<!-- 录制时间显示 -->
<LinearLayout
android:id="@+id/ll_timer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="5dp"
android:gravity="center_vertical"
android:visibility="gone" >
<ImageView
android:id="@+id/iv_recorderStateImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/recorder_state_recorder" />
<TextView
android:id="@+id/tv_recorderTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="00:00"
android:textColor="@android:color/white"
android:textSize="25sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 录制控制按钮 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="4dp" >
<Button
android:id="@+id/bt_recorder"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:text="@string/recorder" />
<Button
android:id="@+id/bt_stop"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:enabled="false"
android:text="@string/stop" />
</LinearLayout>
</RelativeLayout>
用到了一个drawable资源
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<size
android:width="10dp"
android:height="10dp"/>
<solid
android:color="#f00"
/>
</shape>
TestRecorderVideoActivity.java
package com.lxl.testrecordervideo;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
public class TestRecorderVideoActivity extends Activity implements OnClickListener {
private Button bt_recorder, bt_stop;
private TextView tv_recorderTime;
private LinearLayout layout;
private SurfaceView sv_show;
private SurfaceHolder surfaceHolder;
private RecorderService recorder;
Timer timer = null; // 统计时间
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
}
/**
* 初始化控件
*/
private void init() {
bt_recorder = (Button) findViewById(R.id.bt_recorder);
bt_stop = (Button) findViewById(R.id.bt_stop);
tv_recorderTime = (TextView) findViewById(R.id.tv_recorderTime);
layout = (LinearLayout) findViewById(R.id.ll_timer);
sv_show = (SurfaceView) findViewById(R.id.sv_show);
bt_recorder.setOnClickListener(this);
bt_stop.setOnClickListener(this);
sv_show = (SurfaceView) findViewById(R.id.sv_show);
surfaceHolder = sv_show.getHolder();
surfaceHolder.setKeepScreenOn(true); // 保持屏幕高亮
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_recorder:
// 录制
try {
brightnessMax(); // 录制时让屏幕高亮
Log.i("info", "开始高亮");
recorder = new RecorderService(surfaceHolder );
recorder.startRecorder();
bt_recorder.setEnabled(false);
bt_stop.setEnabled(true);
timer = new Timer();
timer.schedule(new mTimerTask(), 0, 1000); // 启动录制时间显示
} catch (Exception e) {
Log.w("info", "录制发生异常:" + e.getMessage());
e.printStackTrace();
}
break;
case R.id.bt_stop:
// 执行停止录制操作
timer.cancel(); // 停止录制时间显示
timer = null;
layout.setVisibility(View.GONE); //取消时间显示
recorder.stopRecorder();
bt_recorder.setEnabled(true);
bt_stop.setEnabled(false);
brightnessMin(); // 停止高亮
break;
default:
break;
}
}
private class mTimerTask extends TimerTask {
private long start_time;
private long end_time;
private SimpleDateFormat simpleDateFormat;
public mTimerTask() {
super();
// 设置录制时间布局显示
layout.setVisibility(View.VISIBLE);
start_time = System.currentTimeMillis(); // 记录开始时间
simpleDateFormat = new SimpleDateFormat("mm:ss");
}
@Override
public void run() {
// 计算从开始到现在所用的时间
end_time = System.currentTimeMillis();
Date date = new Date(end_time - start_time);
// 通知主线程显示
Message msg = new Message();
msg.what = UPDATETIME;
msg.obj = simpleDateFormat.format(date);
handler.sendMessage(msg);
}
}
private static final int UPDATETIME = 1;
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UPDATETIME:
tv_recorderTime.setText(msg.obj.toString());
break;
default:
break;
}
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if(recorder != null) {
recorder.releaseRecorder();
}
}
/**
* 设置屏幕最大亮度
*/
private void brightnessMax() {
WindowManager.LayoutParams lp = getWindow().getAttributes();
Log.i("info", "设置前的亮度:"+lp.screenBrightness);
lp.screenBrightness = 1.0f;
getWindow().setAttributes(lp);
}
/**
* 停止屏幕高亮
*/
private void brightnessMin() {
WindowManager.LayoutParams lp = getWindow().getAttributes();
Log.i("info", "设置前的亮度:"+lp.screenBrightness);
lp.screenBrightness = -1.0f;
getWindow().setAttributes(lp);
}
}
RecorderService.java
package com.lxl.testrecordervideo;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
public class RecorderService {
private MediaRecorder recorder;
private SurfaceHolder surfaceHolder;
public RecorderService(SurfaceHolder surfaceHolder ) {
this.surfaceHolder = surfaceHolder;
}
/**
* 开始录制
* @throws Exception
*/
public void startRecorder() throws Exception {
initRecorder(); // 初始化
// 准备刻录
recorder.prepare();
// 开始刻录
recorder.start();
}
/**
* 初始化MediaRecorder
*/
private void initRecorder() {
recorder = new MediaRecorder();
// 设置音频来源
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
// 设置视频来源
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); //可行,质量优,就是文件有些大!
// // 设置文件的输出格式
// recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
// // 设置音频编码
// recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
// // 设置视频编码
// recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
// 设置视频宽高
// recorder.setVideoSize(176, 144); //720*480 写了没什么效果!!
// 设置视频帧率
// recorder.setVideoFrameRate(5); // 没有效果!!!
recorder.setPreviewDisplay(surfaceHolder.getSurface());
// 设置文件的输出路径
recorder.setOutputFile(getOutputMediaFile().getAbsolutePath());
}
/**
* 停止录制
*/
public void stopRecorder() {
if(recorder != null){
recorder.stop(); // 停止录制
recorder.reset(); // 重置MediaRecorder
}
}
public void releaseRecorder() {
if(recorder != null) {
recorder.release(); // 释放资源
recorder = null;
}
}
/**
* 获取一个用于保存视频文件的File
*
* @return
*/
private static File getOutputMediaFile() {
// 在SD卡上创建一个自己定义的文件夹
File mediaStorageDir = new File(
Environment.getExternalStorageDirectory(), "testRecorder_3gp");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("info", "failed to create directory :: testRecorder_3gp");
return null;
}
}
// 创建一个视频文件
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_" + timeStamp + ".3gp");
return mediaFile;
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lxl.testrecordervideo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<!-- sdcard的写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 相机的使用权限 -->
<uses-permission android:name="android.permission.CAMERA"/>
<!-- 媒体刻录权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".TestRecorderVideoActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>