【问题标题】:how to make a video from byte array received from onPreviewFrame()如何从从 onPreviewFrame() 接收到的字节数组制作视频
【发布时间】:2014-09-29 10:54:59
【问题描述】:

我能够从 onPreviewFrame() 以字节数组的形式获取视频帧数据。我需要从这个字节数组制作视频。 下面是我的代码 sn-p:

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {

    try {
        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), "MyCameraApp");

        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                Log.d("MyCameraApp", "failed to create directory");
            }
        }

        FileOutputStream out = new FileOutputStream(mediaStorageDir.getAbsolutePath() + "video.mp4");
        out.write(data);
        out.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

生成的文件“video.mp4”不可播放。

任何解决问题的帮助或指导将不胜感激。

注意 我的应用程序将支持 Android 4+ 版本。

【问题讨论】:

  • 这并不像您想象的那么容易。您只是在创建文件名后缀为“.mp4”的一些字节的文件。详细了解 MP4 容器。
  • 嗨,skywall,感谢您的建议。我会朝那个方向研究。
  • 也许 MediaCodec 会做你想做的事。请参阅 Grafika (github.com/google/grafika) 中的各种示例,例如“表演+拍照”活动。 API 18+。

标签: android android-camera android-mediarecorder


【解决方案1】:

这是拍照和录像的代码

    // Add listener to video capture button
    VideoCapture = (Button)findViewById(R.id.buttonVideo);
    VideoCapture.setOnClickListener(new View.OnClickListener(){

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
                captureButton.setVisibility(View.GONE);
            if(isRecording){
                VideoCapture.setBackgroundResource(R.drawable.ic_action_videoplay); 
                   // stop recording and release camera
                mMediaRecorder.stop();  // stop the recording
                releaseMediaRecorder(); // release the MediaRecorder object
                mCamera.lock();         // take camera access back from MediaRecorder

                // inform the user that recording has stopped
                
                isRecording = false;
            }
            else{
                releaseCamera();
                 // initialize video camera
                if (prepareVideoRecorder()) {
                    // Camera is available and unlocked, MediaRecorder is prepared,
                    // now you can start recording
                    mMediaRecorder.start();

                    // inform the user that recording has started
                    
                    isRecording = true;
                } else {
                    // prepare didn't work, release the camera
                    releaseMediaRecorder();
                    // inform user
                }

                VideoCapture.setBackgroundResource(R.drawable.ic_launcher_videopause);
                isRecording = true;
            }
            
        }
        
    });

    private PictureCallback mPicture = new PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {

        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null){
            Log.d(TAG, "Error creating media file, check storage permissions: ");
            return;
        }

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();

            /* set image preview in imageview */
            previewImage = (ImageView)findViewById(R.id.imageViewPrieview);
            previewImage.setImageURI(Uri.fromFile(pictureFile));

            /* release camera & removeallview from preview */
            relaese();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }
    }
};



/** Create a file Uri for saving an image or video */
private Uri getOutputMediaFileUri(int type){
    return Uri.fromFile(getOutputMediaFile(type));
}

/** Create a File for saving an image or video */
private File getOutputMediaFile(int type){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), "MyCameraApp");
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

    if (type == MEDIA_TYPE_IMAGE){
        //                  mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        //                  "IMG_"+ timeStamp + ".jpg");
        mediaFile = new File("/sdcard/"+ "IMG_"+ timeStamp + ".jpg");
        Log.i("Image","Image is captured");

    } else if(type == MEDIA_TYPE_VIDEO) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                "VID_"+ timeStamp + ".mp4");
    } else {
        return null;
    }

    return mediaFile;
}

这些用于准备录像机的代码

 private boolean prepareVideoRecorder(){
    
    mCamera = getCameraInstance();
    mMediaRecorder = new MediaRecorder();
    
    
    // step 1: Unlock camera & Set camera to MediaRecorder
    mCamera.unlock();
    mMediaRecorder.setCamera(mCamera);
    
    // step 2: set Audio & Video Source
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    
    // step 3: set camcorder profile , it required Api Level 8
    mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
    
    // step 4: set output file
    mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
    
    // step 5: set preview output
    mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
    
    // step 6: prepare Configured Media recorder
    try {
        mMediaRecorder.prepare();
    } catch (IllegalStateException e) {
        Log.d("TAG","IllegalStateException preparing MediaRecorder" + e.getMessage());
        return false;
    }catch (IOException e) {
        Log.d("TAG","IO Exception preparing MediaRecorde" + e.getMessage());
        return false;
        
    }
    return true;
}
private void releaseMediaRecorder(){
    if (mMediaRecorder != null) {
        mMediaRecorder.reset();   // clear recorder configuration
        mMediaRecorder.release(); // release the recorder object
        mMediaRecorder = null;
        mCamera.lock();           // lock camera for later use
    }

我认为这会对您有所帮助。因为它对我有用。

Android API 目前不提供暂停方法

这有点技术性,不过是在cmets上征集的。

public class MediaRecorder,从 API 级别 1 开始使用,没有暂停功能,从 MediaRecorder 状态图中可以看出:

录制时,API 允许我们使用reset()stop() 公共方法:

reset() -> 将 MediaRecorder 重新启动到空闲状态。

stop() -> 停止录制。

【讨论】:

  • 现在检查代码,我为视频捕获添加按钮点击事件
  • 您好 DreamCoder,感谢您的回复。我需要从 onPreviewFrame() 接收的帧数据(字节数组)制作视频,因为我需要在录制 MediaRecorder 支持的视频时实现暂停/恢复功能。
猜你喜欢
  • 2012-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-20
  • 2016-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多