2016-03-23 51 views
8

Tôi muốn chụp ảnh trong khi quay video bằng API camera2.Cách lập trình Chụp ảnh trong khi quay video bằng Camera2 API trong Android

Hai trình diễn riêng biệt có sẵn. 1. To capture image và 2. To record video

Tôi đã cố gắng kết hợp chúng thành một ứng dụng. Nhưng bối rối trong nhiều điều. Giống như

  • CameraDevice là thiết bị duy nhất đại diện cho một máy ảnh được kết nối với thiết bị Android.
  • Mẫu khác nhau cần thiết theo yêu cầu. Đối với hình ảnh: mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); và đối với video mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
  • Trong createCaptureMặt cần phương pháp ImageReader cần thiết và cho video MediaRecorder là cần thiết.

CameraCaptureSession.StateCallback là cần thiết trong phương thức createCapturePhương thức cho cả hình ảnh và video.

Và API camera2 là mới. Vì vậy, không có nhiều ví dụ có sẵn trên Google.

Bất kỳ ai có bất kỳ ý tưởng nào về điều này? như cách chụp ảnh trong khi ghi hình trong Android?

+0

bạn đã thử các giải pháp mà chúng tôi đề xuất? –

+0

Tôi sẽ thử nó chắc chắn. –

Trả lời

