2015-10-20 41 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文件處於完美狀態。