使用Python在音频文件的特定位置插入WAV文件

2 投票
5 回答
2167 浏览
提问于 2025-04-15 20:22

我的问题是这样的:我有一个2分钟长的WAV音频文件,我想在这个音频文件的某个位置(比如说0:48)插入另一个7秒长的WAV音频文件,也就是把这两个WAV文件合在一起,用Python来实现。不幸的是,我一直没能找到办法去做这件事,不知道是不是有什么明显的解决方案我没想到,或者用Python实现这个是否可行。有没有什么库可以提供帮助呢?谢谢大家!

根据原帖评论的更新:

我应该说明一下,我想插入的WAV文件要和原来的WAV文件“重叠”播放,这样两个音频才能同时响起,抱歉没有说清楚。有没有办法实现这样的效果呢?

5 个回答

1

使用 pydub这个包 (老实说,这个包是我写的)

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')
1

如果它们是PCM编码的,你可以使用wave这个工具;如果不是的话,就可以用类似pygst这样的工具。

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()

我写这段代码的时候没有测试过,所以可能会有错误(甚至是语法错误);不过我在使用Python的经验是,很多时候代码直接运行就没问题;-)

如果你还需要其他帮助,随时告诉我哦。

撰写回答