Android使用七牛實現錄像加時間水印和拍照(截幀回調)

需求:

  現在有個需求,就是需要使用手機實現錄像,在視頻中添加時間水印,並且在錄像過程中,實現拍照功能,在網上查找了資料,決定使用七牛的SDK來實現這個功能,在錄像中拍照,在七牛中使用 截幀回調可以實現。

效果:
開始錄像

在這裏插入圖片描述

拍照

在這裏插入圖片描述

保存視頻

在這裏插入圖片描述
在這裏插入圖片描述

例子下載

https://download.csdn.net/download/ljp345775/12543119

思路:

  實現錄像和拍照的功能不算很難,照着官方的開發文檔弄就可以了,就是這個在錄像視頻中添加時間水印,我的思路是通過服務每秒發送一次廣播,然後,接收到廣播以後,就改變一次水印。跟我以前寫過一篇通過服務和廣播實現多界面共享計時器的思路差不多,有興趣的可以看一下:android中利用service和廣播實現多個activity共享計時器

實現步驟:
  1. 導入jar包
    從官網下載需要的jar包,然後導入到項目
    官方地址:https://github.com/pili-engineering/PLDroidShortVideo/archive/v3.1.1.zip
    如果覺得官方下載的慢,也可以下載我寫的例子,裏面有我下載好的。
    官方的jar包所在位置如下:
    在這裏插入圖片描述導入到項目中以後如下圖:
    在這裏插入圖片描述
  2. 初始化SDK
