Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FFmpeg.AutoGen example of how to split audio file

Tags:

c

c#

audio

I want to use the FFmpeg.AutoGen project from here: https://github.com/Ruslan-B/FFmpeg.AutoGen

I'm not familiar with the ffmpeg API, so I wanted to get an example of how to split an audio file into little files, for example the audio file is about 2 hours long (can be mp3,ogg,wav,etc.) and I want to split it into several little files of x minutes. The splitting should be done on the main audio file with timestamps from and to, for example from = 00:25:00 (meaning 25 minutes), to = 00:31:12 (meaning 31 minutes, 12 seconds) and the output should be the section from the main audio file, the result is 00:06:12 (meaning 6 minutes, 12 seconds) long.

How can this task be achieved with the project? Also a C example can help me, I would try to convert it into the framework.

Thanks for your responses.

like image 868
Sven Avatar asked Oct 17 '25 23:10

Sven


1 Answers

FFmpeg.AutoGen

What I think you need to do:

  1. Decode audio file
  2. Extract audio samples from the desired start timestamp until desired end timestamp
  3. Encode the extracted samples
  4. Write new audio file

Here are some sources in C which might help you to put it all together:

  • Read any audio file type: Libavcodec tutorial: decode virtually any audio file in C/C++. Note: avcodec_decode_audio4 is already deprecated (see New AVCodec API) You should use avcodec_send_packet / avcodec_receive_frame.
  • Encode / decode audio: FFmpeg examples - especially decode_audio.c / encode_audio.c

I think that the effort to use FFmpeg.AutoGen is too high for your use-case and therefore I propose 2 alternatives: Use NAudio or FFmpeg via command line

NAudio

This code reads an MP3, extracts a defined segment and writes it to a WAV file. It is based on the blog post Concatenating Segments of an Audio File with NAudio and can be tweaked quite easily.

using NAudio.Wave;
using System;

namespace NAudioSegments
{
    class SegmentProvider : IWaveProvider
    {
        private readonly WaveStream sourceStream;
        private int segmentStart, segmentDuration;

        public SegmentProvider(WaveStream sourceStream)
        {
            this.sourceStream = sourceStream;
        }

        public WaveFormat WaveFormat => sourceStream.WaveFormat;

        public void DefineSegment(TimeSpan start, TimeSpan duration)
        {
            if (start + duration > sourceStream.TotalTime)
                throw new ArgumentOutOfRangeException("Segment goes beyond end of input");
            segmentStart = TimeSpanToOffset(start);
            segmentDuration = TimeSpanToOffset(duration);
            sourceStream.Position = segmentStart;
        }

        public int TimeSpanToOffset(TimeSpan ts)
        {
            var bytes = (int)(WaveFormat.AverageBytesPerSecond * ts.TotalSeconds);
            bytes -= (bytes % WaveFormat.BlockAlign);
            return bytes;
        }

        public int Read(byte[] buffer, int offset, int count)
        {
            int totalBytesRead = 0;
            int bytesRead = 0;
            do
            {
                bytesRead = ReadFromSegment(buffer, offset + totalBytesRead, count - totalBytesRead);
                totalBytesRead += bytesRead;
            } while (totalBytesRead < count && bytesRead != 0);
            return totalBytesRead;
        }

        private int ReadFromSegment(byte[] buffer, int offset, int count)
        {
            var bytesAvailable = (int)(segmentStart + segmentDuration - sourceStream.Position);
            var bytesRequired = Math.Min(bytesAvailable, count);
            return sourceStream.Read(buffer, offset, bytesRequired);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var source = new Mp3FileReader(@"<input-path>"))
            {
                var segmentProvider = new SegmentProvider(source);
                // Add desired splitting e.g. start at 2 seconds, duration 1 second
                segmentProvider.DefineSegment(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(1));
                WaveFileWriter.CreateWaveFile(@"<output-path>", segmentProvider);
            }
        }
    }
}

FFmpeg via command line

You could invoke ffmpeg directly from your C# code via the System.Diagnostics.Process class (see e.g. this SO question) instead of using FFmpeg.AutoGen.

You could then use the following command line for automatically splitting the audio file in segemnts of the same length beginning at 00:00:00

ffmpeg -i in.m4a -f segment -segment_time 300 -c copy out%03d.m4a

or you can change the start time with the parameter -ss (replace <start-time> with the number of seconds). You would need to repeat this for every segment.

ffmpeg -ss <start-time> -i in.m4a -c copy -t 300 out.m4a

Source on superuser

like image 102
Marius Avatar answered Oct 20 '25 14:10

Marius