如何在android中录制视频的同时在视频上绘图,并保存视频和绘图?

Mar*_*unG 5 java android drawing opengl-es-2.0 camera2

我正在尝试开发一款应用程序,允许我在录制视频时在视频上绘图,然后将录制内容和视频保存在一个 mp4 文件中以供以后使用。另外,我想使用camera2库,特别是我需要我的应用程序在高于API 21的设备上运行,并且我总是避免使用已弃用的库。

我尝试了很多方法来做到这一点,包括在 FFmpeg 中放置了 TextureView.getBitmap() (来自相机)的叠加层和从画布中获取的位图。它可以工作,但由于它是一个缓慢的功能,视频无法捕获足够的帧(甚至没有 25 fps),而且运行速度非常快。我希望也包括音频。

我考虑过 MediaProjection 库,但我不确定它是否可以捕获包含相机的布局和仅在其 VirtualDisplay 内的绘图,因为应用程序用户也可以在视频上添加文本,而且我不想要键盘出现。

请帮助,已经进行了一周的研究,但我发现没有什么对我有用的。

PS:如果用户按下“停止录制”按钮后包含一点处理时间,我不会有问题。

编辑:

现在,在 Eddy 的回答之后,我正在使用 Shadercam 应用程序在相机表面上绘图,因为该应用程序执行视频渲染,而要做的解决方法是将我的画布渲染为位图,然后渲染为 GL 纹理,但是我无法成功地做到这一点。我需要你们的帮助,我需要完成应用程序:S

我正在使用shadercam库(https://github.com/googlecreativelab/shadercam),并用以下代码替换了“ExampleRenderer”文件:

public class WriteDrawRenderer extends CameraRenderer
{
    private float offsetR = 1f;
    private float offsetG = 1f;
    private float offsetB = 1f;

    private float touchX = 1000000000;
    private float touchY = 1000000000;

    private  Bitmap textBitmap;

    private int textureId;

    private boolean isFirstTime = true;

    //creates a new canvas that will draw into a bitmap instead of rendering into the screen
    private Canvas bitmapCanvas;

    /**
     * By not modifying anything, our default shaders will be used in the assets folder of shadercam.
     *
     * Base all shaders off those, since there are some default uniforms/textures that will
     * be passed every time for the camera coordinates and texture coordinates
     */
    public WriteDrawRenderer(Context context, SurfaceTexture previewSurface, int width, int height)
    {
        super(context, previewSurface, width, height, "touchcolor.frag.glsl", "touchcolor.vert.glsl");
        //other setup if need be done here


    }

    /**
     * we override {@link #setUniformsAndAttribs()} and make sure to call the super so we can add
     * our own uniforms to our shaders here. CameraRenderer handles the rest for us automatically
     */
    @Override
    protected void setUniformsAndAttribs()
    {
        super.setUniformsAndAttribs();

        int offsetRLoc = GLES20.glGetUniformLocation(mCameraShaderProgram, "offsetR");
        int offsetGLoc = GLES20.glGetUniformLocation(mCameraShaderProgram, "offsetG");
        int offsetBLoc = GLES20.glGetUniformLocation(mCameraShaderProgram, "offsetB");

        GLES20.glUniform1f(offsetRLoc, offsetR);
        GLES20.glUniform1f(offsetGLoc, offsetG);
        GLES20.glUniform1f(offsetBLoc, offsetB);

        if (touchX < 1000000000 && touchY < 1000000000)
        {
            //creates a Paint object
            Paint yellowPaint = new Paint();
            //makes it yellow
            yellowPaint.setColor(Color.YELLOW);
            //sets the anti-aliasing for texts
            yellowPaint.setAntiAlias(true);
            yellowPaint.setTextSize(70);

            if (isFirstTime)
            {
                textBitmap = Bitmap.createBitmap(mSurfaceWidth, mSurfaceHeight, Bitmap.Config.ARGB_8888);
                bitmapCanvas = new Canvas(textBitmap);
            }

            bitmapCanvas.drawText("Test Text", touchX, touchY, yellowPaint);

            if (isFirstTime)
            {
                textureId = addTexture(textBitmap, "textBitmap");
                isFirstTime = false;
            }
            else
            {
                updateTexture(textureId, textBitmap);
            }

            touchX = 1000000000;
            touchY = 1000000000;
        }
    }

    /**
     * take touch points on that textureview and turn them into multipliers for the color channels
     * of our shader, simple, yet effective way to illustrate how easy it is to integrate app
     * interaction into our glsl shaders
     * @param rawX raw x on screen
     * @param rawY raw y on screen
     */
    public void setTouchPoint(float rawX, float rawY)
    {
        this.touchX = rawX;
        this.touchY = rawY;
    }
}
Run Code Online (Sandbox Code Playgroud)

请帮助大家,已经一个月了,我仍然坚持使用同一个应用程序:(并且对 opengl 不了解。两周了,我尝试在我的应用程序中使用这个项目,但视频上没有渲染任何内容。

提前致谢!

Edd*_*ala 0

这是一个应该可行的粗略轮廓,但这需要相当多的工作:

  1. 设置 android.media.MediaRecorder 来录制视频和音频
  2. 从 MediaRecorder 获取 Surface 并从中设置 EGLImage ( https://developer.android.com/reference/android/opengl/EGL14.html#eglCreateWindowSurface(android.opengl.EGLDisplay , android.opengl.EGLConfig, java.lang .Object, int[], int) ); 为此,您需要完整的 OpenGL 上下文和设置。然后您需要将该 EGLImage 设置为渲染目标。
  3. 在该 GL 上下文中创建 SurfaceTexture。
  4. 配置相机将数据发送到该 SurfaceTexture
  5. 启动媒体记录器
  6. 在从相机接收到的每一帧上,将用户完成的绘图转换为 GL 纹理,并将相机纹理和用户绘图进行合成。
  7. 最后调用glSwapBuffers将合成帧发送到录像机