- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
cwac-camera 库具有在保存照片之前调用的事件 Hook :
@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 是否有办法检测录制的文件并发出信号。
--
我刚刚在 http://developer.android.com/reference/android/media/MediaRecorder.html#setMaxDuration(int) 的 Android 文档中跳过了这个
“停止是异步发生的,不能保证记录器会在通知监听器时停止。”
这解释了为什么文件有时没有正确关闭,这隐含地意味着使用 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
有两点很奇怪:
不确定是我在某处犯了错误还是 cwac-camera 出了问题。
有人要评论吗?
--
关于 2.,无论那是什么,我的日志显示触发事件的媒体记录器是相同的,并且在 what=800 (MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) 之后不久,一个未记录的 what=536871912 被引发。第二次引发事件时未记录的 what=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 事件也被引发了两次,但是未记录的 what=?根本没有提出。供应商特定实现?
[来自三星 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
最佳答案
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() 不起作用,因为它可能会在文件实际写入磁盘之前报告文件已完成。
关于android - 检测视频文件何时真正写入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26986821/
缓冲区溢出问题是众所周知的。因此,我们有幸使用标准库函数,例如 wcscat_s()。 Microsoft 的好心人已经创建了类似的安全字符串函数,例如 StringCbCat()。 但是我遇到了一个
HTTP缓存相关的问题好像是前端面试中比较常见的问题了,上来就会问什么cache-control字段有哪些,有啥区别啥的。嗯……说实话,我觉得至少在本篇来说,HTTP缓存还算不上复杂,只是字段稍
代理,其实全称应该叫做代理服务器,它是客户端与服务器之间得中间层,本质上来说代理就是一个服务器,在HTTP的链路中插入的一个中间环节,就是代理服务器啦。所谓的代理服务就是指:服务本身不生产内容,
我们在前两篇的内容中分别学习了缓存和代理,大致了解了缓存有哪些头字段,代理是如何服务于服务器和客户端的,那么把两者结合起来,代理缓存,也就是说代理服务器也可以缓存,当客户端请求数据的时候,未必一
在前面的章节,我们把HTTP/1.1的大部分核心内容都过了一遍,并且给出了基于Node环境的一部分示例代码,想必大家对HTTP/1.1已经不再陌生,那么HTTP/1.1的学习基本上就结束了。这两
我们前一篇学习了HTTP/2,相比于HTTP/1,HTTP/2在性能上有了大幅的改进,但是HTTP/2因为底层还是基于TCP协议的,虽然HTTP/2在应用层引入了流的概念,利用多路复用解决了队头
前面我们花了很大的篇幅来讲HTTP在性能上的改进,从1.0到1.1,再到2.0、3.0,HTTP通过替换底层协议,解决了一直阻塞性能提升的队头阻塞问题,在性能上达到了极致。 那么,接下
上一篇噢,我们搞明白了什么是安全的通信,这个很重要,特别重要,敲黑板!! 然后,我们还学了HTTPS到底是什么,以及HTTPS真正的核心SSL/TLS是什么。最后我们还聊了聊TLS的实
经过前两章的学习,我们知道了通信安全的定义以及TLS对其的实现~有了这些知识作为基础,我们现在可以正式的开始研究HTTPS和TLS协议了。嗯……现在才真正开始。 我记得之前大概聊过,当
这一篇文章,我们核心要聊的事情就是HTTP的对头阻塞问题,因为HTTP的核心改进其实就是在解决HTTP的队头阻塞。所以,我们会讲的理论多一些,而实践其实很少,要学习的头字段也只有一个,我会在最开始
我们在之前的文章中介绍HTTP特性的时候聊过,HTTP是无状态的,每次聊起HTTP特性的时候,我都会回忆一下从前辉煌的日子,也就是互联网变革的初期,那时候其实HTTP不需要有状态,就是个浏览页面
前面几篇文章,我从纵向的空间到横向的时间,再到一个具体的小栗子,可以说是全方位,无死角的覆盖了HTTP的大部分基本框架,但是我聊的都太宽泛了,很多内容都是一笔带过,再加上一句后面再说就草草结束了。
我的问题确实很简单,是否应该对适配器(设计模式)类进行单元测试,以及如何进行测试? 例子: 我想用PHP创建一个ClientSocket类,它是fsockopen,fread,fwrite的适配器。
目前,我在 PHP 脚本中使用此查询: SELECT * FROM `ebooks` WHERE `id`!=$ebook[id] ORDER BY RAND() LIMIT 125; 数据库最多大约
我们都知道可以使用 GetCustomAttributes 方法查询程序集的属性。我想用它来识别我的应用程序的扩展模块。但是,为了避免加载每个程序集,我更喜欢防御性方法: 使用 Assembly.Re
我正在移植一个非常大的代码库,我在处理旧代码时遇到了更多困难。 例如,这会导致编译器错误: inline CP_M_ReferenceCounted * FrAssignRef(CP_M_Refere
[关于此主题还有其他类似的问题,但是它们都没有回答我在这里提出的问题,即AFAICT。 (即,我已经阅读了所有答案,解释了为什么特定构造无法与发问者尝试进行的操作,在某些情况下,它们提供了获得所需结果
嗨 我想为需要全屏运行的网络艺术应用程序构建一个控制面板,因此所有控制颜色和速度值等内容的面板都必须位于不同的窗口中。 我的想法是建立一个数据库来存储所有这些值,当我在控制面板窗口中进行更改时,应用程
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
假设我想实现一个分布式数据库(每个节点都是其他节点的副本);我听说 cdb 能够轻松地在两个节点之间进行同步,并且至少支持某种形式的冲突解决。 不幸的是我不知道 couchdb 因此我不得不问:节点“
我是一名优秀的程序员,十分优秀!