在 Cordova 应用程序中录制和保存音频

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

啊,看着那个标题,你可能会想,“这在科尔多瓦肯定是一件简单的事情,而且肯定是雷蒙德,再一次,写博客是非常明显和简单的,只是为了把人们带到他的 亚马逊愿望清单 上。”是的,我也是这么想的。这个周末我开始为我儿子开发一个简单的小科尔多瓦应用程序。我认为这也会是一篇很棒的博文。但是在处理它时,我遇到了一个录音问题,这让我疯狂了几个小时,所以我想我最好分享一下,这样其他人就不必再用头撞墙了。

因为这个问题变成了一个皇家集群——你知道吗,我决定在这里详细地写博客,并在本周晚些时候讨论应用程序本身。现在,考虑这个用例:

“你想让用户录音。稍后,用户可以播放该录音。”

简单吧?所以我开始研究一种可以让用户进行录音并为其命名的表格。我希望他们能够录制并回放以确保他们喜欢它。

单击记录会触发对媒体捕获插件的调用:


 var captureerror = function(e) {
console.log('captureerror' ,e);
}

var capturesuccess = function(e) { console.log('capturesuccess');console.dir(e); $scope.sound.file = e[0].localurl; $scope.sound.filepath = e[0].fullpath; }

$scope.record = function() { navigator.device.capture.captureaudio( capturesuccess,captureerror,{duration:10}); }

这是此处的样板媒体捕获用法。我将 url 和文件路径都存储在 $scope 中,以便稍后保存。播放功能也很简单:


 var captureerror = function(e) {
console.log('captureerror' ,e);
}

var capturesuccess = function(e) { console.log('capturesuccess');console.dir(e); $scope.sound.file = e[0].localurl; $scope.sound.filepath = e[0].fullpath; }

$scope.record = function() { navigator.device.capture.captureaudio( capturesuccess,captureerror,{duration:10}); }

这在 android 和 ios 中运行良好。但我注意到一些奇怪的事情。当我在 capturesuccess 中查看媒体捕获对象时,我在 android 中看到了这个:

看到我叫出来的部分了吗?执着的。凉爽的。这给了我温暖的绒毛。然而,在 ios 中,我看到了这个:

如您所见,它被存储在一个临时位置,这是不好的。不幸的是,媒体捕获插件中没有任何内容可以更改以修改此行为。因此——答案很明确。

文件系统!

所以从理论上讲,这应该很容易。首先,我们选择一个涵盖 android 和 ios 的持久位置。文件插件提供了这样一个别名: cordova.file.datadirectory

我们有一个文件夹,对吧?所以实际上我们需要做的就是将文件从一个位置复制到另一个位置。复制。该死。文件。

但我们有一个问题。首先,我们必须给文件一个唯一的名称。为了处理这个问题,我只用了时间和现有的扩展。


 var captureerror = function(e) {
console.log('captureerror' ,e);
}

var capturesuccess = function(e) { console.log('capturesuccess');console.dir(e); $scope.sound.file = e[0].localurl; $scope.sound.filepath = e[0].fullpath; }

$scope.record = function() { navigator.device.capture.captureaudio( capturesuccess,captureerror,{duration:10}); }

然后我花了大约一个小时试图让复制命令工作。我首先添加了大量带有 f 字样的 console.log 消息。如果您不知道这个词是什么,请问您的青少年。我认为有了文件路径,我可以这样做:


 var captureerror = function(e) {
console.log('captureerror' ,e);
}

var capturesuccess = function(e) { console.log('capturesuccess');console.dir(e); $scope.sound.file = e[0].localurl; $scope.sound.filepath = e[0].fullpath; }

$scope.record = function() { navigator.device.capture.captureaudio( capturesuccess,captureerror,{duration:10}); }

但是,不,那太容易了。您需要先使用 window.resolvelocalfilesystemurl 。由于文件复制命令需要路径,因此您必须执行两次。这是我最终得到的代码。我删除了一些可能会冒犯某些读者的 console.log 消息。如果你好奇的话,我 不仅仅是 说脏话。


 var captureerror = function(e) {
console.log('captureerror' ,e);
}

var capturesuccess = function(e) { console.log('capturesuccess');console.dir(e); $scope.sound.file = e[0].localurl; $scope.sound.filepath = e[0].fullpath; }

$scope.record = function() { navigator.device.capture.captureaudio( capturesuccess,captureerror,{duration:10}); }

总而言之,还不错。一些嵌套的回调,几乎一半的代码都与我的应用程序有关,而不是实际问题,我花了一些时间才到达那里。

幸运的是,一切都很完美。

所以在这一点上,我已经保存了我的音频文件的位置,所以我可以在媒体 api 中使用它,但新位置不再适用于媒体插件。为什么?我不知道。我去年 写了 一篇关于当你使用媒体插件和相对路径时,你必须在 android 上做一些时髦的事情的博客,基本上是在你的相对 url 前加上前缀。就我而言,我使用的是 file:// url,我只是假设它会起作用。

这就是事情变得很棒的地方——它在 android 上运行得很好,但在 ios 上却不行。因为——原因。我在 cordova s​​lack 频道上提出了这个问题,@purplecabbage 提到相对路径可能有效。在我的开发工具中,我尝试通过控制台手动创建媒体对象。我发现——给定文件名——我可以通过将其用作根目录来使用媒体插件访问该文件: "../library/nocloud/"

所以现在我的播放代码如下所示:


 var captureerror = function(e) {
console.log('captureerror' ,e);
}

var capturesuccess = function(e) { console.log('capturesuccess');console.dir(e); $scope.sound.file = e[0].localurl; $scope.sound.filepath = e[0].fullpath; }

$scope.record = function() { navigator.device.capture.captureaudio( capturesuccess,captureerror,{duration:10}); }

嗯是的。就是这样。我的应用程序现在可以使用了。我可以录制和测试音频,并且可以将其保存到永久文件系统中。正如我所说,我将在本周晚些时候分享真正的应用程序。