【问题标题】:Tap and hold to record video like Vine点击并按住以录制视频,如 Vine
【发布时间】:2015-09-30 04:55:55
【问题描述】:

我想做一个录制视频的应用程序,看起来像藤蔓,按住录制,释放它停止,按住录制并保持到最后。

我用过MediaRecorder,但是每次只录一次,如果再开始录,app就崩溃了。

请告诉我有什么方法可以做到这一点? 我编辑了我的代码:

public class VideoRecordingActivity extends AppCompatActivity implements View.OnTouchListener, View.OnLongClickListener {
private Context myContext;
private boolean hasCamera;
private boolean onRecording;

private Camera mCamera;
private CameraPreview mPreview;
private MediaRecorder mediaRecorder;
private boolean cameraFront = false;
private int cameraId;

private int videoNumer;
private boolean isActionDown = false;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_video_introduction_recording);
    initUI();
    initialize();
}
private LinearLayout lnCameraPreview;
private ImageButton btn_recording;

private void initUI() {
    lnCameraPreview = (LinearLayout) findViewById(R.id.ln_body_recording);
    btn_recording = (ImageButton) findViewById(R.id.btn_recording);

}

public void initialize() {
    myContext = this;
    mPreview = new CameraPreview(this, cameraId, mCamera);
    lnCameraPreview.addView(mPreview);
    btn_recording.setOnLongClickListener(this);
    btn_recording.setOnTouchListener(this);
    videoNumer = 0;
}
public boolean onLongClick(View v) {
    isActionDown = true;
    try {
        boolean isPrepared = false;
        if (isActionDown)
            isPrepared = prepareMediaRecorder();
        if (isPrepared && isActionDown) {
            // work on UiThread for better performance
            runOnUiThread(new Runnable() {
                public void run() {
                    mediaRecorder.start();
                    onRecording = true;
                }
            });

        }
    } catch (Exception e) {
        e.printStackTrace();
        Log.e("onLongPress Error ", e.toString());
    }

    return true;
}


@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_UP:
            isActionDown = false;

            try {
                if (onRecording) {

                    if (mediaRecorder != null) {
                        mediaRecorder.stop();
                    }
                    onRecording = false;
                    videoNumer++;
                }
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            break;
    }
    return false;
}



public void onResume() {
    super.onResume();
    if (!hasCamera(myContext)) {
        Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG).show();
        return;
    }
    initCamera();
}

@Override
protected void onPause() {
    super.onPause();
    // when on Pause, release camera in order to be used from other
    // applications
    releaseCamera();
}


private final int cMaxRecordDurationInMs = 30000;
private final long cMaxFileSizeInBytes = 5000000;
private final int cFrameRate = 20;
private File prRecordedFile;

@SuppressLint("SdCardPath")
private boolean prepareMediaRecorder() {
    mediaRecorder = new MediaRecorder();

    try {
        mCamera.unlock();
    } catch (Exception ex) {
        return false;
    }

        // adjust the camera the way you need
        mediaRecorder.setCamera(mCamera);
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);

        //
        CamcorderProfile cpHigh = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
        mediaRecorder.setProfile(cpHigh);
        mediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());

    mediaRecorder.setOutputFile("/sdcard/" + videoNumer + "videocapture_example.mp4");

    //set max size
    mediaRecorder.setMaxDuration(600000); // Set max duration 60 sec.
    mediaRecorder.setMaxFileSize(50000000); // Set max file size 50M

    try {
        mediaRecorder.prepare();
    } catch (Exception e) {
        releaseMediaRecorder();
        e.printStackTrace();
    }
    return true;
}

private void releaseMediaRecorder() {
    if (mediaRecorder != null) {
        mediaRecorder.reset(); // clear recorder configuration
        mediaRecorder.release(); // release the recorder object
        mediaRecorder = null;
        if (mCamera != null) {
            mCamera.lock(); // lock camera for later use
        }
    }
}

/**
 * Camera
 */

private void initCamera() {
    if (mCamera == null) {
        // if the front facing camera does not exist
        if (findFrontFacingCamera() < 0) {
            Toast.makeText(this, "No front facing camera found.", Toast.LENGTH_LONG).show();
        }
        mCamera = Camera.open(findBackFacingCamera());
        mPreview.refreshCamera(mCamera);
    }
    onRecording = false;
}

private boolean hasCamera(Context context) {
    // check if the device has camera
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        hasCamera = true;
    } else {
        hasCamera = false;
    }
    return hasCamera;
}

