音频变速python版

音频变速

如何能在不改变音频其他特点的情况下,只改变语速呢?

有几个python的库可以实现该功能,下面一一介绍。

pydub库

首先,确保安装了pydub和ffmpeg。

下面是一个简单的Python脚本,展示如何改变音频的播放速度:

python 复制代码
from pydub import AudioSegment
from pydub.playback import play


def change_speed(audio_file, speed=1.0):
    sound = AudioSegment.from_file(audio_file)
    # 增加速度
    sound_with_altered_speed = sound._spawn(sound.raw_data, overrides={
         "frame_rate": int(sound.frame_rate * speed)
    }).set_frame_rate(sound.frame_rate)
    return sound_with_altered_speed

# 加载音频文件
audio_path = "your_audio_file.mp3"
# 改变速度,例如1.5倍速
altered_sound = change_speed(audio_path, speed=1.5)
# 播放修改后的音频
play(altered_sound)
# 导出音频
altered_sound.export("modified_audio.mp3", format="mp3")

change_speed函数接受原始音频文件路径和速度因子。通过修改帧率来改变速度。如果你想要加快速度,可以将速度因子设置为大于1的值;如果想要减慢速度,将其设置为小于1的值。

但是该方法在改变语音的同时,使得音调也发生改变。

librosa库

librosa主要用于音乐和音频分析。它支持音频的时间伸缩(即改变音频速度而不改变音调),并且提供了许多其他音频处理功能。

实现代码:

python 复制代码
import librosa
import soundfile as sf

audio_path = 'your_audio_file.wav'
y, sr = librosa.load(audio_path, sr=None)  # sr=None 保持原始采样率

# 变速处理,比如加速1.5倍
y_change = librosa.effects.time_stretch(y, 1.5)
#保存
sf.write('output_audio_file.wav', y_change, sr)

在改变音频速度的同时保持原有音调,librosa使用了时间拉伸算法(Time Stretching)。

librosa.effects.time_stretch函数是用于调整音频的播放速度,同时不改变音频的音高(音调)。

我们看下这个函数源码:

python 复制代码
def time_stretch(y, rate, **kwargs):
    '''Time-stretch an audio series by a fixed rate.'''
  
    if rate <= 0:
        raise ParameterError('rate must be a positive number')

    # Construct the short-term Fourier transform (STFT)
    stft = core.stft(y, **kwargs)

    # Stretch by phase vocoding
    stft_stretch = core.phase_vocoder(stft, rate)

    # Predict the length of y_stretch
    len_stretch = int(round(len(y)/rate))

    # Invert the STFT
    y_stretch = core.istft(
        stft_stretch, dtype=y.dtype, length=len_stretch, **kwargs)

    return y_stretch

可以看到,该函数主要包含三个步骤:

1.音频的频谱表示

首先,librosa.effects.time_stretch利用短时傅里叶变换(STFT)将音频信号从时间域转换到频域。这种转换将音频分解成其组成的频率成分,每个成分都有相应的幅度和相位。

2.相位估计(phase_vocoder)

在进行时间伸缩处理时,保持相位连续性是一个重要的挑战。librosa采用了相位估计技术来调整每个频率成分的相位,以保证在变速过程中音频信号的相位连续性。这是通过相位重构实现的,确保在变速后的音频中,所有频率成分的相位都能正确对齐。

3.相位恢复和重构,重建音频

处理相位信息时,使用相位展开技术,从原始音频中提取和修改相位信息,然后在处理过程中适当调整这些信息以匹配新的时间伸缩率。

最后,将处理过的频谱数据通过逆短时傅里叶变换(ISTFT)重新转换回时间域,生成最终的音频输出。在这一步中,经过调整的幅度和重构的相位信息被合成,以产生时间伸缩后的音频信号。

补充:相位声码器Phase vocoder

相位声码器(phase vocoder)是一种特殊的声码器,用于分析和修改音频信号的频谱相位。它是在数字信号处理中广泛使用的一种工具,特别适用于时间伸缩(改变音频速度而不改变音调)和音高移动(改变音调而不改变速度)。

相位声码器技术可以实现音频的时间伸缩。这一技术是基于频域处理,它可以调整音频的时长而不改变音高,主要依靠精确的相位处理。

先看看源码:

