使用MediaRecorder录制实时音频并解决文件损坏问题

admin 百科 11

使用MediaRecorder录制实时音频并解决文件损坏问题-第1张图片-佛山资讯网

本文详细阐述了如何使用JavaScript的MediaRecorder API进行实时音频录制,并通过PHP将其保存到服务器。核心内容包括解决录制文件损坏的关键问题,即在MediaRecorder实例化时正确指定音频MIME类型和编码器,以及处理数据块的两种策略:客户端累积发送最终Blob或服务器端追加(并强调其局限性),旨在帮助开发者生成可播放的音频文件。

引言:实时音频录制与挑战

在现代Web应用中,通过麦克风进行实时音频录制已成为常见需求。JavaScript的MediaRecorder API提供了强大的能力来实现这一目标。然而,在将录制的数据分块发送到服务器并保存时,开发者常会遇到一个棘手的问题:生成的音频文件无法播放或显示为损坏。这通常是由于对MediaRecorder的工作机制和音频文件格式的误解造成的。

本文将深入探讨这一问题,并提供一个基于JavaScript和PHP的解决方案,确保录制的音频文件能够正确保存和播放。

问题分析:为什么录制文件会损坏?

当使用MediaRecorder进行分块录制并将数据发送到服务器时,文件损坏的主要原因可以归结为以下两点:

  1. MIME类型和编码器定义不当: 许多开发者错误地尝试在Blob构造函数中指定音频的MIME类型和编码器(例如{ 'type' : 'audio/ogg; codecs=opus' })。然而,MediaRecorder生成的数据块的格式和编码方式,必须在其初始化时就确定。如果在MediaRecorder实例化时没有明确指定或指定了不兼容的类型,它可能会使用默认值,导致后续Blob构造中的类型声明与实际数据不符。
  2. 数据块处理不当: MediaRecorder通过ondataavailable事件分发的数据 (e.data) 是音频流的片段。对于一个连续可播放的音频文件,这些片段需要按照正确的顺序进行拼接。如果服务器端简单地使用file_put_contents覆盖文件,或者即使是追加,但没有正确处理容器格式(如OGG或WebM)的结构,最终文件仍会损坏。

解决方案一:正确初始化MediaRecorder

解决文件损坏问题的首要步骤是确保MediaRecorder在开始录制时就知道它应该生成什么格式的音频数据。这意味着需要在MediaRecorder的构造函数中明确指定mimeType。

核心修改:MediaRecorder构造函数

// ...
navigator.mediaDevices.getUserMedia({ audio: true })
    .then(function(stream) {
        // 定义MediaRecorder选项,指定MIME类型和编码器
        const mrOptions = { mimeType: 'audio/ogg; codecs=opus' }; 
        // 在此处初始化MediaRecorder时指定选项
        mediaRecorder = new MediaRecorder(stream, mrOptions);
        mediaRecorder.start(2000); // 每2秒触发一次ondataavailable事件

        mediaRecorder.ondataavailable = function(e) {
            // 确保e.data是非空的
            if (e.data.size > 0) {
                chunks.push(e.data);
                // 创建Blob时,使用MediaRecorder实际使用的MIME类型
                const blob = new Blob(chunks, { type: mediaRecorder.mimeType });
                chunks = []; // 清空chunks,准备接收下一个片段

                var reader = new FileReader();
                reader.readAsDataURL(blob); 
                reader.onloadend = function() {
                    var data = reader.result.split(";base64,")[1]; 
                    requestp2("a.php", "data=" + encodeURIComponent(data));
                }
            }
        };
    })
    .catch(function(err) {
        console.log('The following getUserMedia error occurred: ' + err);
    });
// ...

登录后复制

解释:

  • mrOptions = { mimeType: 'audio/ogg; codecs=opus' }:这里我们明确告诉MediaRecorder,我们希望它生成OGG容器格式的音频,并使用Opus编码器。Opus是一种高效的音频编码器,非常适合语音和音乐。
  • mediaRecorder = new MediaRecorder(stream, mrOptions):将定义好的选项传递给MediaRecorder构造函数。
  • const blob = new Blob(chunks, { type: mediaRecorder.mimeType });:在ondataavailable回调中创建Blob时,使用mediaRecorder.mimeType来确保Blob的类型与MediaRecorder生成的数据类型一致。

解决方案二:正确处理数据块(客户端累积 vs. 服务器端追加)

即使MediaRecorder生成了正确格式的音频数据块,如果这些块没有被正确地拼接起来,最终文件仍然会损坏。

策略一:客户端累积所有数据块,一次性发送 (推荐)

对于生成一个完整的、连续的音频文件,最健壮的方法是在客户端累积所有的e.data块,直到录制停止,然后将所有块合并成一个大的Blob,一次性发送到服务器。

客户端 JavaScript 修改:

标签: php javascript java html 编码 浏览器 app access ai 音乐 win stream

发布评论 0条评论)

还木有评论哦,快来抢沙发吧~