ユーザーが画面にタッチしてビデオをすばやく撮影できる基本的なビデオカメラを構築しようとしていますが、これは簡単なことのように思えましたが、私が遭遇した主な問題は、Android MediaRecorder がクラッシュすることなく迅速な開始と再起動を許可しないことです。ユーザーが撮影してから停止し、すぐに再び撮影を再開すると、常にクラッシュします。これを直接修正する方法があるかどうかはわかりません。そのため、単一のビデオを録画しようとするが、何らかの制御を得ようとすることで、これを達成する別の方法も考案しました。 mediaRecorder が実際にファイルに書き込むとき。ただし、FileDescriptor を使用してこれを完全に実行することはできませんでした。以下に、元のコードと、書き込みを制御する 2 回目の試みで使用した方法を貼り付けます。どちらかのコードを調整して一時停止機能を実現する方法はありますか? どんな助けでも大いに役立ちます ありがとう
ファイルを setOutPutFile() に設定する一般的な方法を使用した最初の試み:
public class MainActivity extends Activity implements SurfaceHolder.Callback {
public static final String LOGTAG = "VIDEOCAPTURE";
private MediaRecorder recorder;
private SurfaceHolder holder;
private CamcorderProfile camcorderProfile;
private Camera camera;
boolean recording = false;
boolean usecamera = true;
boolean previewRunning = false;
double timer = 0;
ProgressBar pb;
boolean neverEnd;
@Override
public 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_PORTRAIT);
camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
setContentView(R.layout.activity_main);
pb = (ProgressBar) findViewById(R.id.progressBar1);
pb.setProgress(0);
SurfaceView cameraView = (SurfaceView) findViewById(R.id.CameraView);
holder = cameraView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
cameraView.setClickable(true);
cameraView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
recording = true;
new recordVideo().execute();
Log.v(LOGTAG, "Recording Started");
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
recording = false;
return true;
}
return false;
}
});
}
private void prepareRecorder() {
recorder = new MediaRecorder();
recorder.setPreviewDisplay(holder.getSurface());
if (usecamera) {
camera.unlock();
recorder.setCamera(camera);
}
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
recorder.setProfile(camcorderProfile);
Calendar calendarTime = Calendar.getInstance();
//initial attempt using a file path with setoutputfile
File file = new File(Environment.getExternalStorageDirectory(),
String.valueOf(calendarTime.getTimeInMillis()) + ".mp4");
if (camcorderProfile.fileFormat == MediaRecorder.OutputFormat.THREE_GPP) {
recorder.setOutputFile(file.getAbsolutePath());
} else if (camcorderProfile.fileFormat == MediaRecorder.OutputFormat.MPEG_4) {
recorder.setOutputFile(file.getAbsolutePath());
} else {
recorder.setOutputFile(file.getAbsolutePath());
}
// recorder.setMaxDuration(50000); // 50 seconds
// recorder.setMaxFileSize(5000000); // Approximately 5 megabytes
boolean initialized = false;
while (!initialized) {
try {
recorder.prepare();
initialized = true;
} catch (IllegalStateException e) {
e.printStackTrace();
// finish();
initialized = false;
} catch (IOException e) {
e.printStackTrace();
// finish();
initialized = false;
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
Log.v(LOGTAG, "surfaceCreated");
if (usecamera) {
camera = Camera.open();
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
previewRunning = true;
} catch (IOException e) {
Log.e(LOGTAG, e.getMessage());
e.printStackTrace();
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.v(LOGTAG, "surfaceChanged");
if (!recording && usecamera) {
if (previewRunning) {
camera.stopPreview();
}
try {
Camera.Parameters p = camera.getParameters();
p.setPreviewSize(camcorderProfile.videoFrameWidth,
camcorderProfile.videoFrameHeight);
p.setPreviewFrameRate(camcorderProfile.videoFrameRate);
camera.setParameters(p);
camera.setPreviewDisplay(holder);
camera.startPreview();
previewRunning = true;
} catch (IOException e) {
Log.e(LOGTAG, e.getMessage());
e.printStackTrace();
}
prepareRecorder();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v(LOGTAG, "surfaceDestroyed");
if (recording) {
recorder.stop();
recording = false;
}
recorder.release();
if (usecamera) {
previewRunning = false;
// camera.lock();
camera.release();
}
finish();
}
private class recordVideo extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
try {
recorder.start();
while (recording) {
Thread.sleep(100);
publishProgress();
}
recorder.stop();
recorder.release();
recorder = null;
// recorder.release();
Log.v(LOGTAG, "Recording Stopped");
// Let's prepareRecorder so we can record again
prepareRecorder();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
if (recording) {
timer += 0.1;
pb.setProgress((int) (timer * 10));
}
}
}
}
FileDescriptor を使用した私の方法は次のとおりです。これは機能せず、ファイルを作成しただけで書き込みはしませんでした。
//Pass it into setOutputFile() like this
recorder.setOutputFile(getStreamFd());
private FileDescriptor getStreamFd() {
ParcelFileDescriptor pipe = null;
try {
Calendar calendarTime = Calendar.getInstance();
File file = new File(Environment.getExternalStorageDirectory(),
String.valueOf(calendarTime.getTimeInMillis()) + ".mp4");
pipe = ParcelFileDescriptor.open(file,
ParcelFileDescriptor.MODE_CREATE
| ParcelFileDescriptor.MODE_APPEND
| ParcelFileDescriptor.MODE_WORLD_WRITEABLE);
byte[] buf = new byte[1024];
int len;
FileOutputStream out = new FileOutputStream(FileDescriptor.out);
InputStream is = new FileInputStream(FileDescriptor.in);
while (usecamera) {
if(recordng){
out.write(buf, 0, len);
}
}
is.close();
out.close();
} catch (IOException e) {
Log.e(getClass().getSimpleName(), "Exception opening pipe", e);
}
return pipe.getFileDescriptor();
}