python 复制代码
def phase_vocoder(D, rate, hop_length=None):
    """Phase vocoder.  Given an STFT matrix D, speed up by a factor of `rate`

    Based on the implementation provided by [1]_.

    .. note:: This is a simplified implementation, intended primarily for
             reference and pedagogical purposes.  It makes no attempt to
             handle transients, and is likely to produce many audible
             artifacts.  For a higher quality implementation, we recommend
             the RubberBand library [2]_ and its Python wrapper `pyrubberband`.

    .. [1] Ellis, D. P. W. "A phase vocoder in Matlab."
        Columbia University, 2002.
        http://www.ee.columbia.edu/~dpwe/resources/matlab/pvoc/

    .. [2] https://breakfastquay.com/rubberband/

    Parameters
    ----------
    D : np.ndarray [shape=(d, t), dtype=complex]
        STFT matrix

    rate :  float > 0 [scalar]
        Speed-up factor: `rate > 1` is faster, `rate < 1` is slower.

    hop_length : int > 0 [scalar] or None
        The number of samples between successive columns of `D`.

        If None, defaults to `n_fft/4 = (D.shape[0]-1)/2`

    Returns
    -------
    D_stretched : np.ndarray [shape=(d, t / rate), dtype=complex]
        time-stretched STFT

    See Also
    --------
    pyrubberband
    """

    n_fft = 2 * (D.shape[0] - 1)

    if hop_length is None:
        hop_length = int(n_fft // 4)

    time_steps = np.arange(0, D.shape[1], rate, dtype=np.float)

    # Create an empty output array
    d_stretch = np.zeros((D.shape[0], len(time_steps)), D.dtype, order='F')

    # Expected phase advance in each bin
    phi_advance = np.linspace(0, np.pi * hop_length, D.shape[0])

    # Phase accumulator; initialize to the first sample
    phase_acc = np.angle(D[:, 0])

    # Pad 0 columns to simplify boundary logic
    D = np.pad(D, [(0, 0), (0, 2)], mode='constant')

    for (t, step) in enumerate(time_steps):

        columns = D[:, int(step):int(step + 2)]

        # Weighting for linear magnitude interpolation
        alpha = np.mod(step, 1.0)
        mag = ((1.0 - alpha) * np.abs(columns[:, 0])
               + alpha * np.abs(columns[:, 1]))

        # Store to output array
        d_stretch[:, t] = mag * np.exp(1.j * phase_acc)

        # Compute phase advance
        dphase = (np.angle(columns[:, 1])
                  - np.angle(columns[:, 0])
                  - phi_advance)

        # Wrap to -pi:pi range
        dphase = dphase - 2.0 * np.pi * np.round(dphase / (2.0 * np.pi))

        # Accumulate phase
        phase_acc += phi_advance + dphase

    return d_stretch

直接调用调用phase_vocoder来实现时间伸缩。这里是一个简单的示例:

python 复制代码
import librosa

# 加载音频数据
y, sr = librosa.load('audio_file.wav', sr=None)

# 计算STFT
D = librosa.stft(y)

# 应用相位声码器进行时间伸缩
D_stretched = librosa.core.phase_vocoder(D, rate=1.5)

# 通过逆STFT重构音频
y_stretched = librosa.istft(D_stretched)

基本原理:

相关推荐
一个小猴子`8 分钟前
FFMpeg音视频解码实战
ffmpeg·音视频
小白教程23 分钟前
Python爬取视频的架构方案,Python视频爬取入门教程
python·架构·音视频·python爬虫·python视频爬虫·python爬取视频教程
仰望星空的小随1 小时前
django相关面试题
python·django·sqlite
2401_890665862 小时前
免费送源码:Java+SpringBoot+MySQL SpringBoot网上宠物领养管理系统 计算机毕业设计原创定制
java·vue.js·spring boot·python·mysql·pycharm·html5
黑不拉几的小白兔2 小时前
第十五届蓝桥杯大赛软件赛省赛Python 大学 B 组试做(下)【本期题单: 缴纳过路费, 纯职业小组】
数据库·python·蓝桥杯
仙人掌_lz2 小时前
使用Python从零实现一个端到端多模态 Transformer大模型
开发语言·人工智能·python·ai·transformer·多模态
Json____2 小时前
springboot 处理编码的格式为opus的音频数据解决方案【java8】
spring boot·后端·音视频·pcm·音频处理·解码器·opus
赤鸢QAQ2 小时前
ffpyplayer+Qt,制作一个视频播放器
python·qt·音视频
隔壁小查2 小时前
【后端开发】Spring MVC阶段总结
python·spring·mvc
kgduu3 小时前
Python编程快速上手 让繁琐工作自动化笔记
python