I would like to be able to split my audio (mp3 or equiv.) or video file based upon multiple timestamps. The same way, for those who have used any editing software, you can crop the file based upon selecting a start time and end time.
What I have done so far:
[HttpPost]
public async Task<string> ProcessFullAudio([FromBody] ProcessFullAudioRequest processFullAudioRequest)
{
if (processFullAudioRequest == null || processFullAudioRequest.StartEndTimes == null || processFullAudioRequest.StartEndTimes.Length == 0)
{
throw new ArgumentException("Invalid request: StartEndTimes cannot be null or empty.");
}
var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
var fileName = $"{Guid.NewGuid()}_{timestamp}.mp3";
var outputFilePath = Path.Combine(customFolder, fileName);
int amntOfTimeStamps = processFullAudioRequest.StartEndTimes.Length;
int step = 0;
string lineOfCodeForFirstTime = " \"aselect='not(between(t,<START>,<END>)";
string lineOfCodeForRestOfTimes = "+between(t,<START>,<END>)";
string argument = "";
string result = null;
string filterComplex = GenerateAtrims(processFullAudioRequest.StartEndTimes);
while (step != amntOfTimeStamps)
{
step++;
if (step == 1)
{
result = ReplacePlaceholders(lineOfCodeForFirstTime, HhMmSsToSeconds(processFullAudioRequest.StartEndTimes[step - 1].Start).ToString() , HhMmSsToSeconds(processFullAudioRequest.StartEndTimes[step - 1].End).ToString());
argument += result;
}
else
{
result = ReplacePlaceholders(lineOfCodeForRestOfTimes, HhMmSsToSeconds(processFullAudioRequest.StartEndTimes[step - 1].Start).ToString() , HhMmSsToSeconds(processFullAudioRequest.StartEndTimes[step - 1].End).ToString());
argument += result;
}
}
var FFMPEG_PATH = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "ffmpeg.exe");
if (!System.IO.File.Exists(FFMPEG_PATH))
{
return "ffmpeg.exe IS NULL";
}
var arguments = $"-i {processFullAudioRequest.InputFilePath} -af {argument})' ,asetpts=N/SR/TB\" -acodec libmp3lame {outputFilePath}";
await ProcessAsyncHelper.ExecuteShellCommand(FFMPEG_PATH, arguments, Timeout.Infinite);
return outputFilePath;
}
The code, I hope, is self explanatory. The argument variable should like something like this:
-i C:\Users\User\Desktop\AudioEditorBackEnmd\AudioEditorAPI\wwwroot\mp3\TestAudio_123.mp3 -af "aselect='not(between(t,120,240))' ,asetpts=N/SR/TB" -acodec libmp3lame C:\Users\User\Desktop\AudioEditorBackEnmd\AudioEditorAPI\wwwroot\mp3\aa887f21-0a90-4ec5-80ba-2b265cb445b4_20250219_123804.mp3
After returning the output path for the newly processed edited audio, I pass it to my DownloadFile function:
[HttpGet]
public async Task<IActionResult> DownloadProcessedFile([FromQuery] string fileName)
{
if (string.IsNullOrWhiteSpace(fileName))
{
return BadRequest("File name is required.");
}
var filePath = Path.Combine(customFolder, fileName);
if (!System.IO.File.Exists(filePath))
{
return NotFound(new { fileName });
}
try
{
var fileBytes = await System.IO.File.ReadAllBytesAsync(filePath);
return File(fileBytes, "audio/mpeg", fileName);
}
catch (Exception ex)
{
throw;
}
}
Everything works, in the sense off, I am able to get an processed file which is shorter than the original audio. However the issue is that the timestamps are off. For example, in the argument that I provided above, I am cropping the audio from 120 to 240, which is from the 2 min mark till the 4 min mark. The audio which I am passing is 01:06:53 however the processed audio gives me back 1:05:22 which is not excepted as I should be getting 01:04:53.
The annoying thing is that I was getting the desired output at one point. Im not sure what changes caused the timestamps to become off. The only changes which I did was changing the file locations to my wwwroot folder.
I have tried many different variations of commands to get a desired output but can't seem to get anything close - I always get 1:05:22 back. From the commands that I tired was:
var arguments = $"-i {processFullAudioRequest.InputFilePath} -af {argument})' , asetpts=N/SR/TB\" -c:a libmp3lame -q:a 2 {outputFilePath}";
I tried so many more but I simply can't remember. And now I feel like I have reached a hard wall in coming up with a solution for this.
Any help I would much appreciate. I have tried to give as much detail as I can but if anything remains please let me know.