This commit is contained in:
巫翔 2021-09-28 16:25:05 +08:00
commit e2dc633112
7 changed files with 1086 additions and 0 deletions

21
package.json Normal file
View File

@ -0,0 +1,21 @@
{
"name": "capture-cordova-plugin",
"version": "1.0.0",
"description": "Video or Photo Capture Cordova Plugin",
"cordova": {
"id": "capture-cordova-plugin",
"platforms": [
"android"
]
},
"repository": {
"type": "git",
"url": "https://m.shuto.cn:8680/center/capture-cordova-plugin.git"
},
"keywords": [
"ecosystem:cordova",
"cordova-android"
],
"author": "shuto",
"license": "ISC"
}

35
plugin.xml Normal file
View File

@ -0,0 +1,35 @@
<?xml version='1.0' encoding='utf-8'?>
<plugin id="capture-cordova-plugin" version="1.0.0"
xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<name>Capture Plugin</name>
<js-module name="capture-cordova-plugin" src="www/capture.js">
<clobbers target="capture" />
</js-module>
<platform name="android">
<config-file parent="/*" target="res/xml/config.xml">
<feature name="capture-cordova-plugin">
<param name="android-package" value="cn.shuto.plugin.capture.CaptureCordovaPlugin" />
</feature>
</config-file>
<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</config-file>
<config-file target="AndroidManifest.xml" parent="application">
<activity android:name="com.mabeijianxi.smallvideorecord2.MediaRecorderActivity" android:clearTaskOnLaunch="true" android:configChanges="orientation|keyboardHidden|screenSize" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:windowSoftInputMode="stateAlwaysHidden" android:exported="false"/>
<provider android:name="org.apache.cordova.camera.FileProvider" android:authorities="${applicationId}.cordova.plugin.camera.provider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/camera_provider_paths"/>
</provider>
</config-file>
<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-feature android:name="android.hardware.camera" android:required="true"/>
</config-file>
<source-file src="src/android/CaptureCordovaPlugin.java" target-dir="src/cn/shuto/plugin/capture" />
<framework custom="true" src="src/android/mobile-ffmpeg-x2.gradle" type="gradleReference" />
</platform>
</plugin>

View File

@ -0,0 +1,31 @@
package cn.shuto.plugin.capture;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* This class echoes a string called from JavaScript.
*/
public class CaptureCordovaPlugin extends CordovaPlugin {
public static final int REQUEST_CODE = 0x777578;
private CallbackContext callbackContext;
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
this.callbackContext = callbackContext;
JSONObject param = args.optJSONObject(0);
if (action.equals("capture")) {
this.capture(param, callbackContext);
return true;
}
return false;
}
private void capture(JSONObject param, CallbackContext callbackContext) {
}
}

View File

