今天用安卓錄製視頻
用的是別人現成的代碼,代碼原地址http://blog.csdn.net/peijiangping1989/article/details/7049991
但是會報錯
06-03 21:32:32.285: W/System.err(27250): java.lang.RuntimeException: start failed.
06-03 21:32:32.285: W/System.err(27250): at android.media.MediaRecorder.start(Native Method)
06-03 21:32:32.285: W/System.err(27250): at com.it_videorecorder.MainActivity.record(MainActivity.java:87)
06-03 21:32:32.285: W/System.err(27250): at java.lang.reflect.Method.invokeNative(Native Method)
06-03 21:32:32.285: W/System.err(27250): at java.lang.reflect.Method.invoke(Method.java:511)
06-03 21:32:32.285: W/System.err(27250): at android.view.View$1.onClick(View.java:3586)
06-03 21:32:32.285: W/System.err(27250): at android.view.View.performClick(View.java:4084)
06-03 21:32:32.285: W/System.err(27250): at android.view.View$PerformClick.run(View.java:16966)
06-03 21:32:32.285: W/System.err(27250): at android.os.Handler.handleCallback(Handler.java:615)
06-03 21:32:32.289: W/System.err(27250): at android.os.Handler.dispatchMessage(Handler.java:92)
06-03 21:32:32.289: W/System.err(27250): at android.os.Looper.loop(Looper.java:137)
06-03 21:32:32.289: W/System.err(27250): at android.app.ActivityThread.main(ActivityThread.java:4931)
06-03 21:32:32.289: W/System.err(27250): at java.lang.reflect.Method.invokeNative(Native Method)
06-03 21:32:32.289: W/System.err(27250): at java.lang.reflect.Method.invoke(Method.java:511)
06-03 21:32:32.289: W/System.err(27250): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
06-03 21:32:32.292: W/System.err(27250): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
06-03 21:32:32.292: W/System.err(27250): at dalvik.system.NativeStart.main(Native Method)
這個錯誤百度了下,貌似不少人遇到。
我看了下大概有幾個可能的原因
第一 視頻尺寸設置不支持
第二 格式設置不對,是3gp 還是mp4這個不同手機會有不同的實現方式。我的是這個原因
第三 幀率設置不對。可能幀率設置的高手機支持不了那麼高的分辨率
大概是這幾個原因,每個人程序不同,即使報同樣的錯誤解決方式也會不一樣。都試一試,逐個排查一下。
貼個代碼,因上面那個鏈接裏面的代碼會出現小小錯誤,把我的發上來,有用的上的就拿去吧。
package com.dineed.videorecorder;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
public class VideoRecorderActivity extends Activity {
private Button start;// 開始錄製按鈕
private Button stop;// 停止錄製按鈕
private MediaRecorder mediarecorder;// 錄製視頻的類
private SurfaceView surfaceview;// 顯示視頻的控件
// 用來顯示視頻的一個接口,我靠不用還不行,也就是說用mediarecorder錄製視頻還得給個界面看
// 想偷偷錄視頻的同學可以考慮別的辦法。。嗯需要實現這個接口的Callback接口
private SurfaceHolder surfaceHolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉標題欄
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);// 設置全屏
// 設置橫屏顯示
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// 選擇支持半透明模式,在有surfaceview的activity中使用。
getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(R.layout.activity_video_recorder);
init();
}
private void init() {
start = (Button) this.findViewById(R.id.start);
stop = (Button) this.findViewById(R.id.stop);
start.setOnClickListener(new TestVideoListener());
stop.setOnClickListener(new TestVideoListener());
surfaceview = (SurfaceView) this.findViewById(R.id.surfaceview);
SurfaceHolder holder = surfaceview.getHolder();// 取得holder
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
surfaceview = null;
surfaceHolder = null;
mediarecorder = null;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
surfaceHolder = holder;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
surfaceHolder = holder;
}
});// holder加入回調接口
// setType必須設置,要不出錯.
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.video_recorder, menu);
return true;
}
class TestVideoListener implements OnClickListener {
@Override
public void onClick(View v) {
if (v == start) {
mediarecorder = new MediaRecorder();// 創建mediarecorder對象
// 設置錄製視頻源爲Camera(相機)
mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// 設置錄製完成後視頻的封裝格式THREE_GPP爲3gp.MPEG_4爲mp4
mediarecorder
.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// 設置錄製的視頻編碼h263 h264
mediarecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
// 設置視頻錄製的分辨率。必須放在設置編碼和格式的後面,否則報錯
mediarecorder.setVideoSize(640, 480);
// 設置錄製的視頻幀率。必須放在設置編碼和格式的後面,否則報錯
//mediarecorder.setVideoFrameRate(20);
mediarecorder.setPreviewDisplay(surfaceHolder.getSurface());
// 設置視頻文件輸出的路徑
mediarecorder.setOutputFile("/sdcard/love.3gp");
try {
// 準備錄製
mediarecorder.prepare();
// 開始錄製
mediarecorder.start();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (v == stop) {
if (mediarecorder != null) {
// 停止錄製
mediarecorder.stop();
// 釋放資源
mediarecorder.release();
mediarecorder = null;
}
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// 將holder,這個holder爲開始在oncreat裏面取得的holder,將它賦給surfaceHolder
surfaceHolder = holder;
}
public void surfaceCreated(SurfaceHolder holder) {
// 將holder,這個holder爲開始在oncreat裏面取得的holder,將它賦給surfaceHolder
surfaceHolder = holder;
}
public void surfaceDestroyed(SurfaceHolder holder) {
// surfaceDestroyed的時候同時對象設置爲null
surfaceview = null;
surfaceHolder = null;
mediarecorder = null;
}
}
佈局文件
其實就是一個Surfview和兩個BUTTON
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" >
<SurfaceView
android:id="@+id/surfaceview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="4"
android:gravity="center"
android:orientation="vertical" >
<Button
android:id="@+id/start"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Start" />
<Button
android:id="@+id/stop"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Stop" />
</LinearLayout>
</LinearLayout>
要注意在manifest.xml添加外部存儲寫權限,攝像頭權限錄音權限。
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>