Экран мерцает и изменяется при запуске видеозаписи

Я интегрирую фото / видеозапись в своем приложении, и у меня проблема с захватом видео. Когда начинается видеозапись, экран мерцает, я получаю короткую паузу, затем начинается захват видео. Однако, используя приложение камеры телефона, вообще нет фликкера / паузы.

Кроме того, дисплей предварительного просмотра камеры изменяется, как только вызывается recorder.start() . Я не понимаю, почему это так. Это делает предварительный просмотр искаженным (все выглядит шире и шире).

Мои вопросы: Как предотвратить фликер / паузу при начале видеозаписи? Как предотвратить изменение размера экрана recorder.start() ?

Всякий раз, когда «видеорежим» включен, initRecording() . Как только пользователь нажимает кнопку, startRecording() . Наконец, когда кнопка снова нажата, stopRecording() . Менее важно, при переходе в «режим изображения» destroyRecorder() .

 @Override public void onResume() { super.onResume(); Camera camera = null; try { camera = Camera.open(); } catch (Exception e) { // Camera isn't available Toast.makeText( getActivity(), "Camera is not available at this time.", Toast.LENGTH_SHORT ).show(); getActivity().finish(); return; } if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD ) { setCameraDisplayOrientation( camera ); } else { camera.setDisplayOrientation( 90 ); } setCamera( camera ); setCameraZoomDisplay( camera ); if ( getSurfaceHolder() != null ) { startPreview(); if ( getMode() == MODE_VIDEO ) { initRecording(); } } } private void setCameraDisplayOrientation( Camera camera ) { CameraInfo info = new CameraInfo(); Camera.getCameraInfo( 0, info ); int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int result = ( info.orientation - degrees + 360 ) % 360; camera.setDisplayOrientation( result ); } private void initRecording() { MediaRecorder recorder = new MediaRecorder(); setRecorder( recorder ); Camera camera = getCamera(); camera.unlock(); recorder.setCamera( camera ); recorder.setAudioSource( MediaRecorder.AudioSource.MIC ); recorder.setVideoSource( MediaRecorder.VideoSource.CAMERA ); CamcorderProfile cp = CamcorderProfile.get( CamcorderProfile.QUALITY_HIGH ); recorder.setProfile( cp ); String extension; switch (cp.fileFormat) { case MediaRecorder.OutputFormat.MPEG_4: extension = "mp4"; break; case MediaRecorder.OutputFormat.THREE_GPP: extension = "3gp"; break; default: extension = "tmp"; } setVideoMimeType( MimeTypeMap.getSingleton().getMimeTypeFromExtension( extension ) ); File toFile = new File( getActivity().getCacheDir(), "tempvideo.tmp" ); if ( toFile.exists() ) { toFile.delete(); } setTempFile( toFile ); recorder.setOutputFile( toFile.getPath() ); recorder.setPreviewDisplay( getSurfaceHolder().getSurface() ); try { recorder.prepare(); setRecorderInitialized( true ); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private boolean startRecording() { try { getRecorder().start(); setRecording( true ); ImageView actionImageView = getActionImageView(); actionImageView.setImageResource( R.drawable.record_red ); } catch (Exception e) { getCamera().lock(); } return true; } private void stopRecording() { MediaRecorder recorder = getRecorder(); if ( recorder != null && isRecording() ) { recorder.stop(); setRecording( false ); setRecorderInitialized( false ); try { insertVideo(); } catch (IOException e) { e.printStackTrace(); } initRecording(); ImageView actionImageView = getActionImageView(); actionImageView.setImageResource( R.drawable.record_green ); } } private void destroyRecorder() { MediaRecorder recorder = getRecorder(); recorder.release(); setRecorder( null ); getCamera().lock(); } 

Причина небольшого увеличения при вызове MediaRecorder.start () заключается в том, что камера изменила размер своего предварительного просмотра в соответствии с разрешением записываемого видео. Эту проблему можно устранить, установив предварительный просмотр и восстановление видео при настройке. Я думаю, что я также нашел способ остановить мерцание, хотя я обнаружил, что при работе с Camera and MediaRecorder немного отставания или мерцания может происходить из любого из нескольких мест, так что это может быть Бит более жесткий для отслеживания. Документация Android для настройки камеры / видеомагнитофона – это хорошее место для начала, чтобы основные части были настроены правильно, но я обнаружил, что необходимо вникать в некоторые из документации api класса для отладки и создания опыта Действительно гладкий.

Класс Camera.Parameters является ключом к поддержанию плавной видеозаписи. Когда у вас есть объект Camera, вы можете использовать Camera.getParameters() чтобы получить текущие параметры для их изменения. Camera.setParameters(Camera.Parameters) затем могут использоваться для запуска любых изменений, которые были сделаны.

Чтобы предотвратить изменение размера видеоизображения, нам необходимо убедиться, что размер предварительного просмотра параметров соответствует записанному видеоразрешению. Чтобы получить список поддерживаемых размеров видео / предварительного просмотра, мы можем использовать Camera.Parameters.getSupportedPreviewSizes() для нашего текущего объекта Parameters, который вернет список объектов Camera.Size . Каждый из этих объектов будет иметь свойство width и height, доступ к которому осуществляется напрямую через Camera.Size.width и Camera.Size.height (без методов getter). Метод getSupportedPreviewSizes() гарантированно возвращает хотя бы один результат, и кажется, что результаты упорядочены с наивысшего разрешения до самого низкого.

(Для уровня API> 11 существует также метод getSupportedVideoSizes() , но похоже, что это только в том случае, если у устройства есть некоторые размеры видео, которые отличаются от размеров предварительного просмотра, иначе он возвращает значение null. Я не имел успеха с этим методом , Поэтому я буду придерживаться использования PreviewSizes, поскольку он гарантирует возвращение размера, подходящего как для видео, так и для предварительного просмотра, но это то, что нужно знать о продвижении.)

Как только мы получим Camera.Size который соответствует желаемому видеоразрешению, мы можем установить этот размер с помощью Camera.Parameters.setPreviewSize(width, height). Кроме того, чтобы помочь с мерцанием, я использую Camera.Parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO). Camera.setParameters() эти шаги, используйте Camera.setParameters() чтобы уведомить камеру о ваших изменениях. Я успел установить эти параметры сразу после получения камеры, поскольку параметры настройки, пока пользователь взаимодействует с этим действием, вызвали некоторое отставание. Если вы используете одну и ту же операцию для захвата видео и изображений, вы также можете установить параметры изображения здесь, объект камеры будет обрабатывать с помощью соответствующих параметров для каждого режима.

Почти готово! Теперь, когда предварительный просмотр позаботился, все, что осталось, – убедиться, что MediaRecorder использует то же разрешение, что и предварительный просмотр. При подготовке вашего медиа-рекордера между вызовами MediaRecorder.setProfile() (или установкой кодеров, для уровня API <8) и MediaRecorder.setOutputFile() поместите вызов в MediaRecorder.setVideoSize(width, height) используя те же значения Как ваш предварительный просмотр. Теперь переход от предварительного просмотра к записи с использованием MediaRecorder.start() должен быть бесшовным, поскольку оба они используют одинаковое разрешение.

Вот несколько быстрых фрагментов кода, чтобы вы могли видеть все в действии:

Получение и настройка параметров:

 Camera.Parameters params = camera.getParameters(); params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); //myVideoSize is an instance of Camera.Size List<Camera.Size> previewSizes = params.getSupportedPreviewSizes(); myVideoSize = previewSizes.get(0); params.setPreviewSize(myVideoSize.width, myVideoSize.height); camera.setParameters(params); 

Затем установите размер на медиа-рекордере:

 //After setting the profile.... mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); //Use myVideoSize from above mediaRecorder.setVideoSize(myVideoSize.width, myVideoSize.height); //Before setting the output file mediaRecorder.setOutputFile(myFile);