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搭建服务器

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