检测视频文件何时被真正写入?

时间:2014-11-18 04:51:35

标签: android video commonsware-cwac cwac-camera

cwac-camera库具有在保存照片之前调用的事件挂钩:

@Override public void saveImage(PictureTransaction xact, byte[] image) {}

我是否只是忽略了这一点,或者没有水槽告诉我视频文件何时被保存?

更多背景信息:结束视频的方法有两种。一个是通过致电

.stopRecording();

另一种方法是将记录器配置为最大持续时间/最大文件大小(在这种情况下,记录在没有显式调用stopRecording()的情况下停止:

recorder.setMaxDuration()

在这两种情况下,从我看来,Android需要大约100到200毫秒来完成文件。因为当我使用

时,视频文件经常被破坏
mediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
        @Override public void onInfo(MediaRecorder mr, int what, int extra) {}
}

检测它何时完成或在调用stopRecording()后立即尝试读取它。我尝试使用FileObserver来检测媒体记录器何时实际关闭文件,这很有效。

我想讨论这个问题,如果有人有相同的经验,并且有一种方式cwac-camera如何检测并发出录音文件的信号。

-

我刚刚在此处的Android文档http://developer.android.com/reference/android/media/MediaRecorder.html#setMaxDuration(int)

中介绍了此内容

"停止异步发生,无法保证在收到收件人通知时录音机会停止。"

这解释了为什么文件有时没有被正确关闭,这隐含意味着使用FileObserver可能是写入文件后唯一安全且有效的方法。

所以我们需要这样的东西来检测事件。

@Override protected File getVideoPath() {
    File file = super.getVideoPath(); // assemble the video path
    fileObserverPath = file.getAbsolutePath();

    fileObserver = new FileObserver(fileObserverPath, FileObserver.CLOSE_WRITE) {
        @Override public void onEvent(int event, String videoPath) {

            System.out.println("**** CameraHost: write closed");

            if (fileObserver != null) { // defensive
                fileObserver.stopWatching();
                fileObserver = null;
            }

            // process the file here
        }
    };
    fileObserver.startWatching();

    return file;
}

-

我继续将以下代码添加到我的CameraHost以获取时间:

@Override public void configureRecorderOutput(int cameraId, MediaRecorder recorder) {

    System.out.println("**** CameraHost: configureRecorderOutput");

    recorder.setMaxDuration(Constants.FRAMEPLAYER_MAX_RECORDING_LENGTH_PER_FRAME_MSEC);
    recorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
        @Override public void onInfo(MediaRecorder mr, int what, int extra) {
            switch (what) {
                case MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED: {

                    System.out.println("**** CameraHost: MEDIA_RECORDER_INFO_MAX_DURATION_REACHED");

                    break;
                }
            }
        }
    });

    super.configureRecorderOutput(cameraId, recorder);
}

时序:

11-20 07:33:28.974  32602-32602/cc.closeup.android I/System.out﹕ **** CameraHost: configureRecorderOutput
11-20 07:33:31.064  32602-32602/cc.closeup.android I/System.out﹕ **** CameraHost: MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
11-20 07:33:31.084  32602-32602/cc.closeup.android I/System.out﹕ **** CameraHost: MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
11-20 07:33:36.914  32602-32655/cc.closeup.android I/System.out﹕ **** CameraHost: write closed
11-20 07:33:36.914  32602-32655/cc.closeup.android I/System.out﹕ **** CameraHost: write closed

