记录来自麦克风的JS声音或语音注释

记录来自麦克风的JS声音或语音注释


不久前,在开发一个公司Web应用程序时,客户希望能够留下语音评论。 以前,我没有遇到过媒体内容的创建,因此我开始对此感兴趣地进行研究。

该网络提供了有关创建和处理此类内容的足够的背景信息,但是我没有找到一个简单的,可以正常工作的示例。 在客户执行任务之后,我决定发布最简单的录音和保存语音评论示例,并撰写一篇文章。 也许这些材料对某人有用,并有助于研究。

问题陈述


我们为自己设定了开发在浏览器中运行的微型应用程序的任务,该应用程序将允许您记录语音注释,将记录发送到服务器,服务器将保存记录,如果成功,它将返回带有已创建文件名称的响应并将对象显示在页面上,以便可以收听记录。

在浏览器中录制声音


决定使用MediaStream Recording Web API来实现录音。 对于录制,我们使用MediaRecorder()接口。 但首先,创建一个接口。 让我们让index.html仅包含最基本的标签,在标签的主体中,我们将包含一个文件,其中包含我们将来的JavaScript voice.js:

<!DOCTYPE html> <head> <meta charset="UTF-8"> <title>Voice comments</title> </head> <body> <script src="voice.js"></script> </body> </html> 

创建一个voice.js文件,在其中定义一个URL常量,该常量将包含指向接收录制声音的脚本的链接。 接下来,创建“开始”和“停止”按钮以开始和停止录音,以及将在其中显示保存的记录的div块。 在此界面上,您可以直接进行录音。

正如已经提到的用于录制的内容一样,我们将使用MediaRecorder()接口(有关该接口的更多信息,请参见文档),对于其操作,必须确定要从中获取声音的媒体流,仅在仅需要音轨的情况下对其进行初始化。

 navigator.mediaDevices.getUserMedia({ audio: true}) .then(stream => { const mediaRecorder = new MediaRecorder(stream)}); 

现在,我们有了常量mediaRecorder,它包含接口的实例,并且我们将继续使用它。

要开始记录,我们需要调用MediaRecorder.start()方法,要停止记录,请调用MediaRecorder.stop()方法。 在这种情况下,MediaRecorder.stop()生成一个dataavailable事件,通过该事件我们可以访问二进制数组形式的数字化录音。

因此,我们将描述上述事件,声明voice []数组并将接收到的数据写入其中:

 navigator.mediaDevices.getUserMedia({ audio: true}) .then(stream => { const mediaRecorder = new MediaRecorder(stream); let voice = []; document.querySelector('#start').addEventListener('click', function(){ mediaRecorder.start(); }); mediaRecorder.addEventListener("dataavailable",function(event) { voice.push(event.data); }); document.querySelector('#stop').addEventListener('click', function(){ mediaRecorder.stop(); }); }); 

现在,我们将准备接收的数据以进行发送。 为此,通过stop事件,创建一个BLOB实例,将接收到的数据放入其中,并指定MIME数据类型。 在我们的情况下,它将是音频/ WAV。

 mediaRecorder.addEventListener("stop", function() { const voiceBlob = new Blob(voice, { type: 'audio/wav' }); 

结果,我们有了voiceBlob常量,该常量是我们将来录制语音消息的wav文件的内容。

将记录发送到服务器


为了将记录发送到服务器,我决定使用fetch()方法。 由于此方法是最现代的方法,并且提供了一种改进的接口,用于向服务器发出请求。 作为我们任务的一部分,我们需要在其主体中发起POST请求,以发送将来文件的内容以保存在服务器上(fetch()方法的工作方式以及在文档中详细找到的功能)。 使用语音字段创建一个新表单,然后将记录的内容放入其中。

 let fd = new FormData(); fd.append('voice', voiceBlob); 

我们创建了一个异步功能,用于向服务器发送消息以接收响应并显示音频对象以播放已保存的文件。 作为参数,该函数将采用上面创建的形式。

我们发起一个服务器请求:

 let promise = await fetch(URL, { method: 'POST', body: form}); 

如果来自服务器的HTTP响应不包含错误代码(响应代码在200-299的范围内),那么它仍然可供我们解码响应,在页面上创建新的音频对象,确定其属性并显示它。 答案的形成方式将在下面讨论。

在服务器上保存文件


让我们在服务器上创建一个脚本,该脚本将接收带有语音消息的POST请求。 由于我们发送的录音基本上已经是格式的文件,因此我们将在服务器上相应地接收它:

 $uploadDir = 'voice/'; $typeFile = explode('/', $_FILES['voice']['type']); $uploadFile = $uploadDir . basename(md5($_FILES['voice']['tmp_name'].time()).'.'.$typeFile[1]); if (move_uploaded_file($_FILES['voice']['tmp_name'], $uploadFile)) { $response = ['result'=>'OK', 'data'=>'../'.$uploadFile]; } else { $response = ['result'=>'ERROR', 'data'=>'']; } echo json_encode($response); 

您可以找到许多类似的PHP代码示例,它们可以处理网络上收到的文件。 首先,初始化变量$ uploadDir-接收到的文件将保存到的目录,在本例中,文件类型和typeFile等于wav,包括目录在内的完整文件名。 这种情况下的文件名是通过组合“临时”文件名和使用md5方法加密的当前时间的字符串值形成的。 如果您成功地将带有语音消息的文件保存到指定目录中,我们将以数组的形式形成响应,其中包含取决于结果的等于“ OK”或“ ERROR”的结果字段以及“ data”字段,如果成功处理,则包含指向已保存文件的链接。

为了方便起见,我们将数组转换为JSON对象,并将其作为响应发送。

完整的示例代码可在GitHub找到

PS浏览器仅允许您使用安全的HTTPS连接来记录媒体内容。

Source: https://habr.com/ru/post/zh-CN484196/


All Articles