Reputation: 447
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.
Upvotes: 4
Views: 4219
Reputation: 1679
FFmpeg.AutoGen
What I think you need to do:
Here are some sources in C which might help you to put it all together:
avcodec_decode_audio4
is already deprecated (see New AVCodec API) You should use avcodec_send_packet
/ avcodec_receive_frame
.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
Upvotes: 8