camera特效app(安卓)

文章目录

  • 1.前言:
  • 2. 效果预览:
  • 3.特效视频制作及上传
    • 3.1特效视频格式
    • 3.2视频上传到网站
    • 3.3 发布博客
  • 4.camera使用
  • 5.项目源码

1.前言:

相信大家都看过直播,直播中的礼物特效非常的炫酷,今天就教大家如何实现这一过程。其原理就是在摄像头画面上播放透明的特效视频。首先需要准备好mp4格式的特效视频。然后使用opengles进行渲染,实现透明化。当然,由于没有服务器,只能白嫖了。只需要把制作好的特效视频上传到好看视频网站上面,通过抓包拿到播放地址,然后将地址上传到一篇博客上面即可。启动app时首先会爬取该博客上面的视频播放地址。通过这种方法即可以减小app的体积(仅有3.5M),又无需自己购买服务器。后期如果需要更改或修改特效视频,只需要修改博客上面的播放地址即可。

2. 效果预览:

app下载地址:https://www.pgyer.com/T6he

3.特效视频制作及上传

3.1特效视频格式

特效视频的制作也很简单,视频格式如下所示:

camera特效app(安卓)_第1张图片
视频的上半部分为我们想要的特效视频,下半部分为透明度,其值越接近255,则表示越不透明。在使用opengles渲染视频的时候,只需要把下半部分的像素值作为其透明度即可。

3.2视频上传到网站

关于视频如何上传到好看视频网站,已经如何抓包获取视频播放地址,我在之前的一篇博客上面已经详细的说明了,如果不明白可前往查看。

3.3 发布博客

上传完视频拿到播放地址以后,只需要发布一篇博客,并将视频的播放地址都发布到该博客上面即可。博客内容如下所示:
camera特效app(安卓)_第2张图片
为了app自动获取特效的名称,需要在播放地址后面加上特效的名字,这样app特效的下拉框中就会自动填写这些特效名字。

4.camera使用

使用camerax来显示摄像头画面。camerax相比于camera2更加方便,兼容性更广。
使用camerax首先需要添加摄像头权限

<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />

添加相关依赖:

    //CameraX
    def camerax_version = "1.1.0-beta03"
// CameraX core library using camera2 implementation
    implementation "androidx.camera:camera-camera2:$camerax_version"
// CameraX Lifecycle Library
    implementation "androidx.camera:camera-lifecycle:$camerax_version"
// CameraX View class
    implementation "androidx.camera:camera-view:1.0.0-alpha24"

开启摄像头代码:

//开启摄像头
if(allPermissionsGranted()){
	startCamera(); //start camera if permission has been granted by user
} else{
	ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, 1001);
}

/**
 * 获取摄像头权限
 */
private final String[] REQUIRED_PERMISSIONS = new String[]{"android.permission.CAMERA", "android.permission.WRITE_EXTERNAL_STORAGE"};
private boolean allPermissionsGranted() {
    for (String permission : REQUIRED_PERMISSIONS) {
        if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }
    return true;
}


/**
* 开始预览
*/
private CameraControl cameraControl;
private Executor executor = Executors.newSingleThreadExecutor();
private void startCamera() {
   ListenableFuture<ProcessCameraProvider> cameraProviderFuture =
           ProcessCameraProvider.getInstance(this);
   ((ListenableFuture<?>) cameraProviderFuture).addListener(new Runnable() {
       @SuppressLint("RestrictedApi")
       @Override
       public void run() {
           try {

               ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
                       //.setBackpressureStrategy(ImageAnalysis.STRATEGY_BLOCK_PRODUCER)//阻塞模式
                       //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888)
                       //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
                       .build();
               imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
                   @Override
                   public void analyze(@NonNull @NotNull ImageProxy image) {

                       //yuv图像数据转bitmap
                       ImageProxy.PlaneProxy[] planes = image.getPlanes();
                       //cameraX 获取yuv
                       ByteBuffer yBuffer = planes[0].getBuffer();
                       ByteBuffer uBuffer = planes[1].getBuffer();
                       ByteBuffer vBuffer = planes[2].getBuffer();

                       int ySize = yBuffer.remaining();
                       int uSize = uBuffer.remaining();
                       int vSize = vBuffer.remaining();

                       byte[] nv21 = new byte[ySize + uSize + vSize];

                       yBuffer.get(nv21, 0, ySize);
                       vBuffer.get(nv21, ySize, vSize);
                       uBuffer.get(nv21, ySize + vSize, uSize);
                       //获取yuvImage
                       YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, image.getWidth(), image.getHeight(), null);
                       //输出流
                       ByteArrayOutputStream out = new ByteArrayOutputStream();
                       //压缩写入out
                       yuvImage.compressToJpeg(new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight()), 50, out);
                       //转数组
                       byte[] imageBytes = out.toByteArray();
                       //生成bitmap
                       Bitmap bmp = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);

//                            Bitmap rotateBitmap=null;

//                            Dector(bmp);

//                            Message message=new Message();
//                            message.what=2;
//                            message.obj=FPS;
//                            handler.sendMessage(message);


                       image.close();
                   }
               });



               //将相机的生命周期和activity的生命周期绑定,camerax 会自己释放
               ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
               Preview preview = new Preview.Builder().build();
               //创建图片的 capture
               ImageCapture mImageCapture = new ImageCapture.Builder()
                       .setFlashMode(ImageCapture.FLASH_MODE_OFF)
                       .build();
               //选择前置摄像头
               CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
               // Unbind use cases before rebinding
               cameraProvider.unbindAll();

               // Bind use cases to camera
               //参数中如果有mImageCapture才能拍照,否则会报下错
               //Not bound to a valid Camera [ImageCapture:androidx.camera.core.ImageCapture-bce6e930-b637-40ee-b9b9-
               Camera camera = cameraProvider.bindToLifecycle(MainActivity.this, cameraSelector, preview, imageAnalysis,mImageCapture);

               cameraControl = camera.getCameraControl();
               cameraControl.setLinearZoom(0.1f);
               preview.setSurfaceProvider(pvCameraPreview.getSurfaceProvider());
           } catch (ExecutionException e) {
               e.printStackTrace();
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }, ContextCompat.getMainExecutor(this));
}

opengl片源渲染器代码:

"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;" +
"uniform samplerExternalOES textureSampler;" +
"varying vec2 textureCoordinate;" +

"void main(){" +
"vec4 mycolor=texture2D(textureSampler,vec2(textureCoordinate.x,textureCoordinate.y/2.0));"+
"vec4 Alpha=texture2D(textureSampler,vec2(textureCoordinate.x,textureCoordinate.y/2.0+0.5));"+
"float alpha=1.0-(mycolor.r+mycolor.g+mycolor.b)/3.0;"+

"gl_FragColor=vec4(1.0-mycolor.rgb,alpha);" +

"}";

5.项目源码

手机端如果打不开链接,可以使用电脑试一下。
gitee地址:https://gitee.com/mqwdasddqw/SpecialEffect3

你可能感兴趣的:(android,java,摄像头特效,opengl,透明视频)