public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        //初始化
        PLShortVideoEnv.init(getApplicationContext());
    }
}
  1. 申請權限
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.hardware.camera.autofocus" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
  1. 主要代碼實現
  • 初始化錄製對象
    /**
     * 初始化錄製對象
     */
    private void initRecorder(String name) {
        mShortVideoRecorder = new PLShortVideoRecorder();
        mShortVideoRecorder.setRecordStateListener(this);
        // 攝像頭採集選項
        PLCameraSetting cameraSetting = new PLCameraSetting();
        //後攝像頭
        cameraSetting.setCameraId(PLCameraSetting.CAMERA_FACING_ID.CAMERA_FACING_BACK);
        cameraSetting.setCameraPreviewSizeRatio(PLCameraSetting.CAMERA_PREVIEW_SIZE_RATIO.RATIO_16_9);
        cameraSetting.setCameraPreviewSizeLevel(PLCameraSetting.CAMERA_PREVIEW_SIZE_LEVEL.PREVIEW_SIZE_LEVEL_720P);
        // 麥克風採集選項
        PLMicrophoneSetting microphoneSetting = new PLMicrophoneSetting();
        // 視頻編碼選項
        PLVideoEncodeSetting videoEncodeSetting = new PLVideoEncodeSetting(this);
        videoEncodeSetting.setEncodingSizeLevel(PLVideoEncodeSetting.VIDEO_ENCODING_SIZE_LEVEL.VIDEO_ENCODING_SIZE_LEVEL_480P_2); // 480x480
        videoEncodeSetting.setEncodingBitrate(1000 * 1024); // 1000kbps
        videoEncodeSetting.setEncodingFps(25);
        videoEncodeSetting.setHWCodecEnabled(true); // true:硬編 false:軟編
        // 音頻編碼選項
        PLAudioEncodeSetting audioEncodeSetting = new PLAudioEncodeSetting();
        audioEncodeSetting.setHWCodecEnabled(true); // true:硬編 false:軟編
        // 美顏選項
//        PLFaceBeautySetting faceBeautySetting = new PLFaceBeautySetting(1.0f, 0.5f, 0.5f);
        // 錄製選項
        recordSetting = new PLRecordSetting();
        recordSetting.setMaxRecordDuration(600 * 1000); // 10s

        String s = FileUtils.getVideoPath(mActivity, "test");

        recordSetting.setVideoCacheDir(getRootPath(mActivity));
        recordSetting.setVideoFilepath(s);
        // 設置錄製速度 (默認爲 1.0)
//        PLShortVideoRecorder.setRecordSpeed(1.0);
        mShortVideoRecorder.prepare(glsurfaceview, cameraSetting, microphoneSetting,
                videoEncodeSetting, audioEncodeSetting, null, recordSetting);
        //用來設置時間水印
        mWatermarkSetting = new PLWatermarkSetting();
    }

  • 拍照
    /**
     * ===============截圖
     */
    private void screenshot() {

        mShortVideoRecorder.captureFrame(new PLCaptureFrameListener() {
            @Override
            public void onFrameCaptured(PLVideoFrame capturedFrame) {
                if (capturedFrame == null) {
                    return;
                }
                Log.i("aaa", "captured frame width: " + capturedFrame.getWidth() + " height: " + capturedFrame.getHeight() + " timestamp: " + capturedFrame.getTimestampMs());
                try {
                    String photoName = getPhotoName();
                    String picturePath = getRootFile(mActivity) + "/test/" + photoName;
                    Log.e("aaa", "onFrameCaptured: " + picturePath);
                    FileOutputStream fos = new FileOutputStream(picturePath);
                    capturedFrame.toBitmap().compress(Bitmap.CompressFormat.JPEG, 100, fos);
                    fos.close();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Log.e("aaa", "圖片以保存");
                            Toast.makeText(mActivity, photoName + " 保存成功", Toast.LENGTH_SHORT).show();
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

  • 視頻保存
  /**
     * =======保存視頻
     */
    private void stopAndSaveVideo() {
        // 結束一段視頻
        mShortVideoRecorder.endSection();

        mShortVideoRecorder.concatSections(new PLVideoSaveListener() {
            @Override
            public void onSaveVideoSuccess(String s) {
                Log.e("aaa", "onSaveVideoSuccess: " + s);

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showToast(mActivity, "視頻保存完成");
                    }
                });
            }

            @Override
            public void onSaveVideoFailed(int i) {
                Log.e("aaa", "onSaveVideoFailed: " + i);
            }

            @Override
            public void onSaveVideoCanceled() {
                Log.e("aaa", "onSaveVideoCanceled: ");
            }

            @Override
            public void onProgressUpdate(final float v) {
                Log.e("aaa", "onProgressUpdate: " + v);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtil.showToast(mActivity, "" + v);
                    }
                });
            }
        });
    }
  • 廣播接收器
    public class TimeReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String intentAction = intent.getAction();
            if (intentAction.equals("com.ljp.recorddemo.service.timer")) {
                String time = intent.getStringExtra("time");
                Bitmap bitmap = fromText(50, time);
                mWatermarkSetting.setPosition(0.50f, 0.05f);
                mWatermarkSetting.setBitmap(bitmap);
                mShortVideoRecorder.setWatermark(mWatermarkSetting);
            }
        }
    }
  • 服務
/**
 * 作者:Administrator
 * 時間:2020/6/22 0022 13:08
 * 描述:時間服務
 */
public class TimerService extends Service {

    private Timer timer = null;
    private TimerTask timerTask = null;
    private int i = 0;

    @Override
    public void onCreate() {
        super.onCreate();
        //在創建service的時候開始計時
        if(timer==null&&timerTask==null){
            timer = new Timer();
            timerTask = new TimerTask() {
                @Override
                public void run() {
                    i++;
                    //沒執行一次就發送一次廣播
                    Intent intent = new Intent();
                    String time1 = FileUtils.getTime1();
                    intent.putExtra("time", time1);
                    intent.setAction("com.ljp.recorddemo.service.timer");
                    sendBroadcast(intent);
                }
            };
            timer.schedule(timerTask,0,1000);
        }

    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        if(timerTask!=null){
            timerTask.cancel();
            timerTask=null;
        }
        if(timer!=null){
            timer.cancel();
            timer=null;
        }
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
額外功能:

  在這個例子中,需要申請權限,我使用的是嚴振杰老師的permission:2.0.0-rc11,比較好用,我還發現了一個老師的另外一個好用的項目,就是AndServer,就是在手機端搭建服務器的,我也寫了一個例子,有興趣的可以看一下
    Android利用Andserver搭建服務器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章