关于android:基于CameraX完成拍照和拍视频

背景:最近在做一个APP视频上传的我的项目,因为应用的是自家的服务器,内存有肯定的限度,而目前的手机大多分辨率较大,拍进去的视频几秒钟就好几兆,如何让压缩录制的视频,跟微信一样,因而查阅了一些材料,特此记下,避免本人忘记!

我之前大多应用Camera1和Camera2开发相机性能的时候须要调用非常复杂的API,而且因为Android手机的碎片化重大,不同手机对相机性能的反对度也不一样,因而很多做相机相干利用的公司都会封装本人的相机库来简化相机的应用步骤和解决兼容性问题。

之后谷歌为简化相机API的应用,推出了CameraX。最多兼容到Android 5.0,底层调用的也是Camera2,不过比Camera2用起来更简略,而且能够绑定生命周期,从而能够主动的解决相机的开启开释等工作。

dependencies {
   // CameraX 外围库应用 camera2 实现
    implementation "androidx.camera:camera-camera2:1.0.0-beta03"
    // 能够应用CameraView
    implementation "androidx.camera:camera-view:1.0.0-alpha10"
    // 能够应用供应商扩大
    implementation "androidx.camera:camera-extensions:1.0.0-alpha10"
    //camerax的生命周期库
    implementation "androidx.camera:camera-lifecycle:1.0.0-beta03"
    }

配置状态
预览配置:Preview用于相机预览的时候显示预览画面。

Preview preview = new Preview.Builder()
                //设置宽高比
                .setTargetAspectRatio(screenAspectRatio)
                //设置以后屏幕的旋转
                .setTargetRotation(rotation)
                .build();

照相配置:ImageCapture 用于拍照,并将图片保留

ImageCapture imageCapture = new ImageCapture.Builder()
                //优化捕捉速度,可能升高图片品质
                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                //设置宽高比
                .setTargetAspectRatio(screenAspectRatio)
                //设置初始的旋转角度
                .setTargetRotation(rotation)
                .build();

录制视频设置:VideoCapture 用来录制视频和保留视频,宽高比和分辨率设置一个就能够了,不要同时设置否则报错。依据理论的需要来设置,如果对宽高比要求高就设置宽高比,反之就设置分辨率

这个中央是重点,录制视频的时候能够设置分辨率、帧率和bit率进行批改录制视频的大小

VideoCapture videoCapture = new VideoCaptureConfig.Builder()
                //设置以后旋转
                .setTargetRotation(rotation)
                //设置宽高比
                .setTargetAspectRatio(screenAspectRatio)
                //分辨率
                //.setTargetResolution(resolution)
                //视频帧率  越高视频体积越大
                .setVideoFrameRate(25)
                //bit率  越大视频体积越大
                .setBitRate(3 * 1024 * 1024)
                .build();

绑定到生命周期:ProcessCameraProvider 是一个单例类,能够把相机的生命周期绑定到任何LifecycleOwner类中。AppCompatActivity和Fragment都是LifecycleOwner

//Future示意一个异步的工作,ListenableFuture能够监听这个工作,当工作实现的时候执行回调
 ListenableFuture<ProcessCameraProvider> cameraProviderFuture =
                ProcessCameraProvider.getInstance(this);
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();

//从新绑定之前必须先勾销绑定
cameraProvider.unbindAll();

Camera camera = cameraProvider.bindToLifecycle(CameraActivity.this,
                cameraSelector,preview,imageCapture,videoCapture);

OK预览,照相,录视频的配置和绑定到生命周期的工作就实现了

预览的时候须要显示到一个View控件上吧,CameraX中提供了一个PreviewView用来显示预览画面。其外部封装了TextureView和SurfaceView,能够依据不同的模式来抉择其外部应用TextureView还是SurfaceView来显示。

xml中增加PreviewView,并在代码中将其附加到后面创立进去的Preview这个实例上

<androidx.camera.view.PreviewView
        android:id="@+id/view_finder"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

preview.setSurfaceProvider(mPreviewView.createSurfaceProvider(camera .getCameraInfo()));
这样当咱们进入该页面的时候就能够看到相机的预览成果呢,接下来就是执行拍照和录制的性能了

当初咱们就一起看看如何实现拍照

//创立图片保留的文件地址
  File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath(),
          System.currentTimeMillis() + ".jpeg");
  ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build();
  mImageCapture.takePicture(outputFileOptions,mExecutorService , new ImageCapture.OnImageSavedCallback() {
      @Override
      public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
          Uri savedUri = outputFileResults.getSavedUri();
          if(savedUri == null){
              savedUri = Uri.fromFile(file);
          }
          outputFilePath = file.getAbsolutePath();
          onFileSaved(savedUri);
      }

      @Override
      public void onError(@NonNull ImageCaptureException exception) {
          Log.e(TAG, "Photo capture failed: "+exception.getMessage(), exception);
      }
  });
//将后面保留的文件增加到媒体中
private void onFileSaved(Uri savedUri) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            sendBroadcast(new Intent(android.hardware.Camera.ACTION_NEW_PICTURE, savedUri));
        }
        String mimeTypeFromExtension = MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap
                .getFileExtensionFromUrl(savedUri.getPath()));
        MediaScannerConnection.scanFile(getApplicationContext(),
                new String[]{new File(savedUri.getPath()).getAbsolutePath()},
                new String[]{mimeTypeFromExtension}, new MediaScannerConnection.OnScanCompletedListener() {
                    @Override
                    public void onScanCompleted(String path, Uri uri) {
                        Log.d(TAG, "Image capture scanned into media store: $uri"+uri);
                    }
                });
        PreviewActivity.start(this, outputFilePath, !takingPicture);
    }

1、调用ImageCapture的takePicture办法来拍照
2、传入一个文件地址用来保留拍好的照片
3、onImageSaved办法是照片曾经拍好并存好之后的回调
4、onFileSaved办法中将后面保留的文件增加到媒体中,最初跳转到预览界面。

录制视频
和拍照相似

//创立视频保留的文件地址
File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath(),
        System.currentTimeMillis() + ".mp4");
mVideoCapture.startRecording(file, Executors.newSingleThreadExecutor(), new VideoCapture.OnVideoSavedCallback() {
    @Override
    public void onVideoSaved(@NonNull File file) {
        outputFilePath = file.getAbsolutePath();
        onFileSaved(Uri.fromFile(file));
    }

    @Override
    public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) {
        Log.i(TAG,message);
    }
});

1、应用VideoCapture的startRecording办法来录视频
2、传入一个File文件用来保留视频,
3、录制实现之后回调onVideoSaved办法,并返回该文件的实例。
4、调用onFileSaved办法将后面保留的文件增加到媒体中,最初跳转到预览界面。
5、达到录制工夫的时候,须要调用videoCapture.stopRecording();办法来进行录像。

当初根本就实现了拍照和录制视频的性能了,下一篇再记录一下CameraView的应用常识!

注:本文章常识大部分都采集于大佬们的博客,我只是在此做常识笔记,避免本人忘记!不用于任何商业用途!
原著地址:https://zhuanlan.zhihu.com/p/…

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理