Split Mp3 File to Time Sec Each Using Sox

Split mp3 file to TIME sec each using SoX

You can run SoX like this:

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

It will create a series of files with a 15-second chunk of the audio each. (Obviously, you may specify a value other than 15.) There is no need to know the total length.

Note that SoX, unlike mp3splt, will decode and reencode the audio (see generation loss). You should make sure to use at least SoX 14.4.0 because previous versions had a bug where audio got lost between chunks.

Trim audio files with Sox in milliseconds

If you want to trim with millisecond precision, specify it:

sox in.mp3 out.mp3 trim 2 0.195

Saves 195 milliseconds with an offset of 2 seconds of in.mp3 to out.mp3.

If you only want the first two seconds of the file use trim like this:

sox in.mp3 out.mp3 trim 0 2

If you want to skip the first two seconds of the file use trim like this:

sox in.mp3 out.mp3 trim 2

If you want to trim 195 milliseconds from the end of the file, use gerald's answer.

Excerpt from the manual:

trim start [length|=end]
The optional length parameter gives the length of audio to output after the
start sample and is thus used to trim off the end of the audio.
Alternatively, an absolute end location can be given by preceding it with
an equals sign. Using a value of 0 for the start parameter will allow trimming
off the end only.

How do you trim the audio file's end using SoX?

The syntax is sox input output trim <start> <duration>

e.g. sox input.wav output.wav trim 0 00:35 will output the first 35 seconds into output.wav.

(you can know what the length is using sox input -n stat)

From the SoX documentation on the trim command:

Cuts portions out of the audio. Any number of positions may be given; audio is not sent to the output until the first position is reached. The effect then alternates between copying and discarding audio at each position. Using a value of 0 for the first position parameter allows copying from the beginning of the audio.

For example,

sox infile outfile trim 0 10

will copy the first ten seconds, while

play infile trim 12:34 =15:00 -2:00

and

play infile trim 12:34 2:26 -2:00

will both play from 12 minutes 34 seconds into the audio up to 15 minutes into the audio (i.e. 2 minutes and 26 seconds long), then resume playing two minutes before the end of audio.

Per dpwe's comment, the position values are interpreted as being relative to the previous position, unless they start with = (in which case they are relative to the start of the file) or - (in which case they are relative to the end of the file).

So, trimming five seconds off the end would be sox input output trim 0 -5

How do I reduce the play time of a voice mp3 file with sox to 75%?

Try this (with input.wav as your input file)

sox input.wav output.wav speed 1.33

Taken from this, its example 13.

Regarding pitch correction, if the pitch should stay the same, use this command instead.

sox input.wav output.wav tempo 1.33

Regarding filesize. It depends on the audio format you want to use. If it is compressed, select settings for higher compression. If not, you may want to convert it to mono, reduce the sample rate or bits.

Split audio file into pieces

EDIT

With SOX:

string sox = @"C:\Program Files (x86)\sox-14-4-1\sox.exe";
string inputFile = @"D:\Brothers Vibe - Rainforest.mp3";
string outputDirectory = @"D:\splittest";
string outputPrefix = "split";

int[] segments = { 10, 15, 30 };

IEnumerable<string> enumerable = segments.Select(s => "trim 0 " + s.ToString(CultureInfo.InvariantCulture));
string @join = string.Join(" : newfile : ", enumerable);
string cmdline = string.Format("\"{0}\" \"{1}%1n.wav" + "\" {2}", inputFile,
Path.Combine(outputDirectory, outputPrefix), @join);

var processStartInfo = new ProcessStartInfo(sox, cmdline);
Process start = System.Diagnostics.Process.Start(processStartInfo);

If SOX complains about libmad (for MP3) : copy DLLs next to it, see here

Alternatively you can use FFMPEG in the same manner :

ffmpeg -ss 0 -t 30 -i "Brothers Vibe - Rainforest.mp3" "Brothers Vibe - Rainforest.wav"

(see the docs for all the details)


You can do that easily with BASS.NET :

For the code below you pass in :

  • input file name
  • desired duration for each segment
  • output directory
  • prefix to use for each segment file

The method will check whether the file is long enough for the specified segments, if yes then it will cut the file to WAVs with the same sample rate, channels, bit depth.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Un4seen.Bass;
using Un4seen.Bass.Misc;

namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
if (!Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero))
throw new InvalidOperationException("Couldn't initialize BASS");

string fileName = @"D:\Brothers Vibe - Rainforest.mp3";
var segments = new double[] {30, 15, 20};
string[] splitAudio = SplitAudio(fileName, segments, "output", @"D:\split");
}

private static string[] SplitAudio(string fileName, double[] segments, string prefix, string outputDirectory)
{
if (fileName == null) throw new ArgumentNullException("fileName");
if (segments == null) throw new ArgumentNullException("segments");
if (prefix == null) throw new ArgumentNullException("prefix");
if (outputDirectory == null) throw new ArgumentNullException("outputDirectory");
int i = Bass.BASS_StreamCreateFile(fileName, 0, 0,
BASSFlag.BASS_STREAM_PRESCAN | BASSFlag.BASS_STREAM_DECODE);
if (i == 0)
throw new InvalidOperationException("Couldn't create stream");

double sum = segments.Sum();

long length = Bass.BASS_ChannelGetLength(i);
double seconds = Bass.BASS_ChannelBytes2Seconds(i, length);
if (sum > seconds)
throw new ArgumentOutOfRangeException("segments", "Required segments exceed file duration");
BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(i);

if (!Directory.Exists(outputDirectory)) Directory.CreateDirectory(outputDirectory);

int index = 0;
var list = new List<string>();
foreach (double segment in segments)
{
double d = segment;
long seconds2Bytes = Bass.BASS_ChannelSeconds2Bytes(i, d);
var buffer = new byte[seconds2Bytes];
int getData = Bass.BASS_ChannelGetData(i, buffer, buffer.Length);
string name = string.Format("{0}_{1}.wav", prefix, index);
string combine = Path.Combine(outputDirectory, name);
int bitsPerSample = info.Is8bit ? 8 : info.Is32bit ? 32 : 16;
var waveWriter = new WaveWriter(combine, info.chans, info.freq, bitsPerSample, true);
waveWriter.WriteNoConvert(buffer, buffer.Length);
waveWriter.Close();
list.Add(combine);
index++;
}
bool free = Bass.BASS_StreamFree(i);

return list.ToArray();
}
}
}

TODO

The extraction is not optimized, if you are concerned with memory usage, then the function should be enhanced to grab parts of a segments and write them progressively to the WaveWriter.

Notes

BASS.NET has a nag screen, but you can request for a free registration serial at their website.

Note, install BASS.NET then make sure to copy bass.dll from the base package next to your EXE. Also, you can use pretty much any audio formats, see their website for formats plugins and how to load them (BASS_PluginLoad).

Splitting an Audio File Into Equal-Lenght Segments Using FFmpeg

You can use the segment muxer. Basic example:

ffmpeg -i input.wav -f segment -segment_time 2 output_%03d.wav
  • -f segment indicates that the segment muxer should be used for the output.
  • -segment_time 2 makes each segment 2 seconds long.
  • output_%03d.wav is the output file name pattern which will result iin output_000.wav, output_001.wav, output_002.wav, and so on.


Related Topics



Leave a reply



Submit