Media Recorder mit Google Vision API

Ich benutze das FaceTracker sample von der Android Vision API. Es treten jedoch Schwierigkeiten beim Aufzeichnen von Videos auf, während die Overlays darauf gezeichnet sind.

Eine Möglichkeit besteht darin, Bitmaps als Bilder zu speichern und sie mit FFmpeg oder Xuggler zu verarbeiten, um sie als Videos zusammenzuführen. Ich frage mich jedoch, ob es eine bessere Lösung für dieses Problem gibt, wenn wir Videos zur Laufzeit aufnehmen können, während die Vorschau projiziert wird.

Update 1: Ich habe das @ aktualisie folgend class mit Media Recorder, aber die Aufnahme funktioniert immer noch nicht. Wenn ich die Funktion triggerRecording () aufrufe, wird der folgende Fehler ausgegeben:

MediaRecorder: Start in ungültigem Zustand aufgerufen: 4

und ich habe die Berechtigung zum externen Speichern in der Manifest-Datei.

Update 2:

Ich habe das oben genannte Problem im Code behoben und den setupMediaRecorder () in den onSurfaceCreated-Rückruf verschoben. Wenn ich jedoch die Aufzeichnung beende, wird die Laufzeitausnahme ausgelöst. Laut demDokumentatio Wenn keine Video- / Audiodaten vorhanden sind, wird eine Laufzeitausnahme ausgelöst.

Also, was fehle ich hier?

public class CameraSourcePreview extends ViewGroup {
    private static final String TAG = "CameraSourcePreview";

    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

    static {
        ORIENTATIONS.append(Surface.ROTATION_0, 90);
        ORIENTATIONS.append(Surface.ROTATION_90, 0);
        ORIENTATIONS.append(Surface.ROTATION_180, 270);
        ORIENTATIONS.append(Surface.ROTATION_270, 180);
    }

    private MediaRecorder mMediaRecorder;
    /**
     * Whether the app is recording video now
     */
    private boolean mIsRecordingVideo;

    private Context mContext;
    private SurfaceView mSurfaceView;
    private boolean mStartRequested;
    private boolean mSurfaceAvailable;
    private CameraSource mCameraSource;

    private GraphicOverlay mOverlay;

    public CameraSourcePreview(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        mStartRequested = false;
        mSurfaceAvailable = false;

        mSurfaceView = new SurfaceView(context);

        mSurfaceView.getHolder().addCallback(new SurfaceCallback());

        addView(mSurfaceView);

        mMediaRecorder = new MediaRecorder();
    }

    private void setUpMediaRecorder() throws IOException {
        mMediaRecorder.setPreviewDisplay(mSurfaceView.getHolder().getSurface());
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);

        mMediaRecorder.setOutputFile(Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_DCIM + File.separator + System.currentTimeMillis() + ".mp4");
        mMediaRecorder.setVideoEncodingBitRate(10000000);
        mMediaRecorder.setVideoFrameRate(30);
        mMediaRecorder.setVideoSize(480, 640);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        //int rotation = mContext.getWindowManager().getDefaultDisplay().getRotation();
        //int orientation = ORIENTATIONS.get(rotation);
        mMediaRecorder.setOrientationHint(ORIENTATIONS.get(0));
        mMediaRecorder.prepare();

        mMediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
            @Override
            public void onError(MediaRecorder mr, int what, int extra) {
                Timber.d(mr.toString() + " : what[" + what + "]" + " Extras[" + extra + "]");
            }
        });
    }

    public void start(CameraSource cameraSource) throws IOException {
        if (cameraSource == null) {
            stop();
        }

        mCameraSource = cameraSource;

        if (mCameraSource != null) {
            mStartRequested = true;
            startIfReady();
        }
    }

    public void start(CameraSource cameraSource, GraphicOverlay overlay) throws IOException {
        mOverlay = overlay;
        start(cameraSource);
    }

    public void stop() {
        if (mCameraSource != null) {
            mCameraSource.stop();
        }
    }

    public void release() {
        if (mCameraSource != null) {
            mCameraSource.release();
            mCameraSource = null;
        }
    }

    private void startIfReady() throws IOException {
        if (mStartRequested && mSurfaceAvailable) {
            mCameraSource.start(mSurfaceView.getHolder());
            if (mOverlay != null) {
                Size size = mCameraSource.getPreviewSize();
                int min = Math.min(size.getWidth(), size.getHeight());
                int max = Math.max(size.getWidth(), size.getHeight());
                if (isPortraitMode()) {
                    // Swap width and height sizes when in portrait, since it will be rotated by
                    // 90 degrees
                    mOverlay.setCameraInfo(min, max, mCameraSource.getCameraFacing());
                } else {
                    mOverlay.setCameraInfo(max, min, mCameraSource.getCameraFacing());
                }
                mOverlay.clear();
            }

            mStartRequested = false;
        }
    }

    private class SurfaceCallback implements SurfaceHolder.Callback {
        @Override
        public void surfaceCreated(SurfaceHolder surface) {
            mSurfaceAvailable = true;
            surface.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

            // setup the media recorder
            try {
                setUpMediaRecorder();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                startIfReady();
            } catch (IOException e) {
                Timber.e(TAG, "Could not start camera source.", e);
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder surface) {
            mSurfaceAvailable = false;
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int width = 320;
        int height = 240;
        if (mCameraSource != null) {
            Size size = mCameraSource.getPreviewSize();
            if (size != null) {
                width = size.getWidth();
                height = size.getHeight();
            }
        }

        // Swap width and height sizes when in portrait, since it will be rotated 90 degrees
        if (isPortraitMode()) {
            int tmp = width;
            width = height;
            height = tmp;
        }

        final int layoutWidth = right - left;
        final int layoutHeight = bottom - top;

        // Computes height and width for potentially doing fit width.
        int childWidth = layoutWidth;
        int childHeight = (int) (((float) layoutWidth / (float) width) * height);

        // If height is too tall using fit width, does fit height instead.
        if (childHeight > layoutHeight) {
            childHeight = layoutHeight;
            childWidth = (int) (((float) layoutHeight / (float) height) * width);
        }

        for (int i = 0; i < getChildCount(); ++i) {
            getChildAt(i).layout(0, 0, childWidth, childHeight);
        }

        try {
            startIfReady();
        } catch (IOException e) {
            Timber.e(TAG, "Could not start camera source.", e);
        }
    }

    private boolean isPortraitMode() {
        int orientation = mContext.getResources().getConfiguration().orientation;
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            return false;
        }
        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            return true;
        }

        Timber.d(TAG, "isPortraitMode returning false by default");
        return false;
    }

    private void startRecordingVideo() {
        try {
            // Start recording
            mMediaRecorder.start();
            mIsRecordingVideo = true;
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }

    private void stopRecordingVideo() {
        // UI
        mIsRecordingVideo = false;
        // Stop recording
        mMediaRecorder.stop();
        mMediaRecorder.reset();
    }

    public void triggerRecording() {
        if (mIsRecordingVideo) {
            stopRecordingVideo();
            Timber.d("Recording stopped");
        } else {
            startRecordingVideo();
            Timber.d("Recording starting");
        }
    }
}

Antworten auf die Frage(2)

Ihre Antwort auf die Frage