Python Librosa efficient way to get a part from audio that matches condition

Viewed 26

I used librosa module to get this audio file signal, I used this code:

import librosa
import librosa.display
from matplotlib import pyplot as plt
from scipy.signal import butter, filtfilt
x, sr = librosa.load("./output.wav")
def butter_highpass(data,cutoff, fs, order=5):
    """
    Design a highpass filter.
    Args:
    - cutoff (float) : the cutoff frequency of the filter.
    - fs     (float) : the sampling rate.
    - order    (int) : order of the filter, by default defined to 5.
    """
    # calculate the Nyquist frequency
    nyq = 0.5 * fs
    # design filter
    high = cutoff / nyq
    b, a = butter(order, high, btype='high', analog=False)
    # returns the filter coefficients: numerator and denominator
    y = filtfilt(b, a, data)
    return y
x_f=butter_highpass(x,1000, sr, order=5)
plt.figure(figsize=(14, 5))
librosa.display.waveshow(x_f, sr=sr)
plt.show()

I get this:

I know python, but I don't have any knowledge of audio processing and this stuff.

Now, Is there a way to get all parts in a long file audio, let's say 1 hour, that have all this intense parts (music).

1 Answers

I found a way:

You can tweak the MIN_VAL until you get your desired result. The greater the value the script will find parts that have louder volume.

from pydub import AudioSegment
from pydub.utils import make_chunks
song = AudioSegment.from_wav("./m1.wav")
MIN_VAL = 0.1
li = []
li1 = []
max_amp = song.max_dBFS
average = song.dBFS
trigger_dbfs = average - average*MIN_VAL
chunk_length_ms = 5000 # pydub calculates in millisec
chunks = make_chunks(song, chunk_length_ms)
s= 0
start = False
for i in chunks:
    if round(trigger_dbfs,1) <= round(i.dBFS,1):
        if not start:
            start = True

        li.append(i)
    elif start==True:
        li1.append(sum(li, AudioSegment.empty()))
        li = []
        start = False

for i in range(len(li1)):
    li1[i].export(f"audio/{i}.mp3", format="mp3")
a = sum(li1, AudioSegment.empty())
a.export(f"full.mp3", format="mp3")

You will have all parts in song/ directory. And a full.mp3 in the main directory that will have all the parts in one audio file.

Note: You can also change chunk_length_ms value in milliseconds, the value will divide audio by the milliseconds you specify to calculate the volume. If you set a value less than 1 second you will get funky results

Edit: I wrote a repository, you can check it Bensound-Extract-loud-parts-from-audio

Related