private int findFrontFacingCamera() {
    int cameraId = -1;
    // Search for the front facing camera
    int numberOfCameras = Camera.getNumberOfCameras();
    for (int i = 0; i < numberOfCameras; i++) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(i, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            cameraId = i;
            cameraFront = true;
            break;
        }
    }
    this.cameraId = cameraId;
    return cameraId;
}

private int findBackFacingCamera() {
    int cameraId = -1;
    // Search for the back facing camera
    // get the number of cameras
    int numberOfCameras = Camera.getNumberOfCameras();
    // for every camera check
    for (int i = 0; i < numberOfCameras; i++) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(i, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            cameraId = i;
            cameraFront = false;
            break;
        }
    }
    this.cameraId = cameraId;
    return cameraId;
}

public void switchCamera() {
    // if the camera preview is the front
    if (cameraFront) {
        int cameraId = findBackFacingCamera();
        if (cameraId >= 0) {
            // open the backFacingCamera
            mCamera = Camera.open(cameraId);
            // refresh the preview
            mPreview.refreshCamera(mCamera);
        }
    } else {
        int cameraId = findFrontFacingCamera();
        if (cameraId >= 0) {
            // open the backFacingCamera
            mCamera = Camera.open(cameraId);
            // refresh the preview
            mPreview.refreshCamera(mCamera);
        }
    }
}

private void releaseCamera() {
    // stop and release camera
    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}

}

【问题讨论】:

  • 您需要展示您的代码,除非您向我们展示您目前所做的工作,否则社区将无法提供帮助。
  • 我想你在longClickListener()写了代码来录制视频,你可能没有写onTouch()方法,写onTouch()方法和ACTION_UP和ACTION_CANCEL在长按时释放mediaRecorder活动结束,尽管显示您的代码
  • 当我开始时,记录,停止。没关系,但是当我再次按开始时。崩溃了
  • 请你展示你的相机预览课程,因为我在我的项目中遇到了相机预览课程的问题

标签: android android-studio


【解决方案1】:

您可以通过在录制按钮上设置 OnLongClickListener() 和 OnTouchListener() 来实现此功能。像这样:

recordBtn.setOnLongClickListener(recordBtnLCListener);
recordBtn.setOnTouchListener(recordBtnTouchListener);

然后:

@Override
public boolean onLongClick(View v) {
    ivCancel.setVisibility(View.GONE);
    ivDone.setVisibility(View.GONE);
    isActionDown = true;
    try {
        if (isActionDown) {
            initRecorder();
            if (isActionDown)
                prepareRecorder();
        }
        if (isPrepared && isActionDown) {
            mMediaRecorder.start();
            isRecording = true;
        }
    } catch (Exception e) {
        e.printStackTrace();
        Log.e("onLongPress Error ", e.toString());
    }

    return true;
}

和:

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_UP:
            isActionDown = false;

            try {
                if (isRecording) {

                    if (mMediaRecorder != null) {
                        mMediaRecorder.stop();
                    }
                    isRecording = false;
                }
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            break;
    }
    return false;
}

这样,您可以录制视频的各个部分。意味着每次长按录制按钮时,录制开始。当您松开按钮时,录制停止,您必须将这部分视频保存在任何临时文件夹中。 一旦您完成了对视频的所有部分的拍摄,您就必须将视频的所有部分组合成一个视频。

这里是合并所有保存在 tempory 文件夹中的视频部分的代码:

