Python工具箱系列(六十二)

对录音文件进行操作

在参加会议、论坛时经常会有录音的需求。但限于条件,经常会出现录音的声音小需要增强,无关内容需要剪切等需求。此时,就需要对音频文件进行变换。以下代码演示了部分变换功能。

from pydub import AudioSegment
from pydub.silence import detect_silence, detect_nonsilent
from pathlib import Path
import glob
import matplotlib.pyplot as plt
import librosa
import librosa.display
from librosa.display import waveshow

def add_silence(audiofilename, silence_length, output_file):
    """
    给音频文件头增加一段静音

    Args:
        audiofilename (string): 音频文件名
        silence_length (int): 静音的秒数
        output_file (string): 输出的音频文件名
    """
    one_sec_segment = AudioSegment.silent(duration=silence_length*1000)
    sound = AudioSegment.from_file(audiofilename)

    final_song = one_sec_segment + sound
    final_song.export(output_file, format="wav")


def cut(audiofilename, start, duration, outputfilename):
    """
    从音频文件中切割一段并且输出为文件

    Args:
        audiofilename (string): 音频文件名
        start (int): 开始时间(秒)
        duration (int): 持续时间(秒)
        output_file (string): 输出的音频文件名
    """
    sound = AudioSegment.from_file(audiofilename)
    print(sound.duration_seconds, sound.dBFS, sound.frame_rate)
    cutstart = start*1000
    cutend = (start+duration)*1000
    clip = sound[cutstart:cutend]
    clip.export(outputfilename)


def cutbynonesilent(audiofilename):
    """
    从音频文件中切割所有非静音段,并且输出成系列文件

    Args:
        audiofilename (string): 音频文件名
    """
    sound = AudioSegment.from_file(audiofilename)

    # 非静音检测,按最少2秒,-50DB为分隔标准
    start_end_list = detect_nonsilent(sound, 2000, -50, 1)

    # 将非静音时段的音频单独输出
    pth = Path(audiofilename)
    for index, seg in enumerate(start_end_list):
        # 组合输出文件名
        outputfilename = Path.joinpath(pth.parent, f'{pth.stem}-{index}.wav')
        clip = sound[seg[0]:seg[1]]
        clip.export(outputfilename)


def continuous_mix(filelist, outputfilename):
    """
    串烧

    Args:
        filelist (list): 要串烧的文件列表
        outputfilename (string): 输出文件
    """
    one_sec_segment = AudioSegment.silent(duration=2*1000)
    mixer = AudioSegment.from_file(filelist[0])

    for file in filelist[1:]:
        # 在头上合成时加入一段静音进行分隔。
        clip = AudioSegment.from_file(file)
        mixer = mixer + one_sec_segment + clip

    # 渐入与渐出
    mixer.fade_in(1000).fade_out(1000)

    mixer.export(outputfilename)

def volum(audiofilename,factor):
    """
    放大或者缩小音量

    Args:
        audiofilename (string): 音频文件名
        factor (int): 正值为放大的分贝数,负值为缩小的分贝数
    """
    pth = Path(audiofilename)
    outputfilename = Path.joinpath(pth.parent, f'{pth.stem}-gain{pth.suffix}')
    sound = AudioSegment.from_file(audiofilename)
    sound += factor
    sound.export(outputfilename)
    
def test_mixer():
    # 串烧指定目录下的所有MP3文件
    globfiles = glob.iglob(r'd:\test\mp3\*.mp3')
    continuous_mix(list(globfiles), r'd:\test\done\mixer.mp3')


def test_cut():
    targetfilename = r'D:\test\m4a\1.m4a'
    cut(targetfilename, 10, 20, r'd:\test\cut1.wav')
    cutbynonesilent(targetfilename)

def test_volum():
    
    originaudio = r'D:\test\m4a\1-0.wav'
    changedaudio = r'D:\test\m4a\1-0-gain.wav'
    
    volum(originaudio,20)
    
    # plt.figure(figsize=(15,17))
    fig, ax = plt.subplots(nrows=2, sharex=True)
    
    origin ,sr = librosa.load(originaudio)
    librosa.display.waveshow(origin,sr=sr,ax=ax[0])
    ax[0].set(title='origin audio wave')
    ax[0].label_outer()

    changed ,sr = librosa.load(changedaudio)
    librosa.display.waveshow(changed,sr=sr,ax=ax[1])
    ax[1].set(title='changed audio wave')
    ax[1].label_outer()
    plt.show()
    
test_mixer()
test_cut()
test_volum()

上述代码中:

  • 综合使用了librosa/pydub两种声音处理库,各取所长。librosa能够在更底层处理音频文件,进行各类变换。
  • add_silence函数对指定的音频文件进行加工,在头部加入一段静音
  • cut函数对于指定的音频文件进行切割,能够将其中一段音频切出来后存为另一个音频文件
  • cutbynonesilent函数对于指定的音频文件进行切割,能够将非静音部分切割为不同的文件。这个功能对于录音来说非常必要。在现实的录音中,有可能存在大段的静音。切割后,可以针对每部分进行语音的加工(放大音量、语音转文字等)
  • continuous_mix函数是一个串烧的函数,能够将输入的文件列表中的文件依次合成在一起。形成一个串烧的效果,并且加入了静音,以及渐入渐出效果
  • volum函数对音频文件进行音量的增强与衰减。下图展示了音量变化的效果

python-audio-003.png

最后再整理一下安装过程:

pip install pyaudio
pip install pydub
pip install librosa
pip install matlibplot

代码中列出的MP3/wav文件可以随便替换,不必纠结。

posted @ 2025-08-15 16:30  西安衍舆航天  阅读(8)  评论(0)    收藏  举报