两件奇怪的事情:

  1. 引发MEDIA_RECORDER_INFO_MAX_DURATION_REACHED,但录制不会停止。与Android文档中指定的内容相反,我必须明确地调用stop。
  2. 即使configureRecorderOutput只引发一次,我的侦听器也会被调用两次。我尝试了相同的外部cwac相机,听众只被叫一次。
  3. 不确定我是否在某处犯了错误或在cwac-camera中出了问题。

    有人评论吗?

    -

    关于2.,无论是什么,我的日志显示触发事件的媒体记录器是相同的,并且在= 800(MEDIA_RECORDER_INFO_MAX_DURATION_REACHED)之后短缺,未记录的= 536871912被引发。第二次事件被提出没有文件记录= 268436456。

    [来自华硕Memo Pad 7:]

    11-20 09:41:25.748    3398-3398/cc.closeup.android I/System.out﹕ **** CameraHost: onInfo: mr = android.media.MediaRecorder@41c9da88, what = 800, extra 0
    11-20 09:41:25.748    3398-3398/cc.closeup.android I/System.out﹕ **** CameraHost: MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
    11-20 09:41:25.748    3398-3398/cc.closeup.android I/System.out﹕ **** CameraHost: onInfo: mr = android.media.MediaRecorder@41c9da88, what = 536871912, extra 0
    
    11-20 09:41:25.778    3398-3398/cc.closeup.android I/System.out﹕ **** CameraHost: onInfo: mr = android.media.MediaRecorder@41c9da88, what = 800, extra 0
    11-20 09:41:25.778    3398-3398/cc.closeup.android I/System.out﹕ **** CameraHost: MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
    11-20 09:41:25.778    3398-3398/cc.closeup.android I/System.out﹕ **** CameraHost: onInfo: mr = android.media.MediaRecorder@41c9da88, what = 268436456, extra 0
    

    我在另一台设备上运行了这个,其中MEDIA_RECORDER_INFO_MAX_DURATION_REACHED事件也被提升了两次,但是没有记录的是什么=?根本没有提高。供应商具体实施?

    [来自三星Galaxy Note 2:]

    11-20 09:46:42.711  25699-25699/cc.closeup.android I/System.out﹕ **** CameraHost: onInfo: mr = android.media.MediaRecorder@42831c30, what = 800, extra 0
    11-20 09:46:42.711  25699-25699/cc.closeup.android I/System.out﹕ **** CameraHost: MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
    
    11-20 09:46:42.776  25699-25699/cc.closeup.android I/System.out﹕ **** CameraHost: onInfo: mr = android.media.MediaRecorder@42831c30, what = 800, extra 0
    11-20 09:46:42.776  25699-25699/cc.closeup.android I/System.out﹕ **** CameraHost: MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
    

    我一直在发帖...

    -

    关于1.,录制实际上已停止(录制的文件长一秒),但FileObserver()显然只是稍后调用,即在我明确调用cameraView.stop()之后。

    我试图直接在事件中传递的MediaRecorder上调用stop(),这可以在Android中运行,但不能在cwac中运行。

    -

    关于1.,我进一步深入研究,看起来视频文件一直保持写入,直到我明确调用cameraView.stop() - 然后它被截断为一秒并关闭。

    // startRecording() called here
    
    11-20 11:29:49.072    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:49.072    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 32, videoPath = media0.mp4
    11-20 11:29:49.082    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:49.082    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:49.082    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:49.082    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:49.082    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:49.082    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.132    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.132    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.132    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.132    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    
    11-20 11:29:51.132    4987-4987/cc.closeup.android I/System.out﹕ **** CameraHost: MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
    
    11-20 11:29:51.142    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.142    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.142    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.142    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.142    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    (...)
    11-20 11:29:51.182    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.182    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.182    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    
    11-20 11:29:51.192    4987-4987/cc.closeup.android I/System.out﹕ **** CameraHost: MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
    
    11-20 11:29:51.192    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.192    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.192    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.192    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.192    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    (...)
    11-20 11:29:51.252    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.262    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.262    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.262    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.262    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:51.262    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    
    // stopRecording() called here
    
    11-20 11:29:52.492    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.492    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.492    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.492    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.572    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.572    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.572    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.572    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.572    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.572    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.572    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    (...)
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 2, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: FileObserver: onEvent: event = 8, videoPath = media0.mp4
    11-20 11:29:52.582    4987-5167/cc.closeup.android I/System.out﹕ **** CameraHost: write closed: videoPath = media0.mp4
    

1 个答案:

答案 0 :(得分:3)

FileObserver可用于检测文件何时被最终写入。它可以挂钩到CameraHost中的getVideoDirectory()重写:

@Override protected File getVideoDirectory() {
    fileObserver = new FileObserver(videoDirectory.getAbsolutePath(), FileObserver.CLOSE_WRITE) {
        @Override public void onEvent(int event, String videoPath) {
            System.out.println("**** CameraHost: FileObserver: onEvent: event = " + event + ", videoPath = " + videoPath);

            if (fileObserver != null && videoPath != null && event == FileObserver.CLOSE_WRITE) { // do not process directory
                System.out.println("**** CameraHost: write closed: videoPath = " + videoPath);

                // fileObserver.stopWatching(); // TODO this needs to be closed somewhere
                // fileObserver = null;

                raiseVideo(videoPath);
            }
        }
    };
    fileObserver.startWatching();

    return videoDirectory;
}

FileObserver的局限性在于只有在显式调用stopRecording()时才能正常工作。如果由于已达到预定义的文件大小或持续时间而终止录制,则提升得太晚(另请参阅https://github.com/commonsguy/cwac-camera/issues/242)。

使用recorder.setOnInfoListener()不起作用,因为它可能会在文件实际写入磁盘之前报告文件的最终确定。