錄影功能簡單實現&字幕srt儲存
阿新 • • 發佈:2019-01-29
介面效果
功能介紹
照相機預覽
- 窗體的onCreate中新增
SurfaceHolder holder = surfaceView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceView.setKeepScreenOn(true);//保持螢幕高亮
- surfaceCreated
@Override
public void surfaceCreated(SurfaceHolder holder) {
surfaceHolder = holder;
//初始化相機
initCamera();
}
- surfaceChanged
@Override
public void surfaceChanged(SurfaceHolder holder, int i, int i1, int i2) {
surfaceHolder = holder;
//開啟相機預覽
cameraPreview();
}
- surfaceDestroyed
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
surfaceView = null;
surfaceHolder = null ;
//釋放MediaRecorder及相機
stopRecord();
//釋放MediaPlayer
stopPlay();
}
- initCamera:初始化相機
private void initCamera() {
if (camera != null) {
camera.release();
camera = null;
}
try {
//開啟後置攝像頭(此文未涉及前置攝像頭)
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
if (camera != null) {
cameraPara = camera.getParameters();
//可通過camera.getParameters().getSupportedVideoSizes()獲取支援的大小
cameraPara.setPreviewSize(600, 480);
cameraPara.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
camera.cancelAutoFocus();//連續自動對焦
camera.setParameters(cameraPara);
}
} catch (Exception e) {
e.printStackTrace();
if (camera != null) {
camera.release();
camera = null;
}
}
}
- cameraPreview:相機預覽
private void cameraPreview() {
if (camera != null) {
try {
camera.setPreviewDisplay(surfaceView.getHolder());
camera.setDisplayOrientation(90);
camera.startPreview();
//設定閃光燈
cameraPara.setFlashMode(isFlashOn ? Parameters.FLASH_MODE_TORCH : Parameters.FLASH_MODE_OFF);
camera.setParameters(cameraPara);
} catch(Exception e) {
e.printStackTrace();
}
}
}
錄影
- startRecord:開始錄製
private static final int RECORDER_MAX_LENGTH = 30 * 60 * 1000;//錄影最大時長
private Handler handler = new Handler();
private long srtInterval = 1000;//字幕輸出的時間間隔
private void startRecord() {
//錄影過程中顯示時間
hour = minute = second = 0;
startRecordTime = new Date().getTime();
handler.postDelayed(updateTimeRunnable, 1000);
//錄影過程中儲存字幕檔案
lastSrtTime = "00:00:00,000";//上次輸出srt的時間
srtRowNum = 1;//字幕輸出的行號
handler.postDelayed(recordSrtRunnable, srtInterval);
//開始錄製
if (mediaRecorder == null) {
mediaRecorder = new MediaRecorder();
}
if (camera == null) {
initCamera();
camera.setDisplayOrientation(90);
}
camera.unlock();
mediaRecorder.setCamera(camera);
try {
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
//設定輸出的檔案格式
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
//與camera的previewSize需設定為一樣
mediaRecorder.setVideoSize(640, 480);
mediaRecorder.setVideoFrameRate(30);
mediaRecorder.setVideoEncodingBitRate(3 * 1024 * 1024);
mediaRecorder.setOrientationHint(90);
//設定記錄會話的最大持續時間(毫秒)
mediaRecorder.setMaxDuration(RECORDER_MAX_LENGTH);
mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mediaRecorder.setOutputFile(path);
mediaRecorder.prepare();
mediaRecorder.start();
} catch (Exception e) {
e.printStackTrace();
stopRecord();
}
}
//顯示錄影時長
private Runnable updateTimeRunnable = new Runnable() {
@Override
public void run() {
if (second >= 59) {
if (minute >= 59) {
hour++;
minute = 0;
} else {
minute++;
}
second = 0;
} else {
second++;
}
if (hour > 0) {
tvTime.setText(String.format("%02d:%02d:%02d", hour, minute, second));
} else {
tvTime.setText(String.format("%02d:%02d", minute, second));
}
//錄製超過最大時長
if (new Date().getTime() - startRecordTime >= RECORDER_MAX_LENGTH) {
stopRecord();
return;
}
handler.postDelayed(this, 1000);
}
}
//將位置資訊寫入字幕檔案
private Runnable recordSrtRunnable = new Runnable() {
@Override
public void run() {
StringBuilder srtBuilder = new StringBuilder();
String srtTime = String.format("%02d:%02d:%02d,000", hour, minute, second);
srtBuilder.append(srtRowNum++ + "\n");
srtBuilder.append(String.format("%s --> %s\n", lastSrtTime, srtTime));
srtBuilder.append(String.format("%s%.2f\n", "高程:", altitude));
srtBuilder.append("\n");
srtBuilder.append(srtRowNum++ + "\n");
srtBuilder.append(String.format("%s --> %s\n", lastSrtTime, srtTime));
srtBuilder.append(String.format("%s%s %s%s\n", "緯度:", latitude, "經度:", longitude));
srtBuilder.append("\n");
lastSrtTime = srtTime;
File srtFile = new File(srtPath);
try {
FileOutputStream fs = new FileOutputStream(srtFile.getAbsolutePath(), true);
fs.write(srtBuilder.toString().getBytes());
fs.close();
} catch (Exception e) {
e.printStackTrack();
}
handler.postDelayed(this, srtInterval);
}
}
- stopRecord:停止錄製,釋放資源
private void stopRecord() {
try {
if (mediaRecorder != null) {
handler.removeCallbacks(recordSrtRunnable);
handler.removeCallbacks(updateTimeRunnable);
mediaRecorder.stop();
mediaRecorder.reset();
mediaRecorder.release();
mediaRecorder = null;
}
if (camera != null) {
camera.release();
camera = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
播放
- startPlay:開始播放
private void startPlay() {
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
}
mediaPlayer.reset();
Uri uri = Uri.parse(path);
mediaPlayer = MediaPlayer.create(MainActivity.this, uri);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDisplay(surfaceHolder);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
stopPlay();
}
});
try {
mediaPlayer.prepare();
} catch (Exception e) {
e.printStackTrace();
}
mediaPlayer.start();
}
- stopPlay:停止播放,釋放資源
private void stopPlay() {
if (mediaPlayer != null){
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
}
其他
- 判斷閃光燈是否可用
getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
- 開關閃光燈
btnFlash.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isFlashOn) {
btnFlash.setImageResource(R.drawable.video_flash_close);
isFlashOn = false;
} else {
btnFlash.setImageResource(R.drawable.video_flash_on);
isFlashOn = true;
}
cameraPara.setFlashMode(isFlashOn ? Parameters.FLASH_MODE_TORCH : Parameters.FLASH_MODE_OFF);
camera.setParameters(cameraPara);
}
});
- AndroidManifest.xml新增許可權
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- 字幕檔案srt的格式
1
00:00:00,000 --> 00:00:01,000
高程:150.60
2
00:00:00,000 --> 00:00:01,000
緯度:22.982481666666665 經度:113.36807833333333
3
00:00:01,000 --> 00:00:02,000
高程:150.60
4
00:00:01,000 --> 00:00:02,000
緯度:22.982481666666665 經度:113.36807833333333
- 錄製結果