android视频录制例子

本文介绍了一款简易视频录制应用的实现过程,包括UI布局、录制流程控制及屏幕亮度调整等关键部分。该应用解决了预览与录制不兼容的问题,并提供了一个可运行在U880手机上的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

最近写了一个视频录制的例子,做下练习。看似简单的视频录制写起来问题还真不少,网上也有很多关于视频录制的代码,但是在我的手机上总是出错,是不是水土不服?我还试过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>

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值