public void mergeVideos() {
    try {
        List<Movie> inMovies = new ArrayList<>();
        for (int i = 0; i < videosPathList.size(); i++) {
            String filePath = videosPathList.get(i);
            try {
                Movie movie = MovieCreator.build(filePath);
                if (movie != null)
                    inMovies.add(movie);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        List<Track> videoTracks = new LinkedList<Track>();
        List<Track> audioTracks = new LinkedList<Track>();
        for (Movie m : inMovies) {
            for (Track t : m.getTracks()) {
                try {
                    if (t.getHandler().equals("soun")) {
                        audioTracks.add(t);
                    }
                    if (t.getHandler().equals("vide")) {
                        videoTracks.add(t);
                    }
                } catch (Exception e) {

                }
            }
        }
        Movie result = new Movie();
        if (audioTracks.size() > 0) {
            result.addTrack(new AppendTrack(audioTracks
                    .toArray(new Track[audioTracks.size()])));
        }
        if (videoTracks.size() > 0) {
            result.addTrack(new AppendTrack(videoTracks
                    .toArray(new Track[videoTracks.size()])));
        }
        BasicContainer out = (BasicContainer) new DefaultMp4Builder().build(result);
        File f = null;
        String finalVideoPath;
        try {
            f = setUpVideoFile(Environment
        .getExternalStorageDirectory()+"/MyApp/videos/");
            finalVideoPath = f.getAbsolutePath();

        } catch (IOException e) {
            e.printStackTrace();
            f = null;
            finalVideoPath = null;
        }
        WritableByteChannel fc = new RandomAccessFile(finalVideoPath, "rw").getChannel();
        out.writeContainer(fc);
        fc.close();
        deleteFilesDir(); //In this method you have to delete all parts of video stored in temporary folder.


    } catch (Exception e) {
        e.printStackTrace();
       progressDialog.dismiss();
        finish();
    }
}

File setUpVideoFile(String directory) throws IOException {
    File videoFile = null;
    if (Environment.MEDIA_MOUNTED.equals(Environment
            .getExternalStorageState())) {
        File storageDir = new File(directory);
        if (storageDir != null) {
            if (!storageDir.mkdirs()) {
                if (!storageDir.exists()) {
                    Log.d("CameraSample", "failed to create directory");
                    return null;
                }
            }
        }
        videoFile = File.createTempFile("video_"
                        + System.currentTimeMillis() + "_",
                .mp4, storageDir);
    }
    return videoFile;
}

停止 mediaRecorder 后可以调用 mergeVideos() 方法。

希望此代码对您有所帮助。 :)

要合并视频,您必须使用 isoparser 库。所以你必须在你的 gradle 文件中添加以下依赖:

compile 'com.googlecode.mp4parser:isoparser:1.0.5.4'

【讨论】:

  • 哇!我还没有尝试过你的代码,但是很酷。感谢您的支持。我会试试看,稍后告诉你。
  • 当然:) 它肯定会工作@Ngyyen koi。只需小心实现它,因为处理相机和媒体记录器不是一件容易的事
  • 我在上面编辑了我的代码。请再检查一次。它没有录制任何视频
  • 尝试在不运行 UI 线程的情况下启动媒体记录器...请按照步骤小心使用媒体记录器。请参考developer.android.com/guide/topics/media/camera.html
  • 嗨 Er.Rohit Sharma,我成功了。但如果视频的长度小于 10 秒,则无法录制。你有什么建议吗?
【解决方案2】:

这是我的代码。

public class VideoRecordingActivity extends AppCompatActivity implements View.OnClickListener, SurfaceHolder.Callback {
MediaRecorder recorder;
SurfaceHolder holder;
boolean recording = false;
private boolean isPrepared = false;
int videoNumber = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    super.onCreate(savedInstanceState);

    recorder = new MediaRecorder();
    initRecorder();
    setContentView(R.layout.activity_video_introduction_recording);

    SurfaceView cameraView = (SurfaceView) findViewById(R.id.ln_body_recording);
    holder = cameraView.getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    cameraView.setClickable(true);
    cameraView.setOnClickListener(this);
}

private void initRecorder() {
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), "CameraSample");

    recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
    recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
    CamcorderProfile cpHigh = CamcorderProfile
            .get(CamcorderProfile.QUALITY_HIGH);
    recorder.setProfile(cpHigh);
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
    //CGlobal.VIDEO_RECORD_PATH = CGlobal.VIDEO_HOME_PATH + "VID_" + timeStamp;
    File mediaFile;
    mediaFile = new File(mediaStorageDir.getPath() + File.separator +
            "VID_"+ timeStamp + ".mp4");

    recorder.setOutputFile(mediaFile+".mp4");
    recorder.setMaxDuration(50000); // 50 seconds
    recorder.setMaxFileSize(5000000); // Approximately 5 megabytes
}

private void prepareRecorder() {
    recorder.setPreviewDisplay(holder.getSurface());
    try {
        recorder.prepare();
        isPrepared = true;
    } catch (IllegalStateException e) {
        e.printStackTrace();
        finish();
    } catch (IOException e) {
        e.printStackTrace();
        finish();
    }
}

public void onClick(View v) {
    if (recording) {
        recorder.stop();
        recording = false;
        isPrepared = false;
        videoNumber++;
        // Let's initRecorder so we can record again
    } else {
        if (!isPrepared){
            initRecorder();
            prepareRecorder();
        }
        recording = true;
        recorder.start();
    }
}

public void surfaceCreated(SurfaceHolder holder) {
    prepareRecorder();
}

public void surfaceChanged(SurfaceHolder holder, int format, int width,
                           int height) {
}

public void surfaceDestroyed(SurfaceHolder holder) {
    if (recording) {
        recorder.stop();
        recording = false;
    }
    recorder.release();
    finish();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 2020-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    相关资源
    最近更新 更多