@ -0,0 +1,704 @@
package com.mabeijianxi.smallvideorecord2;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CheckedTextView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.mabeijianxi.smallvideorecord2.model.MediaObject;
import com.mabeijianxi.smallvideorecord2.model.MediaRecorderConfig;
import java.io.File;
import static com.mabeijianxi.smallvideorecord2.R.id.bottom_layout;
/**
* 视频录制
*/
public class MediaRecorderActivity extends Activity implements
MediaRecorderBase.OnErrorListener, OnClickListener, MediaRecorderBase.OnPreparedListener,
MediaRecorderBase.OnEncodeListener {
private int RECORD_TIME_MIN = (int) (1.5f * 1000);
/**
* 录制最长时间
*/
private int RECORD_TIME_MAX = 6 * 1000;
/**
* 刷新进度条
*/
private static final int HANDLE_INVALIDATE_PROGRESS = 0;
/**
* 延迟拍摄停止
*/
private static final int HANDLE_STOP_RECORD = 1;
/**
* 下一步
*/
private ImageView mTitleNext;
/**
* 前后摄像头切换
*/
private CheckBox mCameraSwitch;
/**
* 回删按钮延时按钮滤镜按钮
*/
private CheckedTextView mRecordDelete;
/**
* 闪光灯
*/
private CheckBox mRecordLed;
/**
* 拍摄按钮
*/
private TextView mRecordController;
/**
* 底部条
*/
private RelativeLayout mBottomLayout;
/**
* 摄像头数据显示画布
*/
private SurfaceView mSurfaceView;
/**
* 录制进度
*/
private ProgressView mProgressView;
/**
* SDK视频录制对象
*/
private MediaRecorderBase mMediaRecorder;
/**
* 视频信息
*/
private MediaObject mMediaObject;
/**
* 是否是点击状态
*/
private volatile boolean mPressedStatus;
/**
* 是否已经释放
*/
private volatile boolean mReleased;
/**
* 视屏地址
*/
public final static String VIDEO_URI = "video_uri";
/**
* 本次视频保存的文件夹地址
*/
public final static String OUTPUT_DIRECTORY = "output_directory";
/**
* 视屏截图地址
*/
public final static String VIDEO_SCREENSHOT = "video_screenshot";
/**
* 录制完成后需要跳转的activity
*/
public final static String OVER_ACTIVITY_NAME = "over_activity_name";
/**
* 最大录制时间的key
*/
public final static String MEDIA_RECORDER_MAX_TIME_KEY = "media_recorder_max_time_key";
/**
* 最小录制时间的key
*/
public final static String MEDIA_RECORDER_MIN_TIME_KEY = "media_recorder_min_time_key";
/**
* 录制配置key
*/
public final static String MEDIA_RECORDER_CONFIG_KEY = "media_recorder_config_key";
private boolean GO_HOME;
private boolean startState;
private boolean NEED_FULL_SCREEN = false;
private RelativeLayout title_layout;
/**
* @param context
* @param overGOActivityName 录制结束后需要跳转的Activity全类名
*/
public static void goSmallVideoRecorder(Activity context, String overGOActivityName, MediaRecorderConfig mediaRecorderConfig) {
context.startActivity(new Intent(context, MediaRecorderActivity.class).putExtra(OVER_ACTIVITY_NAME, overGOActivityName).putExtra(MEDIA_RECORDER_CONFIG_KEY, mediaRecorderConfig));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); // 防止锁屏
initData();
loadViews();
}
private void initData() {
Intent intent = getIntent();
MediaRecorderConfig mediaRecorderConfig = intent.getParcelableExtra(MEDIA_RECORDER_CONFIG_KEY);
if (mediaRecorderConfig == null) {
return;
}
NEED_FULL_SCREEN = mediaRecorderConfig.getFullScreen();
RECORD_TIME_MAX = mediaRecorderConfig.getRecordTimeMax();
RECORD_TIME_MIN = mediaRecorderConfig.getRecordTimeMin();
MediaRecorderBase.MAX_FRAME_RATE = mediaRecorderConfig.getMaxFrameRate();
MediaRecorderBase.NEED_FULL_SCREEN = NEED_FULL_SCREEN;
MediaRecorderBase.MIN_FRAME_RATE = mediaRecorderConfig.getMinFrameRate();
MediaRecorderBase.SMALL_VIDEO_HEIGHT = mediaRecorderConfig.getSmallVideoHeight();
MediaRecorderBase.SMALL_VIDEO_WIDTH = mediaRecorderConfig.getSmallVideoWidth();
MediaRecorderBase.mVideoBitrate = mediaRecorderConfig.getVideoBitrate();
MediaRecorderBase.CAPTURE_THUMBNAILS_TIME = mediaRecorderConfig.getCaptureThumbnailsTime();
GO_HOME = mediaRecorderConfig.isGO_HOME();
}
/**
* 加载视图
*/
private void loadViews() {
setContentView(R.layout.activity_media_recorder);
// ~~~ 绑定控件
mSurfaceView = (SurfaceView) findViewById(R.id.record_preview);
title_layout = (RelativeLayout) findViewById(R.id.title_layout);
mCameraSwitch = (CheckBox) findViewById(R.id.record_camera_switcher);
mTitleNext = (ImageView) findViewById(R.id.title_next);
mProgressView = (ProgressView) findViewById(R.id.record_progress);
mRecordDelete = (CheckedTextView) findViewById(R.id.record_delete);
mRecordController = (TextView) findViewById(R.id.record_controller);
mBottomLayout = (RelativeLayout) findViewById(bottom_layout);
mRecordLed = (CheckBox) findViewById(R.id.record_camera_led);
// ~~~ 绑定事件
/*if (DeviceUtils.hasICS())
mSurfaceView.setOnTouchListener(mOnSurfaveViewTouchListener);*/
mTitleNext.setOnClickListener(this);
findViewById(R.id.title_back).setOnClickListener(this);
// mRecordDelete.setOnClickListener(this);
mRecordController.setOnTouchListener(mOnVideoControllerTouchListener);
// ~~~ 设置数据
// 是否支持前置摄像头
if (MediaRecorderBase.isSupportFrontCamera()) {
mCameraSwitch.setOnClickListener(this);
} else {
mCameraSwitch.setVisibility(View.GONE);
}
// 是否支持闪光灯
if (DeviceUtils.isSupportCameraLedFlash(getPackageManager())) {
mRecordLed.setOnClickListener(this);
} else {
mRecordLed.setVisibility(View.GONE);
}
mProgressView.setMaxDuration(RECORD_TIME_MAX);
mProgressView.setMinTime(RECORD_TIME_MIN);
}
/**
* 初始化画布
*/
private void initSurfaceView() {
if (NEED_FULL_SCREEN) {
mBottomLayout.setBackgroundColor(0);
title_layout.setBackgroundColor(getResources().getColor(R.color.full_title_color));
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mSurfaceView
.getLayoutParams();
lp.setMargins(0,0,0,0);
mSurfaceView.setLayoutParams(lp);
mProgressView.setBackgroundColor(getResources().getColor(R.color.full_progress_color));
} else {
final int w = DeviceUtils.getScreenWidth(this);
((RelativeLayout.LayoutParams) mBottomLayout.getLayoutParams()).topMargin = (int) (w / (MediaRecorderBase.SMALL_VIDEO_HEIGHT / (MediaRecorderBase.SMALL_VIDEO_WIDTH * 1.0f)));
int width = w;
int height = (int) (w * ((MediaRecorderBase.mSupportedPreviewWidth * 1.0f) / MediaRecorderBase.SMALL_VIDEO_HEIGHT));
//
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mSurfaceView
.getLayoutParams();
lp.width = width;
lp.height = height;
mSurfaceView.setLayoutParams(lp);
}
}
/**
* 初始化拍摄SDK
*/
private void initMediaRecorder() {
mMediaRecorder = new MediaRecorderNative();
mMediaRecorder.setOnErrorListener(this);
mMediaRecorder.setOnEncodeListener(this);
mMediaRecorder.setOnPreparedListener(this);
File f = new File(JianXiCamera.getVideoCachePath());
if (!FileUtils.checkFile(f)) {
f.mkdirs();
}
String key = String.valueOf(System.currentTimeMillis());
mMediaObject = mMediaRecorder.setOutputDirectory(key,
JianXiCamera.getVideoCachePath() + key);
mMediaRecorder.setSurfaceHolder(mSurfaceView.getHolder());
mMediaRecorder.prepare();
}
/**
* 点击屏幕录制
*/
private View.OnTouchListener mOnVideoControllerTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mMediaRecorder == null) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 检测是否手动对焦
// 判断是否已经超时
if (mMediaObject.getDuration() >= RECORD_TIME_MAX) {
return true;
}
// 取消回删
if (cancelDelete())
return true;
if (!startState) {
startState = true;
startRecord();
} else {
mMediaObject.buildMediaPart(mMediaRecorder.mCameraId);
mProgressView.setData(mMediaObject);
setStartUI();
mMediaRecorder.setRecordState(true);
}
break;
case MotionEvent.ACTION_UP:
mMediaRecorder.setRecordState(false);
if (mMediaObject.getDuration() >= RECORD_TIME_MAX) {
mTitleNext.performClick();
} else {
mMediaRecorder.setStopDate();
setStopUI();
}
// 暂停
/* if (mPressedStatus) {
// 检测是否已经完成
if (mMediaObject.getDuration() >= RECORD_TIME_MAX) {
mTitleNext.performClick();
}
}*/
break;
}
return true;
}
};
@Override
public void onResume() {
super.onResume();
if (mMediaRecorder == null) {
initMediaRecorder();
} else {
mRecordLed.setChecked(false);
mMediaRecorder.prepare();
mProgressView.setData(mMediaObject);
}
}
/*@Override
public void onPause() {
super.onPause();
stopRecord();
if (!mReleased) {
if (mMediaRecorder != null)
mMediaRecorder.release();
}
mReleased = false;
}*/
/**
* 开始录制
*/
private void startRecord() {
if (mMediaRecorder != null) {
MediaObject.MediaPart part = mMediaRecorder.startRecord();
if (part == null) {
return;
}
mProgressView.setData(mMediaObject);
}
setStartUI();
}
private void setStartUI() {
mPressedStatus = true;
// TODO 开始录制的图标
mRecordController.animate().scaleX(0.8f).scaleY(0.8f).setDuration(500).start();
if (mHandler != null) {
mHandler.removeMessages(HANDLE_INVALIDATE_PROGRESS);
mHandler.sendEmptyMessage(HANDLE_INVALIDATE_PROGRESS);
mHandler.removeMessages(HANDLE_STOP_RECORD);
mHandler.sendEmptyMessageDelayed(HANDLE_STOP_RECORD,
RECORD_TIME_MAX - mMediaObject.getDuration());
}
// mRecordDelete.setVisibility(View.GONE);
mCameraSwitch.setEnabled(false);
mRecordLed.setEnabled(false);
}
@Override
public void onBackPressed() {
/*if (mRecordDelete != null && mRecordDelete.isChecked()) {
cancelDelete();
return;
}*/
if (mMediaObject != null && mMediaObject.getDuration() > 1) {
// 未转码
new AlertDialog.Builder(this)
.setTitle(R.string.hint)
.setMessage(R.string.record_camera_exit_dialog_message)
.setNegativeButton(
R.string.record_camera_cancel_dialog_yes,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
mMediaObject.delete();
finish();
}
})
.setPositiveButton(R.string.record_camera_cancel_dialog_no,
null).setCancelable(false).show();
return;
}
if (mMediaObject != null)
mMediaObject.delete();
finish();
}
/**
* 停止录制
*/
private void stopRecord() {
if (mMediaRecorder != null) {
mMediaRecorder.stopRecord();
}
setStopUI();
}
private void setStopUI() {
mPressedStatus = false;
mRecordController.animate().scaleX(1).scaleY(1).setDuration(500).start();
// mRecordDelete.setVisibility(View.VISIBLE);
mCameraSwitch.setEnabled(true);
mRecordLed.setEnabled(true);
mHandler.removeMessages(HANDLE_STOP_RECORD);
checkStatus();
}
@Override
public void onClick(View v) {
final int id = v.getId();
if (mHandler.hasMessages(HANDLE_STOP_RECORD)) {
mHandler.removeMessages(HANDLE_STOP_RECORD);
}
// 处理开启回删后其他点击操作
if (id != R.id.record_delete) {
if (mMediaObject != null) {
MediaObject.MediaPart part = mMediaObject.getCurrentPart();
if (part != null) {
if (part.remove) {
part.remove = false;
// mRecordDelete.setChecked(false);
if (mProgressView != null)
mProgressView.invalidate();
}
}
}
}
if (id == R.id.title_back) {
onBackPressed();
} else if (id == R.id.record_camera_switcher) {// 前后摄像头切换
if (mRecordLed.isChecked()) {
if (mMediaRecorder != null) {
mMediaRecorder.toggleFlashMode();
}
mRecordLed.setChecked(false);
}
if (mMediaRecorder != null) {
mMediaRecorder.switchCamera();
}
if (mMediaRecorder.isFrontCamera()) {
mRecordLed.setEnabled(false);
} else {
mRecordLed.setEnabled(true);
}
} else if (id == R.id.record_camera_led) {// 闪光灯
// 开启前置摄像头以后不支持开启闪光灯
if (mMediaRecorder != null) {
if (mMediaRecorder.isFrontCamera()) {
return;
}
}
if (mMediaRecorder != null) {
mMediaRecorder.toggleFlashMode();
}
} else if (id == R.id.title_next) {// 停止录制
stopRecord();
/*finish();
overridePendingTransition(R.anim.push_bottom_in,
R.anim.push_bottom_out);*/
} else if (id == R.id.record_delete) {
// 取消回删
if (mMediaObject != null) {
MediaObject.MediaPart part = mMediaObject.getCurrentPart();
if (part != null) {
if (part.remove) {
part.remove = false;
mMediaObject.removePart(part, true);
// mRecordDelete.setChecked(false);
} else {
part.remove = true;
// mRecordDelete.setChecked(true);
}
}
if (mProgressView != null)
mProgressView.invalidate();
// 检测按钮状态
checkStatus();
}
}
}
/**
* 取消回删
*/
private boolean cancelDelete() {
if (mMediaObject != null) {
MediaObject.MediaPart part = mMediaObject.getCurrentPart();
if (part != null && part.remove) {
part.remove = false;
// mRecordDelete.setChecked(false);
if (mProgressView != null)
mProgressView.invalidate();
return true;
}
}
return false;
}
/**
* 检查录制时间显示/隐藏下一步按钮
*/
private int checkStatus() {
int duration = 0;
if (!isFinishing() && mMediaObject != null) {
duration = mMediaObject.getDuration();
if (duration < RECORD_TIME_MIN) {
if (duration == 0) {
mCameraSwitch.setVisibility(View.VISIBLE);
// mRecordDelete.setVisibility(View.GONE);
} else {
mCameraSwitch.setVisibility(View.GONE);
}
// 视频必须大于3秒
if (mTitleNext.getVisibility() != View.INVISIBLE)
mTitleNext.setVisibility(View.INVISIBLE);
} else {
// 下一步
if (mTitleNext.getVisibility() != View.VISIBLE) {
mTitleNext.setVisibility(View.VISIBLE);
}
}
}
return 0;
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case HANDLE_INVALIDATE_PROGRESS:
if (mMediaRecorder != null && !isFinishing()) {
if (mMediaObject != null && mMediaObject.getMedaParts() != null && mMediaObject.getDuration() >= RECORD_TIME_MAX) {
mTitleNext.performClick();
return;
}
if (mProgressView != null)
mProgressView.invalidate();
// if (mPressedStatus)
// titleText.setText(String.format("%.1f",
// mMediaRecorder.getDuration() / 1000F));
if (mPressedStatus)
sendEmptyMessageDelayed(0, 30);
}
break;
}
}
};
@Override
public void onEncodeStart() {
showProgress("", getString(R.string.record_camera_progress_message));
}
@Override
public void onEncodeProgress(int progress) {
}
/**
* 转码完成
*/
@Override
public void onEncodeComplete() {
hideProgress();
Intent intent = null;
try {
intent = new Intent(this, Class.forName(getIntent().getStringExtra(OVER_ACTIVITY_NAME)));
intent.putExtra(MediaRecorderActivity.OUTPUT_DIRECTORY, mMediaObject.getOutputDirectory());
intent.putExtra(MediaRecorderActivity.VIDEO_URI, mMediaObject.getOutputTempTranscodingVideoPath());
intent.putExtra(MediaRecorderActivity.VIDEO_SCREENSHOT, mMediaObject.getOutputVideoThumbPath());
intent.putExtra("go_home", GO_HOME);
startActivity(intent);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("需要传入录制完成后跳转的Activity的全类名");
}
finish();
}
/**
* 转码失败 检查sdcard是否可用检查分块是否存在
*/
@Override
public void onEncodeError() {
hideProgress();
Toast.makeText(this, R.string.record_video_transcoding_faild,
Toast.LENGTH_SHORT).show();
finish();
}
@Override
public void onVideoError(int what, int extra) {
}
@Override
public void onAudioError(int what, String message) {
}
@Override
public void onPrepared() {
initSurfaceView();
}
public void onFinished() {
finish();
}
protected ProgressDialog mProgressDialog;
public ProgressDialog showProgress(String title, String message) {
return showProgress(title, message, -1);
}
public ProgressDialog showProgress(String title, String message, int theme) {
if (mProgressDialog == null) {
if (theme > 0)
mProgressDialog = new ProgressDialog(this, theme);
else
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mProgressDialog.setCanceledOnTouchOutside(false);// 不能取消
mProgressDialog.setCancelable(false);
mProgressDialog.setIndeterminate(true);// 设置进度条是否不明确
}
if (!StringUtils.isEmpty(title))
mProgressDialog.setTitle(title);
mProgressDialog.setMessage(message);
mProgressDialog.show();
return mProgressDialog;
}
public void hideProgress() {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mMediaRecorder.release();
}
@Override
protected void onStop() {
super.onStop();
if (mMediaRecorder instanceof MediaRecorderNative) {
((MediaRecorderNative) mMediaRecorder).activityStop();
}
hideProgress();
mProgressDialog = null;
}
}