0
public void onClick(View v) { 
    // TODO Auto-generated method stub 

    // if(v == myButton) 
    // { 
    if (recording) { 
     // stop recording and release camera 
     // type.setVisibility(View.GONE);1 
     type.setText(""); 
     myChronometer.stop(); 
     myChronometer.setBase(SystemClock.elapsedRealtime()); 
     // mediaRecorder.stop(); // stop the recording 
     releaseMediaRecorder(); // release the MediaRecorder object 
     // 
     myCamera.lock(); 
     recording = false; 

     // "/sdcard/fivo_flim/" + "fivo_flim_"+video_no 
     // + ".mp4"; 


     System.out.println("11111111111 "+SessionManager.getVideoCount(prefs1)); 

     new UploadPicture(VideoScreen.this, mApi, "/", new File(
       "/sdcard/record/" + "record" 
         + SessionManager.getVideoCount(prefs1) + ".mp4")) 
       .execute(); 
     SessionManager.saveVideoCount(prefs1, 
       SessionManager.getVideoCount(prefs1) + 1); 

     mWakeLock.release(); 
     System.out.println("uuuuuuuuuuuuuuuuuu"); 
    } else { 
     // Release Camera before MediaRecorder start 
     releaseCamera(); 
     mWakeLock.acquire(); 

     if (!prepareMediaRecorder()) { 
      Toast.makeText(
        VideoScreen.this, 
        "Fail in PrepareCamera()!\n   \n Please Insert SD Card or\n Restart your phone ", 
        Toast.LENGTH_LONG).show(); 
      finish(); 
     } 
     System.out.println("prepare media recorder"); 
     try { 
      mediaRecorder.prepare(); 
     } catch (Exception e1) { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 
     System.out.println("Starting Media Recorder"); 
     try { 
      mediaRecorder.start(); 
     } catch (Exception e) { 
      // TODO: handle exception 
      System.out.println("exception is " + e); 
     } 
     type.setText("Recording..."); 

     myChronometer.setBase(SystemClock.elapsedRealtime()); 
     myChronometer.start(); 

     recording = true; 
     myButton.setClickable(false); 
     try { 
      new Handler().postDelayed(new Runnable() { 
       @Override 
       public void run() { 
        myButton.setClickable(true); 
       } 
      }, 3000); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 

} 

@SuppressLint({ "NewApi", "SdCardPath" }) 
private boolean prepareMediaRecorder() { 
    myCamera = getCameraInstance(); 
    mediaRecorder = new MediaRecorder(); 
    myCamera.setDisplayOrientation(90); 
    myCamera.unlock(); 
    mediaRecorder.setCamera(myCamera); 
    mediaRecorder.setOrientationHint(90); 
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 

    mediaRecorder.setProfile(CamcorderProfile 
      .get(CamcorderProfile.QUALITY_HIGH)); 

    File mediaStorageDir = new File("/sdcard/record/"); 
    if (!mediaStorageDir.exists()) { 
     if (!mediaStorageDir.mkdirs()) { 
      Logger.Debug("failed to create directory"); 
     } 
    } 


    video_no=SessionManager.getVideoCount(prefs1); 


    mFiles.add("/sdcard/record/" + "record" + video_no 
      + ".mp4"); 
    mediaRecorder.setOutputFile("/sdcard/record/" + "record" 
      + video_no + ".mp4"); 
    video_no++; 

    mediaRecorder.setPreviewDisplay(myCameraSurfaceView.getHolder() 
      .getSurface()); 

    try { 
     mediaRecorder.prepare(); 

    } catch (IllegalStateException e) { 
     releaseMediaRecorder(); 
     return false; 

    } catch (IOException e) { 
     releaseMediaRecorder(); 
     return false; 
    } 

    return true; 

} 

@SuppressLint("SdCardPath") 
private void releaseMediaRecorder() { 
    if (mediaRecorder != null) { 
     mediaRecorder.reset(); 
     mediaRecorder.release(); 
     mediaRecorder = null; 
     myCamera.lock(); 

    } 
} 

private void releaseCamera() { 
    if (myCamera != null) { 
     myCamera.release(); 
     myCamera = null; 
    } 

} 

} 
6

Đối với camera2 API và ảnh chụp nhanh video, bạn sẽ cần phải cải thiện mẫu máy ảnh2video một chút.

  • 3 mục tiêu chụp Bề mặt: Xem trước (một TextureView hoặc SurfaceView), JPEG (ImageReader) và ghi (MediaRecorder hoặc MediaCodec).
  • bề mặt đèo từ cả ba để createCaptureSession
  • Khi không quay video, thiết lập các yêu cầu lặp đi lặp lại để chỉ nhắm mục tiêu xem trước
  • Khi quay video, thiết lập các yêu cầu lặp lại để nhắm mục tiêu cả xem trước và các bề mặt ghi âm, và bắt đầu mediarecorder (như camera2video); khi dừng ghi lại chuyển sang chỉ xem trước nhắm mục tiêu trong yêu cầu lặp lại.
  • Khi bạn muốn chụp ảnh, hãy thực hiện một cuộc gọi chụp() với yêu cầu nhắm vào bề mặt JPEG, bề mặt xem trước và nếu bản ghi đang hoạt động, bề mặt ghi.
  • Lấy hình ảnh JPEG từ ImageReader khi cuộc gọi lại có sẵn trênImageAvailable.
+0

Vì vậy, tôi đã thử điều này trên Samsung S5 của tôi và nó đóng băng xem trước và ghi âm trong khoảng 1/2 giây. Tôi cũng đã cố gắng gửi yêu cầu chỉ cho Trình đọc hình ảnh với cùng một kết quả. Bất kỳ cách nào để tránh điều này? – GroovyDotCom

+0

Nếu thiết bị máy ảnh chỉ hỗ trợ mức LEGACY, thì có thể xảy ra sự cố đóng băng khi sử dụng đầu ra JPEG. Trên thiết bị LIMITED hoặc FULL, một lần chụp JPEG sẽ không làm gián đoạn xem trước nếu thời lượng khung tối thiểu cho độ phân giải JPEG được chọn nhỏ hơn 1/(fps được yêu cầu) –

0

Để mở rộng câu trả lời Eddy Talvala của (mà tôi đồng ý phù thủy):

Nếu bạn muốn chụp một bức ảnh duy nhất khi đang quay video, bạn chỉ cần đưa ra một CaptureRequest đơn chỉ nhắm mục tiêu bề mặt của một ImageReader.The yêu cầu lặp lại của quay video sẽ không bị dừng lại. Với điều đó, bạn có thể chụp nhanh từ video đang được ghi.

Tôi hy vọng điều này sẽ giúp, nếu bạn cần một số mẫu mã tôi sẽ đăng chúng khi im nhà.

+0

Tôi muốn chào mừng các mẫu mã ... –

0

Hãy thử đời này:

public void takeSnapshot(CameraCaptureSession.CaptureCallback captureCallback) { 
    try { 
     //In case that we are in legacy 
     if (null == mCameraActivity || CameraSettings.isLegacyHardwareLevel()) 
      return; 

     int captureTemplate = CameraDevice.TEMPLATE_VIDEO_SNAPSHOT; 
     final CaptureRequest.Builder captureBuilder; 
     captureBuilder = YourCameraDevice.createCaptureRequest(captureTemplate); 
     captureBuilder.addTarget(YourImageReader.getSurface()); 
     //To get the right orientation we must to get it in base of the sensor position. 
     SensorOrientation = CameraManager.getCameraCharacteristics(mCameraId).get(
      CameraCharacteristics.SENSOR_ORIENTATION); 
     captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, SensorOrientation); 

     mCaptureSession.capture(captureBuilder.build(), captureCallback, mBackgroundHandler); 

    } catch (CameraAccessException e) { 
     e.printStackTrace(); 
    } 
} 
0

Tạo hình thu nhỏ video cho một video.Có thể trả về null nếu video bị hỏng hoặc định dạng không được hỗ trợ.

private void makeVideoPreview() { 
    Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail(videoAbsolutePath, MediaStore.Images.Thumbnails.MINI_KIND); 
    saveImage(thumbnail); 
} 
Các vấn đề liên quan