DEV Community

Michael Lip
Michael Lip

Posted on • Originally published at zovo.one

Cutting Audio Files Without Re-encoding Preserves Quality

Every time you re-encode an MP3 it loses quality. Lossy compression applied twice produces worse results than lossy compression applied once. The solution is to cut at frame boundaries without decoding and re-encoding.

The MP3 frame structure

MP3 files are not continuous streams. They are sequences of independent frames, each containing a header and compressed audio data. Each frame represents a fixed duration of audio:

  • MPEG1 Layer 3: 1152 samples per frame
  • At 44.1 kHz: each frame = 26.12 milliseconds

This means you can cut an MP3 at frame boundaries without decoding. Cutting between frames preserves the compression of each frame perfectly. Cutting within a frame requires decoding the frame, truncating the samples, and re-encoding.

Lossless cutting

The term "lossless" in audio cutting means no quality degradation. For MP3, this is achieved by cutting only at frame boundaries.

Frame 1: 0-26ms
Frame 2: 26-52ms
Frame 3: 52-78ms
...
Enter fullscreen mode Exit fullscreen mode

If you want to cut at exactly 50ms, you have two choices:

  1. Cut at 26ms (frame boundary, lossless)
  2. Cut at 52ms (frame boundary, lossless)
  3. Cut at 50ms (requires decoding frame 2, re-encoding, quality loss)

For most use cases, cutting at the nearest frame boundary (within 26ms accuracy) is imperceptible. The human ear cannot distinguish a 26ms timing difference in a cut point.

Common use cases

Ringtone creation. Cut a 30-second clip from a song. The optimal approach: find the frame nearest to your desired start and end points, copy all frames between them.

Podcast editing. Remove dead air, ums, or mistakes. Frame-accurate cuts are more than sufficient for speech editing.

Sample creation. Extract a drum loop or vocal sample from a track. Here, precise start/end points matter more, and you may need sample-accurate (not frame-accurate) cuts, which require decode/re-encode.

The Web Audio approach

In a browser, cutting audio involves decoding the file, slicing the audio buffer, and encoding the result:

async function cutAudio(file, startSec, endSec) {
  const ctx = new AudioContext();
  const buffer = await file.arrayBuffer();
  const audioBuffer = await ctx.decodeAudioData(buffer);

  const startSample = Math.floor(startSec * audioBuffer.sampleRate);
  const endSample = Math.floor(endSec * audioBuffer.sampleRate);
  const length = endSample - startSample;

  const newBuffer = ctx.createBuffer(
    audioBuffer.numberOfChannels,
    length,
    audioBuffer.sampleRate
  );

  for (let ch = 0; ch < audioBuffer.numberOfChannels; ch++) {
    const oldData = audioBuffer.getChannelData(ch);
    const newData = newBuffer.getChannelData(ch);
    for (let i = 0; i < length; i++) {
      newData[i] = oldData[startSample + i];
    }
  }

  return newBuffer;
}
Enter fullscreen mode Exit fullscreen mode

For cutting MP3 files with visual waveform display and precise selection, I built a cutter at zovo.one/free-tools/mp3-cutter. It runs entirely in the browser, shows the waveform for visual cutting, and exports the result without uploading your audio to any server.


I'm Michael Lip. I build free developer tools at zovo.one. 500+ tools, all private, all free.

Top comments (0)