Khachatur Mirijanyan
Khachatur Mirijanyan

Reputation: 435

Split audio on timestamps librosa

I have an audio file and I want to split it every 2 seconds. Is there a way to do this with librosa?

So if I had a 60 seconds file, I would split it into 30 two second files.

Upvotes: 7

Views: 16860

Answers (4)

Anna Andreeva Rogotulka
Anna Andreeva Rogotulka

Reputation: 1620

you can split array in chunks just using index spliting, in order to get 2 seconds you need 2 * sample rate values from array and then step ahead

import librosa
import soundfile as sf


audio_file = "0.wav"
y, sr = librosa.load(audio_file, sr=None) 

# chunk duration 2 seconds
chunk_duration = 2  


chunk_samples = int(chunk_duration * sr)


chunks = [y[i:i + chunk_samples] for i in range(0, len(y), chunk_samples)]

for i, chunk in enumerate(chunks):
    output_file = f"chunk_{i}.wav"
    sf.write(output_file, chunk, sr)

Upvotes: 5

maniac
maniac

Reputation: 1192

Here a funciton to get a certain time frame of the file:

def split_music(
        audio_file: Tuple[np.ndarray, float] | str,
        from_second: int = 0,
        to_second: int = None,
        save_file_path: str = None,
        ) -> Tuple[np.ndarray, float]:
    """
    This code splits an audio file based on the provided seconds
    :param audio_file: either an audio file loaded by librosa or an filepath to load audio from
    :param from_second: the second when the split starts
    :param to_second: the second when the split ends
    :param save_file_path: if provided audio snippet will be saved at location
    :return: the audio snippet as ndarray, sample_rate
    """
    # load audio from file
    if type(audio_file) == str:
        audio_file, sr = librosa.load(file_path)
    elif type(audio_file) == Tuple[np.ndarray, float]:
        audio_file, sr = audio_file

    # last second is end of file if not provided
    to_second = len(audio_file) if to_second is None else to_second
    # split audio
    audio_file = audio_file[from_second*sr:to_second*sr]

    if save_file_path is not None and type(save_file_path) == str:
        # add extension if necessary
        save_file_path, ext = os.path.splitext(save_file_path)
        save_file_path = save_file_path + ".wav" if not ext else save_file_path + ext
        # save to file
        sf.write(save_file_path, audio_file, sr)

    return audio_file, sr

Upvotes: 0

eracube
eracube

Reputation: 2639

You can split your file using librosa running the following code. I have added comments necessary so that you understand the steps carried out.

# First load the file
audio, sr = librosa.load(file_name)

# Get number of samples for 2 seconds; replace 2 by any number
buffer = 2 * sr

samples_total = len(audio)
samples_wrote = 0
counter = 1

while samples_wrote < samples_total:

    #check if the buffer is not exceeding total samples 
    if buffer > (samples_total - samples_wrote):
        buffer = samples_total - samples_wrote

    block = audio[samples_wrote : (samples_wrote + buffer)]
    out_filename = "split_" + str(counter) + "_" + file_name

    # Write 2 second segment
    librosa.output.write_wav(out_filename, block, sr)
    counter += 1
    samples_wrote += buffer

[Update]

librosa.output.write_wav() has been removed from librosa, so now we have to use soundfile.write()

Import required library

import soundfile as sf

replace

librosa.output.write_wav(out_filename, block, sr)

with

sf.write(out_filename, block, sr)

Upvotes: 4

Hendrik
Hendrik

Reputation: 5310

librosa is first and foremost a library for audio analysis, not audio synthesis or processing. The support for writing simple audio files is given (see here), but it is also stated there:

This function is deprecated in librosa 0.7.0. It will be removed in 0.8. Usage of write_wav should be replaced by soundfile.write.

Given this information, I'd rather use a tool like sox to split audio files.

From "Split mp3 file to TIME sec each using SoX":

You can run SoX like this:

 sox file_in.mp3 file_out.mp3 trim 0 2 : newfile : restart

It will create a series of files with a 2-second chunk of the audio each.

If you'd rather stay within Python, you might want to use pysox for the job.

Upvotes: 3

Related Questions