Camera2 MediaRecorder |Аудио и видео записываются асинхронно - PullRequest
0 голосов
/ 22 сентября 2018

Я создаю приложение, которое записывает видео - довольно просто.Я использую Camera2 API вместе с MediaRecorder для достижения этой цели.Мне удалось успешно записать видео, но звук и видео записываются асинхронно.

Допустим, я записываю 5-секундное видео - на выходе получится видеофайл длиной 10 секунд.Первые 5 секунд - это неподвижный кадр, воспроизводящий звук, последние 5 секунд - это кадры без звука.Это похоже на то, как если бы MediaRecorder записывал звук еще до того, как он начал принимать видеокадры.

Устройство, которое я использую для тестирования, - это Samsung Galaxy 7. Мне удалось найти одного человека в Интернете, сталкивающегося с подобной проблемой.без ответов / ответов: Воспроизведение аудио и видео дорожки Android

Как настроить MediaRecorder:

private void setUpMediaRecorder() throws IOException {
    final Activity activity = this;
    if (null == activity) {
        print("Null activity!");
        return;
    }

    mediaRecorder = new MediaRecorder();
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    if (nextVideoAbsolutePath == null || nextVideoAbsolutePath.isEmpty()) {
        nextVideoAbsolutePath = getVideoFilePath(this);
    }
    mediaRecorder.setOutputFile(nextVideoAbsolutePath);
    mediaRecorder.setVideoEncodingBitRate(10000000);
    mediaRecorder.setVideoFrameRate(30);
    mediaRecorder.setVideoSize(videoSize.getWidth(), videoSize.getHeight());
    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
    int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
    switch (sensorOrientation) {
        case SENSOR_ORIENTATION_DEFAULT_DEGREES:
            mediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
            break;
        case SENSOR_ORIENTATION_INVERSE_DEGREES:
            mediaRecorder.setOrientationHint(INVERSE_ORIENTATIONS.get(rotation));
            break;
    }
    mediaRecorder.prepare();
}

Моя StartRecording() функция:

void startRecording()
{
    //Check the camera and TextureView are ready
    if (null == cameraDevice || !textureView.isAvailable() || null == previewSize) {
        return;
    }

    try {

        //Close the existing capture session used for preview
        closePreviewSession();

        //Set up the MediaRecorder
        setUpMediaRecorder();

        //Compile list of surfaces
        List<Surface> surfaces = new ArrayList<>();
        surfaces.add(previewSurface);
        final Surface recorderSurface = mediaRecorder.getSurface();
        surfaces.add(recorderSurface);

        // Start the capture session
        // Once the session starts, we can update the UI and start recording
        cameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                //Store a reference to the session
                currentCaptureSession = cameraCaptureSession;

               //Flag that recording has started
               isRecording = true;
               toggleRecordingButton();

                try {
                    //Initiate requestBuilder
                    captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);

                    //Add the surfaces to the request
                    captureRequestBuilder.addTarget(previewSurface); 
                    captureRequestBuilder.addTarget(recorderSurface);

                    //Build
                    captureRequest = captureRequestBuilder.build();
                    print("CameraCaptureSession stateCallback onConfigured() - Starting media recorder");

                    //Start recording
                    mediaRecorder.start();

                    //Set repeating request for VIDEO
                    currentCaptureSession.setRepeatingRequest(captureRequest, new CameraCaptureSession.CaptureCallback() {
                        @Override
                        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {

                        }
                    }, null);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                print("onConfigureFailed");
                Activity activity = MainActivity.this;
                if (null != activity) {
                    Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
                }
                isRecording = false;
            }
        }, backgroundHandler);
    } catch (Exception e) {
        e.printStackTrace();
    }


}

Моя StopRecording() функция:

private void stopRecording() {
    // UI
    isRecording = false;
    toggleButtonsWhileRecording();

    // Stop recording
    mediaRecorder.stop();
    mediaRecorder.reset();

    //Reset path
    nextVideoAbsolutePath = null;
}

1 Ответ

0 голосов
/ 24 сентября 2018

Оказывается, это ошибка, ограниченная только некоторыми устройствами Samsung Galaxy.Подробнее об этой проблеме и способе ее обхода для обнаружения длинного кадра и его исправления после записи: Сохраненный видеофайл имеет только один видеокадр

В итоге, ошибка связана с появлением этих устройств.из глубокого сна.После сброса телефона проблема решается (но возвращается, если я позволю телефону перейти в режим глубокого сна).

...