2015-10-20 42 views
0

我想为我的webapp写一个wav上传函数。前端部分似乎工作得很好。问题是我的后端(python)。当它收到二进制数据时,我不知道如何将它写入文件。我尝试使用基本的写入功能,声音是腐败的...听起来像“gobbly-gook”。有没有一种特殊的方式来在Python中编写wav文件?到wav文件的二进制字符串

这是我的后端...并不是很重要。

form = cgi.FieldStorage() 
fileData = str(form.getvalue('data')) 

with open("audio", 'w') as file: 
    file.write(fileData) 

我甚至尝试...

with open("audio", 'wb') as file: 
    file.write(fileData) 

我使用aplay播放声音,我发现所有的属性被搞砸了为好。

前: 符号16位小端,价格44100赫兹,立体声

上传后: 无符号8位,汇率8000赫兹,单声道

+1

什么是'cgi.FieldStorage()'?你也不应该从二进制数据中创建一个字符串。 –

+0

CGI(通用网关接口)是我用来获取HTTP请求的东西。我的声音文件二进制数据通过AJAX请求发送,脚本从cgi.FieldStorage中读取二进制字符串。 – Taztingo

+1

所以你在['cgi'](https://docs.python.org/3/library/cgi.html)模块中使用Python的构建?在发布原始声音数据的情况下,我认为你根本不应该使用'cgi.FieldStorage'。我忘记了CGI是如何工作的,但我认为你只是从stdin中读取数据; 'FieldStorage'看起来像是代表'

'标签。 –

回答

2

也许wave module可能帮助?

import wave 
import struct 
import numpy as np 

rate = 44100 

def sine_samples(freq, dur): 
    # Get (sample rate * duration) samples on X axis (between freq 
    # occilations of 2pi) 
    X = (2*np.pi*freq/rate) * np.arange(rate*dur) 

    # Get sine values for these X axis samples (as integers) 
    S = (32767*np.sin(X)).astype(int) 

    # Pack integers as signed "short" integers (-32767 to 32767) 
    as_packed_bytes = (map(lambda v:struct.pack('h',v), S)) 
    return as_packed_bytes 

def output_wave(path, frames): 
    # Python 3.X allows the use of the with statement 
    # with wave.open(path,'w') as output: 
    #  # Set parameters for output WAV file 
    #  output.setparams((2,2,rate,0,'NONE','not compressed')) 
    #  output.writeframes(frames) 

    output = wave.open(path,'w') 
    output.setparams((2,2,rate,0,'NONE','not compressed')) 
    output.writeframes(frames) 
    output.close() 

def output_sound(path, freq, dur): 
    # join the packed bytes into a single bytes frame 
    frames = b''.join(sine_samples(freq,dur)) 

    # output frames to file 
    output_wave(path, frames) 

output_sound('sine440.wav', 440, 2) 

编辑:

我觉得你的情况,你可能只需要:

packedData = map(lambda v:struct.pack('h',v), fileData) 
frames = b''.join(packedData) 
output_wave('example.wav', frames) 

在这种情况下,你只需要知道的采样率。检查波形模块以获取有关其他输出文件参数的信息(即参数为setparams方法)。

+0

我唯一关心的是上传的文件。我不会知道频率或持续时间。这就是为什么我希望能制作一份二进制副本。我在Javascript中使用file.readAsBinaryString。我猜我必须得到频率,持续时间等等,然后才把它发送给我的python? – Taztingo

+0

我不这么认为。我只是把那个代码放在那里作为如何生成原始二进制数据的例子。我会更新我的评论。 – dogwynn

+0

我可以用我在上面发布的代码来做到这一点。发送的数据实际上已经搞乱了。我通过将它作为base64编码发送来修复它,而不仅仅是二进制。无论如何,感谢您的帮助。 – Taztingo

0

只要数据没有损坏,我粘贴的代码就会写入一个wav文件。没有必要使用波模块。

with open("audio", 'w') as file: 
    file.write(fileData) 

我最初是以Javascript读取文件为FileAPI.readAsBinaryString。我将其更改为FileAPI.readAsDataURL,然后使用base64.decode()在python中对其进行解码。一旦我解码它,我就可以将数据写入文件。 .wav文件处于完美状态。