【问题标题】:WAV file from user microphone vs. WAV file from file: Some difference is causing bugs, but what are these different?来自用户麦克风的 WAV 文件与来自文件的 WAV 文件:一些差异会导致错误,但这些有什么不同?
【发布时间】:2018-12-27 20:39:29
【问题描述】:

现在我有两种方法可以将 WAV 文件发送到服务器。用户可以直接上传所述文件,或在他们的麦克风上进行录音。发送文件后,它们的处理方式几乎相同。文件被发送到 S3,稍后可以通过单击某个链接来播放(通过audio = new Audio('https://S3.url'); audio.play()播放文件

处理来自麦克风的文件时:

  • audio.play() 似乎有效。 audio 对象中的所有内容都是相同的(除了 URL 本身),但声音实际上不会通过扬声器播放。另一方面,对于上传的文件,声音会通过扬声器播放。
  • 当我直接访问 URL 时,它们都会打开声音播放器(在 Chrome 中)或提示下载 WAV 文件(在 Firefox 中)。声音播放器适当地播放两种声音,并且下载的 WAV 文件各自包含各自的声音,其他程序可以播放这些声音
  • 如果我真的下载来自用户麦克风的带有声音的文件,而不是将其直接发送到服务器,然后手动上传 WAV 文件,一切都会正常运行(与任何其他文件一样)上传的 WAV 文件)。
  • 在麦克风声音上传到某处然后下载的任何情况下,它都会作为 WAV 文件下载并相应地播放。使用重新上传的 WAV 文件的任何内容都可以按预期工作。

以下是我从用户麦克风获取声音的方法。首先,我使用WebAudioTrack 在我的网页上放置一个录制按钮。一旦用户停止录制,他们点击运行的提交按钮:

saveRecButton.addEventListener("click", function() {
    save_recording(audioTrack.audioData.getChannelData(0))
});

这里,audioTrack.audioData 是一个包含录制声音的AudioBuffergetChannelData(0) 是代表声音的Float32Array。我通过 AJAX 将此数组发送到服务器(Django):

function save_recording(channelData){
    var uploadFormData = new FormData();
    uploadFormData.append('data', $('#some_field').val());
    ...
    uploadFormData.append('audio', channelData);

    $.ajax({
        'method': 'POST',
        'url': '/soundtests/save_recording/',
        'data': uploadFormData,
        'cache': false,
        'contentType': false,
        'processData': false,
        success: function(dataReturned) { 
            if (dataReturned != "success") {
               [- Do Some Stuff -]
            }
    });
}

然后,使用wavio,从数组中写入一个WAV文件:

import wavio
import tempfile
from numpy import array
def save_recording(request):
    if request.is_ajax() and request.method == 'POST':
        form = SoundForm(request.POST)
        if form.is_valid():
            with tempfile.NamedTemporaryFile() as sound_recording:
                sound_array_string = request.POST.get('audio')
                sound_array = array([float(x) for x in sound_array_string.split(',')])
                wavio.write(sound_recording, sound_array, 48000, sampwidth=4)
                sound_recording.seek(0)
                s3_bucket.put_object(Key=some_key, Body=sound_recording, ContentType='audio/x-wav')
            return HttpResponse('success')

那么,当需要听声音时:

在 Python 中:

import boto3
session = boto3.Session(aws_access_key_id='key', aws_secret_access_key='s_key')
bucket = self.session.resource('s3').Bucket(name='bucket_name')
url = session.client('s3').generate_presigned_url('get_object', Params={'Bucket':bucket.name, Key:'appropriate_sound_key'})

然后,在 JavaScript 中:

audio = new Audio('url_given_by_above_python')
audio.play()

如果我上传文件,音频播放良好,但如果我使用用户的麦克风,则根本无法播放。当我将麦克风声音上传到 S3 然后重新下载时,我可能会丢失一些关于 WAV 文件的内容吗?我知道下一步该去哪里;这两个文件之间的所有内容似乎都相同。这是两个 Audio 对象的转储,其中包含来自用户麦克风的 URL。另一个是从手动上传的文件创建的,该文件是从那个确切的用户麦克风重新下载的。文件看起来完全一样(除了 URL,它在访问或下载时会播放两种声音)。

这里肯定有一些不同,但我不知道它是什么,并且已经为此苦苦挣扎了几天。 :(

【问题讨论】:

  • 每个文件的fmt 块包含什么?

标签: javascript django audio amazon-s3


【解决方案1】:

您创建的声音文件是 32 位 PCM,可以说是非标准音频编解码器。 Chrome 支持 (source) 但 Firefox 不支持 (source, bug)。

将其编码为 16 位 PCM,它将被普遍接受。

编辑:如 cmets 中所述,this 是有问题的参数。

【讨论】:

  • 澄清一下,我假设这意味着将 sampwidth4 更改为 2?
  • @PatrickRoberts 是的! (wavio source 的第 237 - 241 行)
猜你喜欢
  • 2018-03-26
  • 2022-08-14
  • 1970-01-01
  • 2012-01-25
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多