2010-03-12 104 views
2

我的問題如下: 我有一個2分鐘長的WAV文件,我的目標是在另一個WAV文件(7秒長)上插入一個第一個WAV文件中的某個點(比如0:48),實質上是使用python合併了兩個WAV。不幸的是,我一直無法弄清楚如何做到這一點,並想知道是否有一些明顯的解決方案,我錯過了,或者如果甚至可以用python做。是否有可能提供解決方案的圖書館? 感謝所有提前。使用python在音頻文件中的某個點插入WAV

UPDATE基於OP評論:

我應該澄清,我想插入的WAV到「重疊」的原始WAV這樣既會演奏,我的道歉。有沒有辦法達到這樣的效果?

回答

1

鬆散的基礎上由Justin代碼,這裏是一些其他的代碼,可能你想要做什麼:

import wave, audioop 

def merge_wav_at_offset(wav_in1, wav_in2, offset, wav_out): 
    """Merge two wave files, with the second wave starting at offset seconds 
    The two input wave files should have the same frame rate, channels, depth 
    Also, offset should be non-negative and can be floating point.""" 
    wf1= wave.open(wav_in1, 'rb') 
    wf2= wave.open(wav_in2, 'rb') 
    wfo= wave.open(wav_out, 'wb') 

    wfout.setparams(wf1.getparams()) 

    frame_rate = wf1.getframerate() 
    sample_width= wf1.getsampwidth() 
    if offset < 0: 
     offset= 0 
    prologue_frames= int(frame_rate*offset) 
    merge_frames= wf2.getnframes() 

    # prologue 
    frames_to_read= prologue_frames 
    while frames_to_read > 0: 
     chunk_size= min(frame_rate, frames_to_read) 
     wfo.writeframes(wf1.readframes(chunk_size)) 
     frames_to_read-= chunk_size 

    # merging 
    frames_to_read= merge_frames 
    while frames_to_read > 0: 
     chunk_size= min(frame_rate, frames_to_read) 
     frames2= wf2.readframes(chunk_size) 

     if frames2: 
      frames1= wf1.readframes(chunk_size) 
      if len(frames1) != len(frames2): # sanity check 
       # obviously you should cater for this case too 
       raise NotImplementedError, "offset+duration(wf2) > duration(wf1)" 
      merged_frames= audioop.add(frames1, frames2, sample_width) 
      wfo.writeframes(merged_frames) 
     else: # early end of wf2 data; improbable but possible 
      break 

     frames_to_read-= chunk_size 

    # epilogue 
    while True: 
     frames= wf1.readframes(frame_rate) 
     if not frames: break 
     wfo.writeframes(frames) 

    for wave_file in wf1, wf2, wfo: 
     wave_file.close() 

我只寫了未經測試的代碼,所以它可能是我有一個bug(甚至語法錯誤);然而,我對Python的使用經驗是,代碼經常按原樣運行;-) 如果您需要更多信息,請告訴我。

+0

非常感謝。不知道關於audioop。 – Onion 2010-04-14 17:44:07

+0

嗯,只是一個問題,爲了使文件合併,儘管偏移+持續時間(wf2)>持續時間(wf1),必須完成什麼? – Onion 2010-04-22 17:31:27

+0

@Onion:我會說,合併'min(len(frames1),len(frames2))',將剩餘的幀(可能來自'frames2')寫出來,打破循環。 – tzot 2010-04-22 19:06:33

1

如果他們是PCM編碼,那麼你可以使用wave,否則使用類似pygst

+0

我在浪潮已經顯得過,但不知道如何才能解決我的問題,使用它。能否以這種方式來指導我如何使用它的例子?謝謝。 – Onion 2010-03-12 22:01:48

+0

只需創建一個用於寫入的新文件,然後讀入並寫出適當數量的幀,寫出插入內容,然後讀取和寫入其餘幀。 – 2010-03-12 22:09:56

0

下面是一些代碼,讓你在正確的方向:

wf = wave.open('in1.wav','rb') 
wf2 = wave.open('in2.wav','rb') 
wfout = wave.open('out.wav','wb') 

wfout.setparams(wf.getparams()) 

sr = wf.getframerate() 
for x in xrange(48): 
    wfout.writeframes(wf.readframes(sr) 
wfout.writeframes(wf2.readframes(sr)) 
for x in xrange(72): 
    wfout.writeframes(wf.readframes(sr)) 

這應該做你在你的問題已經描述了(增加1秒夾48秒變爲2分鐘的歌曲)只要波形格式相同(相同的採樣率,相同的通道數量等)。你可能會讀/寫更大的塊,而不是一秒鐘,但我做了他們作爲1秒的塊來保證安全。

+0

@Justin我會認爲你應該總是打開一個wav文件作爲二進制''rb''或''wb'',而不是你的答案中顯示的文本。 – 2010-03-12 23:05:37

+0

@ Jon-Eric我原本是有'rb''和''wb'的,但後來我看了一下wave上的文檔,它只是說'r'和'w'。我以兩種方式嘗試了代碼,它似乎沒有什麼區別。查看在線文檔並沒有真正照亮我。添加'b'可能更安全,所以我會更改我的代碼。 – 2010-03-12 23:45:52

+0

儘管上面的代碼有效,並且插入的wav在期望的時間播放,似乎原始的wav(2分鐘的歌曲)在插入的wav期間停止播放,然後繼續播放,其效果是是不需要的。我應該澄清,我想要插入的wav「重疊」原始的wav,這樣兩個人都會玩,我的道歉。有沒有辦法達到這樣的效果? – Onion 2010-03-14 12:44:11

1

使用pydub package(充分披露 - 我寫的)

from pydub import AudioSegment 

sound1 = AudioSegment.from_wav('your_wave.mp3') 
the_wave = AudioSegment.from_wav('the_7sec_wave.wav') 

sound_with_wave = sound1.overlay(the_wave, position=48*1000) 

sound_with_wave.export('overlaid.wav', format='wav')