View File

@ -0,0 +1,285 @@
package com.mabeijianxi.smallvideorecord2.model;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by jian on 2016/8/25 17:03
* https://github.com/mabeijianxi
* mabeijianxi@gmail.com
*/
public final class MediaRecorderConfig implements Parcelable {
private final boolean FULL_SCREEN;
/**
* 录制时间
*/
private final int RECORD_TIME_MAX;
/**
* 最少录制时间
*/
private final int RECORD_TIME_MIN;
/**
* 小视频高度
* <p>注意宽度不能随意传需要传送手机摄像头手支持录制的视频高度注意是高度因为会选择具体原因不多解释
* 获取摄像头所支持的尺寸的方式是{@link android.graphics.Camera#getSupportedPreviewSizes()}
* 一般支持的尺寸的高度有2404807201080等具体值请用以上方法获取</p>
*/
private final int SMALL_VIDEO_HEIGHT;
/**
* 小视频宽度
*/
private final int SMALL_VIDEO_WIDTH;
/**
* 最大帧率
*/
private final int MAX_FRAME_RATE;
/**
* 最小帧率
*/
private final int MIN_FRAME_RATE;
/**
* 视频码率
*/
private final int VIDEO_BITRATE;
/**
* 录制后会剪切一帧缩略图并保存就是取时间轴上这个时间的画面
*/
private final int captureThumbnailsTime;
private final boolean GO_HOME;
private MediaRecorderConfig(Buidler buidler) {
this.FULL_SCREEN = buidler.FULL_SCREEN;
this.RECORD_TIME_MAX = buidler.RECORD_TIME_MAX;
this.RECORD_TIME_MIN = buidler.RECORD_TIME_MIN;
this.MAX_FRAME_RATE = buidler.MAX_FRAME_RATE;
this.captureThumbnailsTime = buidler.captureThumbnailsTime;
this.MIN_FRAME_RATE = buidler.MIN_FRAME_RATE;
this.SMALL_VIDEO_HEIGHT = buidler.SMALL_VIDEO_HEIGHT;
this.SMALL_VIDEO_WIDTH = buidler.SMALL_VIDEO_WIDTH;
this.VIDEO_BITRATE = buidler.VIDEO_BITRATE;
this.GO_HOME=buidler.GO_HOME;
}
protected MediaRecorderConfig(Parcel in) {
FULL_SCREEN = in.readByte() != 0;
RECORD_TIME_MAX = in.readInt();
RECORD_TIME_MIN = in.readInt();
SMALL_VIDEO_HEIGHT = in.readInt();
SMALL_VIDEO_WIDTH = in.readInt();
MAX_FRAME_RATE = in.readInt();
MIN_FRAME_RATE = in.readInt();
VIDEO_BITRATE = in.readInt();
captureThumbnailsTime = in.readInt();
GO_HOME = in.readByte() != 0;
}
public static final Creator<MediaRecorderConfig> CREATOR = new Creator<MediaRecorderConfig>() {
@Override
public MediaRecorderConfig createFromParcel(Parcel in) {
return new MediaRecorderConfig(in);
}
@Override
public MediaRecorderConfig[] newArray(int size) {
return new MediaRecorderConfig[size];
}
};
public boolean isGO_HOME() {
return GO_HOME;
}
public boolean getFullScreen() {
return FULL_SCREEN;
}
public int getCaptureThumbnailsTime() {
return captureThumbnailsTime;
}
public int getMaxFrameRate() {
return MAX_FRAME_RATE;
}
public int getMinFrameRate() {
return MIN_FRAME_RATE;
}
public int getRecordTimeMax() {
return RECORD_TIME_MAX;
}
public int getRecordTimeMin() {
return RECORD_TIME_MIN;
}
public int getSmallVideoHeight() {
return SMALL_VIDEO_HEIGHT;
}
public int getSmallVideoWidth() {
return SMALL_VIDEO_WIDTH;
}
public int getVideoBitrate() {
return VIDEO_BITRATE;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (FULL_SCREEN ? 1 : 0));
dest.writeInt(RECORD_TIME_MAX);
dest.writeInt(RECORD_TIME_MIN);
dest.writeInt(SMALL_VIDEO_HEIGHT);
dest.writeInt(SMALL_VIDEO_WIDTH);
dest.writeInt(MAX_FRAME_RATE);
dest.writeInt(MIN_FRAME_RATE);
dest.writeInt(VIDEO_BITRATE);
dest.writeInt(captureThumbnailsTime);
dest.writeByte((byte) (GO_HOME ? 1 : 0));
}
public static class Buidler {
/**
* 录制时间
*/
private int RECORD_TIME_MAX = 6 * 1000;
/**
* 小视频高度
* <p>注意宽度不能随意传需要传送手机摄像头手支持录制的视频高度注意是高度因为会选择具体原因不多解释
* 获取摄像头所支持的尺寸的方式是{@link android.graphics.Camera#getSupportedPreviewSizes()}
* 一般支持的尺寸的高度有2404807201080等具体值请用以上方法获取</p>
*/
private int SMALL_VIDEO_HEIGHT = 480;
/**
* 小视频宽度
*/
private int SMALL_VIDEO_WIDTH = 360;
/**
* 最大帧率
*/
private int MAX_FRAME_RATE = 20;
/**
* 最小帧率
*/
private int MIN_FRAME_RATE = 8;
/**
* 视频码率//todo 注意传入>0的值后码率模式将从VBR变成CBR
*/
private int VIDEO_BITRATE;
/**
* 录制后会剪切一帧缩略图并保存就是取时间轴上这个时间的画面
*/
private int captureThumbnailsTime = 1;
private boolean GO_HOME=false;
public int RECORD_TIME_MIN= (int) (1.5*1000);
private boolean FULL_SCREEN =false;
public MediaRecorderConfig build() {
return new MediaRecorderConfig(this);
}
/**
* @param captureThumbnailsTime 录制后会剪切一帧缩略图并保存就是取时间轴上这个时间的画面
* @return
*/
public Buidler captureThumbnailsTime(int captureThumbnailsTime) {
this.captureThumbnailsTime = captureThumbnailsTime;
return this;
}
/**
* @param MAX_FRAME_RATE 最大帧率(与视频清晰度大小息息相关)
* @return
*/
public Buidler maxFrameRate(int MAX_FRAME_RATE) {
this.MAX_FRAME_RATE = MAX_FRAME_RATE;
return this;
}
/**
* @param MIN_FRAME_RATE 最小帧率(与视频清晰度大小息息相关)
* @return
*/
public Buidler minFrameRate(int MIN_FRAME_RATE) {
this.MIN_FRAME_RATE = MIN_FRAME_RATE;
return this;
}
/**
* @param RECORD_TIME_MAX 录制时间
* @return
*/
public Buidler recordTimeMax(int RECORD_TIME_MAX) {
this.RECORD_TIME_MAX = RECORD_TIME_MAX;
return this;
}
/**
* @param RECORD_TIME_MIN 最少录制时间
* @return
*/
public Buidler recordTimeMin(int RECORD_TIME_MIN) {
this.RECORD_TIME_MIN = RECORD_TIME_MIN;
return this;
}
/**
* @param SMALL_VIDEO_HEIGHT
* @return
*/
public Buidler smallVideoHeight(int SMALL_VIDEO_HEIGHT) {
this.SMALL_VIDEO_HEIGHT = SMALL_VIDEO_HEIGHT;
return this;
}
/**
* @param SMALL_VIDEO_WIDTH
*
* @return
*/
public Buidler smallVideoWidth(int SMALL_VIDEO_WIDTH) {
this.SMALL_VIDEO_WIDTH = SMALL_VIDEO_WIDTH;
return this;
}
/**
* @param VIDEO_BITRATE 视频码率
* @return
*/
public Buidler videoBitrate(int VIDEO_BITRATE) {
this.VIDEO_BITRATE = VIDEO_BITRATE;
return this;
}
public Buidler goHome(boolean GO_HOME) {
this.GO_HOME = GO_HOME;
return this;
}
public Buidler fullScreen(boolean full) {
this.FULL_SCREEN =full;
return this;
}
}
}

View File

@ -0,0 +1,3 @@
dependencies {
implementation 'com.arthenica:mobile-ffmpeg-full:4.4'
}

7
www/capture.js Normal file
View File

@ -0,0 +1,7 @@
var exec = require('cordova/exec');
module.exports = {
capture(option, success, error) {
exec(success, error, 'capture-cordova-plugin', 'capture', [option]);
}
};