4

ビデオの録画中に描画し、後で使用するために録画とビデオの両方を 1 つの mp4 ファイルに保存できるアプリを開発しようとしています。また、camera2 ライブラリを使用したいと考えています。特に、API 21 以降のデバイスでアプリを実行する必要があるため、非推奨のライブラリを常に避けています。

TextureView.getBitmap() (カメラから) のオーバーレイとキャンバスから取得したビットマップを配置した FFmpeg など、多くの方法を試しました。それは機能しましたが、遅い機能であるため、ビデオは十分なフレーム (25 fps でさえ) をキャッチできず、非常に高速に実行されました。音声も入れてほしい。

MediaProjection ライブラリについて考えましたが、アプリのユーザーがビデオにテキストを追加する可能性があり、キーボードが必要ないため、カメラとその VirtualDisplay 内でのみ描画を含むレイアウトをキャプチャできるかどうかはわかりません。現れる。

助けてください、1週間の調査でしたが、うまくいくものは何も見つかりませんでした.

PS: ユーザーが「記録の停止」ボタンを押した後、処理時間が少し含まれていても問題はありません。

編集:

Eddy's Answerの後、アプリがビデオレンダリングを行うため、shadercamアプリを使用してカメラ表面に描画しています。回避策は、キャンバスをビットマップにレンダリングしてからGLテクスチャにレンダリングすることですが、できませんそれを成功させるために。私はあなたの助けが必要です、私はアプリを完成させる必要があります:S

私はシェーダーカム ライブラリ ( 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;
    }
}

みんな助けてください、それは1か月経ちましたが、私はまだ同じアプリで立ち往生しています:(そしてopenglについてはわかりません.2週間、私は自分のアプリにこのプロジェクトを使用しようとしていますが、ビデオに何もレンダリングされていません.

前もって感謝します!

4

1 に答える 1

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. MediaRecorder を起動する
  6. カメラから受信した各フレームで、ユーザーが行った描画を GL テクスチャに変換し、カメラ テクスチャとユーザー描画を合成します。
  7. 最後に、glSwapBuffers を呼び出して、合成されたフレームをビデオ レコーダーに送信します。
于 2016-10-24T00:53:59.217 に答える