NAudio to split mp3 file
Asked Answered
R

5

13

I am very new to audio or mp3 stuff, was looking for a way to have a feature to split an mp3 file in C#, asp.net. After googling for a good 3-day without much of a great help, I am hoping that somebody here can point me to a right direction.

Can I use NAudio to accomplish this? Is there any sample code for that? Thanks in advance.

Rheumatism answered 23/5, 2011 at 7:47 Comment(1)
possible duplicate of Trim an MP3 ProgramaticallyDib
R
13

My final solution to split mp3 file in c# is to use NAudio. Here is a sample script for that, hope it helps someone in the community:

string strMP3Folder = "<YOUR FOLDER PATH>";
string strMP3SourceFilename = "<YOUR SOURCE MP3 FILENAMe>";
string strMP3OutputFilename = "<YOUR OUTPUT MP3 FILENAME>";

using (Mp3FileReader reader = new Mp3FileReader(strMP3Folder + strMP3SourceFilename))
{
    int count = 1;
    Mp3Frame mp3Frame = reader.ReadNextFrame();
    System.IO.FileStream _fs = new System.IO.FileStream(strMP3Folder + strMP3OutputFilename, System.IO.FileMode.Create, System.IO.FileAccess.Write);

    while (mp3Frame != null)
    {
        if (count > 500) //retrieve a sample of 500 frames
            return;

        _fs.Write(mp3Frame.RawData, 0, mp3Frame.RawData.Length);
        count = count + 1;
        mp3Frame = reader.ReadNextFrame();
     }

     _fs.Close();
}

Thanks to Mark Heath's suggestion for this.

The namespace required is NAudio.Wave.

Rheumatism answered 24/5, 2011 at 3:10 Comment(4)
why are you closing and re-opening the Filestream for each frame? This will not perform well.Mclain
It was just for a quick test on the NAudio. You are right, it should not be keep opening and closing on the file stream, edited the code.Rheumatism
how long is a frame?Keratitis
@AndreyKaplun double audioLengthInSeconds = (double) frame.SampleCount / frame.SampleRate;Solifidian
O
12

An MP3 File is made up of a sequence of MP3 frames (plus often ID3 tags on the beginning and end). The cleanest way to split an MP3 file then is to copy a certain number of frames into a new file (and optionally bring the ID3 tags along too if that is important).

NAudio's MP3FileReader class features a ReadNextFrame method. This returns an MP3Frame class, which contains the raw data as a byte array in the RawData property. It also includes a SampleCount property which you can use to accurately measure the duration of each MP3 Frame.

Of answered 23/5, 2011 at 12:27 Comment(3)
Thanks for the comment, I will try out on this.. I will come back to update my findings later. Thanks!Rheumatism
how many milliseconds does every mp3Frame has?? is there any formula or something I can use to get the length of every mp3frame in milliseconds?Clothesline
@ermac2014 use the sample rate. If you know samples per second and you know number of samples, then divide number of samples by sample rate to get duration.Of
B
6

The previous answers helped me get started. NAudio is the way to go.

For my PodcastTool I needed to to split podcasts at 2 minute intervals to make seeking to a specific place faster.

Here's the code to split an mp3 every N seconds:

    var mp3Path = @"C:\Users\ronnie\Desktop\mp3\dotnetrocks_0717_alan_dahl_imagethink.mp3";
    int splitLength = 120; // seconds

    var mp3Dir = Path.GetDirectoryName(mp3Path);
    var mp3File = Path.GetFileName(mp3Path);
    var splitDir = Path.Combine(mp3Dir,Path.GetFileNameWithoutExtension(mp3Path));
    Directory.CreateDirectory(splitDir);

    int splitI = 0;
    int secsOffset = 0;

    using (var reader = new Mp3FileReader(mp3Path))
    {   
        FileStream writer = null;       
        Action createWriter = new Action(() => {
            writer = File.Create(Path.Combine(splitDir,Path.ChangeExtension(mp3File,(++splitI).ToString("D4") + ".mp3")));
        });

        Mp3Frame frame;
        while ((frame = reader.ReadNextFrame()) != null)
        {           
            if (writer == null) createWriter();

            if ((int)reader.CurrentTime.TotalSeconds - secsOffset >= splitLength)
            {   
                // time for a new file
                writer.Dispose();
                createWriter();
                secsOffset = (int)reader.CurrentTime.TotalSeconds;              
            }

            writer.Write(frame.RawData, 0, frame.RawData.Length);
        }

        if(writer != null) writer.Dispose();
    }
Belie answered 23/11, 2011 at 2:13 Comment(3)
It shouldn't be very difficult to modify my sample to achieve that. Have you tried it? I could take a crack at it sometime, just not this moment. What is the unit of measurement for start and stop trim points?Belie
I've been trying still haven't got it yet. My first time with NAudio. The measurements would be a timespan. Start and stop. so basically a trim start and trim end.Columbary
I tried it but CurrentTime is always zero, does anybody know why?Fishnet
P
2

these would be helpful Alvas Audio (commercial) and ffmpeg

Padgett answered 23/5, 2011 at 8:0 Comment(1)
Thanks for the comment, I will first give NAudio a try. :)Rheumatism
S
0

If you want to split podcasts, copy the tracks to an audio device (swimming headers in my case) and include a little audio header made from the Text To Speech service from Google to identify the tracks. (e.g. "History of the world in a hundred objects. Episode 15. Track 1 of 4") you could check a little bash script https://github.com/pulijon/cpodcast/blob/main/cutpodcast.bash

It is prepared to add the audio header in Spanish. For other languages you should change the option -l and the string of header

gtts-cli "Corte $((10#$ntrack)) de $((10#$numtracks)). $5 " -l es --output pre_$track
Sadi answered 10/11, 2022 at 4:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.