如何知道MediaRecorder何时完成将数据写入文件

19

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

一切都很顺利,但主要问题是,一旦录制完成,我们希望在 VideoView 中开始播放录制的视频。

如何知道文件何时准备好以便读取和回放?

6个回答

21

FileObserver类完全符合您的需求。 这里是文档。它易于使用。当观察到的文件在写入后关闭时,将调用onEvent回调,并将CLOSE_WRITE作为参数。

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是否保证在写入期间不关闭文件吗? - Stefan H Singer
不清楚。但是即使如此,您可以在成员变量中维护记录状态,并在onEvent中进行检查。如果录制已暂停,只需忽略该事件即可。 - Ron
5
使用 FileObserver 时需要注意的是它并不像宣传的那样监视单个文件,而是监视整个目录。因此,请监视目录以便检测变化。在 onEvent(int event, String path) 中,实际受影响的文件路径将作为 String 参数传递。然后,您可以将该路径与您感兴趣的文件路径进行比较,并相应地做出响应。有关更多信息,请参见 https://dev59.com/JWQn5IYBdhLWcg3w9K73。 - Tash Pemhiwa
我建议不要使用FileObserver,因为它不能与所有版本兼容。您可以在此处阅读更多信息:https://issuetracker.google.com/issues/37065227 - OneBigQuestion

5
我们使用以下算法解决了类似的问题:
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盒子。如果它已经就位,那么文件就是完整的。

2

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

因此,JPM的答案实际上是正确的。

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


1

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

public void release () Since: API Level 1

释放与此 MediaRecorder 对象关联的资源。当您完成使用 MediaRecorder 后,调用此方法是一个好习惯。

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


真的吗?我以为那只是为了释放资源并让GC处理它们,此外,我们记录了许多剪辑,因此每次重建MediaRecorder可能会对我们的性能造成影响。不过我会进一步调查,谢谢! - Stefan H Singer

0

显然在媒体播放器中没有办法检测录制何时停止,但是如果您创建一个实现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(); 
    }
}

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


1
但是当录制停止时,需要将更多的数据写入存储器,直到录制真正被写入存储器后,我们才能开始播放视频。 - Stefan H Singer
需要写什么?如果你正在编写自定义内容,那么从重写的停止方法内调用你的自定义函数,然后在调用之后设置已停止的变量。 - JPM
2
我知道当我们停止录制时。当录制停止时,录音机将数据写入磁盘,我想知道它何时完成写入数据 :) - Stefan H Singer

0
一种不太优雅的方法是检查文件的lastModified()值,并在文件未被修改2秒钟后打开VideoView。

我们已经有了一些hack的解决方案,但如果有更好的正式解决方案,我更愿意采用它。如果没有更好的方案,那么我们将继续使用我们的hack,并添加一些错误保护措施 :) - Stefan H Singer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接