【问题标题】:How to know when MediaRecorder has finished writing data to file如何知道 MediaRecorder 何时完成将数据写入文件
【发布时间】:2011-11-17 02:54:42
【问题描述】:

我们使用 MediaRecorder 在进行实际录制之前使用 setOutputFile() 将视频录制到外部存储上的文件中。

一切正常,但主要问题是,一旦录制完成,我们想开始在 VideoView 中播放录制的视频。

如何知道文件何时可以读取和播放?

【问题讨论】:

    标签: android file video mediarecorder


    【解决方案1】:

    FileObserver 类非常适合您的需求。 Here is the documentation。它很容易使用。当观察到的文件写入后关闭时,以CLOSE_WRITE为参数调用onEvent回调。

    MyFileObserver fb = new MyFileObserver(mediaFile_path, FileObserver.CLOSE_WRITE);
    fb.startWatching();
    
    class MyFileObserver extends FileObserver {
    
        public MyFileObserver (String path, int mask) {
            super(path, mask);
        }
    
        public void onEvent(int event, String path) {
            // start playing
        }
    }
    

    别忘了致电stopWatching()

    【讨论】:

    • 我现在无法对此进行测试,但您知道是否可以保证 MediaRecorder 在写入之间不会关闭文件?
    • 不知道。但即使是这样,您也可以在成员中维护记录状态并在onEvent 中检查它。如果录制暂停,则忽略该事件。
    • 使用FileObserver 时的一个问题是它不像宣传的那样工作。它不是监视单个文件,而是监视一个目录。因此,请监视目录的更改。在onEvent(int event, String path) 中,受影响的实际文件的路径将作为String 参数传递。然后,您可以将该路径与您感兴趣的文件的路径进行比较并做出相应的响应。请参阅stackoverflow.com/questions/16448002/… 了解更多信息。
    • 我建议不要使用 FileObserver,它不适用于所有版本。你可以在这里阅读更多关于它的信息issuetracker.google.com/issues/37065227
    【解决方案2】:

    我们用以下算法解决了类似的问题:

    while (file not complete)
        sleep for 1 sec
        read the fourth byte of the file
        if it is not 0 (contains 'f' of the 'ftyp' header) then
            file is complete, break
    

    关键是 MediaRecorder 在最后一刻写入 ftyp 框。如果它到位,那么文件是完整的。

    【讨论】:

      【解决方案3】:

      在我的测试中,无论录制文件的大小如何,mediaRecorder.stop() 都是一个阻塞方法,仅在文件被媒体录制器完全写入和关闭后才返回。

      所以 JPM 的回答实际上是正确的。

      您可以通过在 stop() 之后立即调用 File.length() 来验证这一点。你会发现输出文件长度就是此时文件的最终长度。换句话说,媒体记录器不会在 stop() 返回后向文件写入任何内容。

      【讨论】:

        【解决方案4】:

        我自己没有尝试过,但这可能有效:

        public void release () 自:API 级别 1

        释放与此 MediaRecorder 对象关联的资源。它是 使用完后调用此方法的好习惯 媒体记录器。

        如果它按照它说的做,那么我猜如果你调用它并且在这个方法返回之后你知道文件已经准备好了。

        【讨论】:

        • 真的吗?我认为这只是为了释放资源并让 GC 处理它们,而且我们录制了很多剪辑,因此每次重建 MediaRecorder 可能会损害我们的性能。不过我会进一步调查,谢谢!
        【解决方案5】:

        显然没有办法检测媒体播放器中的录制何时停止,但是如果您创建一个实现 MediaRecorder 的自定义类,则可以覆盖一个 stop()。在这里我会做这样的事情:

        public class MyRecorder implements MediaRecorder {
            public boolean stopped;
        
            .... implement all the methods that MediaRecorder has making 
                 sure to call super for each method.
        
            @Override
            public void myStop() {
                this.stopped = true;
                super.stop(); 
            }
        }
        

        然后您可以访问布尔值以查看它是否已停止录制。

        【讨论】:

        • 但是当录制停止时,必须将更多数据写入存储,并且在录制真正写入存储之前,我们无法开始播放视频。
        • 必须写什么?如果它自定义您正在编写的内容,则从覆盖的 stop 方法中调用您的自定义函数,然后在您调用后设置 stop 变量。
        • 我知道我们什么时候停止录制。当记录停止时,记录器将数据写入磁盘,我想知道它何时完成写入数据:)
        【解决方案6】:

        一种肮脏的方法是检查文件的lastModified() 值,如果文件在 2 秒内没有被修改,则打开 VideoView。

        【讨论】:

        • 我们已经有了一些技巧,但如果有合适的解决方案,我会更喜欢。如果没有,那么我们将继续使用我们的 hack 并为其添加一些错误保护:)
        猜你喜欢
        • 2015-07-13
        • 2014-03-18
        • 1970-01-01
        • 1970-01-01
        • 2015-10-01
        • 2020-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多