27

के साथ मीडिया रिकॉर्डर मैं एंड्रॉइड विजन एपीआई से FaceTracker नमूना का उपयोग कर रहा हूं। हालांकि, मुझे वीडियो रिकॉर्ड करने में कठिनाई का सामना करना पड़ रहा है जबकि ओवरले उन पर खींचे जाते हैं।Google विजन एपीआई

एक तरीका है छवियों के रूप में बिटमैप्स को स्टोर करना और एफएफएमपीईजी या एक्सग्लगर का उपयोग करके उन्हें वीडियो के रूप में विलय करने के लिए उन्हें संसाधित करना, लेकिन मुझे आश्चर्य है कि अगर इस समस्या का बेहतर समाधान है तो हम रनटाइम पर वीडियो रिकॉर्ड कर सकते हैं क्योंकि पूर्वावलोकन अनुमानित है ।

अद्यतन 1: मैं मीडिया रिकॉर्डर के साथ following वर्ग अद्यतन, लेकिन रिकॉर्डिंग अभी भी काम नहीं कर रहा है। जब मैं triggerRecording कॉल() फ़ंक्शन यह निम्न त्रुटि फेंक है:

MediaRecorder: एक अमान्य स्थिति में बुलाया शुरू: 4

और मैं मैनिफ़ेस्ट फ़ाइल में बाह्य भंडारण की अनुमति है।

अद्यतन 2:

मैं कोड में ऊपर समस्या का समाधान हो और setupMediaRecorder() onSurfaceCreated कॉलबैक में चले गए हैं। हालांकि, जब मैं रिकॉर्डिंग बंद करता हूं तो यह रनटाइम-अपवाद फेंकता है। documentation के अनुसार यदि कोई वीडियो/ऑडियो डेटा नहीं है तो रनटाइम अपवाद फेंक दिया जाएगा।

तो, मैं यहां क्या खो रहा हूं?

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"); 
     } 
    } 
} 
+1

मुझे एक ही समस्या का सामना करना पड़ रहा है –

+0

तो क्या आपको इसके लिए कोई समाधान मिला? – Reshma

+0

अन्य कारणों के कारण, मैंने अपना दृष्टिकोण बदल दिया और इसके बजाय जीएलएसयूफेस व्यू के साथ ओपनसीवी का इस्तेमाल किया। मेरा अन्य प्रश्न चेकआउट करें: http://stackoverflow.com/q/33368655/1053097 – muneikh

उत्तर

0

समाधान 1: एंड्रॉयड लॉलीपॉप से, एक MediaProjection एपीआई पेश किया गया था जो MediaRecorder साथ संयोजन के रूप में एक वीडियो फ़ाइल के लिए एक SurfaceView को बचाने के लिए इस्तेमाल किया जा सकता। This example shows how to output a SurfaceView to a video file.

समाधान 2: वैकल्पिक रूप से, आप Grafika repository में प्रदान की साफ एनकोडर वर्गों में से एक का उपयोग कर सकते हैं। ध्यान दें कि आपको FaceTracker एप्लिकेशन को पोर्ट करने की आवश्यकता होगी ताकि वह सभी प्रतिपादन करने के लिए ओपनजीएल का उपयोग कर रहा हो। ऐसा इसलिए है क्योंकि ग्राफिका के नमूनों ने बनावट डेटा के तेज़ी से पढ़ने और लिखने के लिए ओपनजीएल पाइपलाइन का उपयोग किया है।

एक न्यूनतम उदाहरण है जो कक्षा में CircularEncoder का उपयोग करके आप जो चाहते हैं उसे प्राप्त करते हैं। यह Frame Blitting का एक उदाहरण प्रदान करता है, साथ ही स्क्रीन पर फ्रेम बफर डेटा प्रदर्शित करता है और वीडियो को आउटपुट करता है।

बड़ा परिवर्तन FaceTracker आवेदन के लिए एक SurfaceView के बजाय एक ग्राफिक्स WindowSurface उपयोग करने के लिए हो सकता है, इस EGL प्रसंग आप एनकोडर के माध्यम से एक फाइल करने के लिए फ्रेम बफर डेटा सहेजने देती सेट करता है। एक बार जब आप विंडोसर्फ़ेस में सब कुछ प्रस्तुत कर सकते हैं, तो ContinuousCaptureActivity कक्षा के समान रिकॉर्डिंग सेट करना मुश्किल है।

संबंधित मुद्दे