Reputation: 1177
How can I send in a stream of bytes which is MP3 audio to FFMpeg and get the output to a stream of PCM bytes? I do not want to write the incoming stream to a file and let FFMpeg work on the file. I want the transcoding to happen in real-time.
I am aware that we can pipe in a stream of data to FFMpeg using the pipe command, how can I stream the data from my C# program.
Assuming I have an array of bytes.
Upvotes: 3
Views: 5074
Reputation: 1177
To solve this, I have spawned a new FFMpeg process. Then I used the pipe command and sent in the data via standard input, and got the output using the standard output. I then converted the output I received to a byte array. The new byte array is the transcoded data. You can write this byte buffer to a memory stream or a file stream, you can do what you like.
var startInfo = new ProcessStartInfo('path/to/ffmpeg');
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
var argumentBuilder = new List<string>();
argumentBuilder.Add("-loglevel panic"); // this makes sure only data is sent to stdout
argumentBuilder.Add("-i pipe:.mp3"); //this sets the input to stdin
// the target audio specs are as follows
argumentBuilder.Add($"-f wav");
argumentBuilder.Add("-ac 1");
argumentBuilder.Add($"-ar 44100");
argumentBuilder.Add("pipe:1"); // this sets the output to stdout
startInfo.Arguments = String.Join(" ", argumentBuilder.ToArray());
_ffMpegProcess = new Process();
_ffMpegProcess.StartInfo = startInfo;
_ffMpegProcess.Start();
We have to write the data to the FFMpeg input channel using Standard Input, we can do it like so:
_ffMpegProcess.StandardInput.BaseStream.Write(byteBuffer);
This will make FFMpeg return the results to the Standard Output, we will need to listen to it now, like so:
while (true)
{
var bytes = new byte[1024]
var result = await _ffMpegProcess.StandardOutput.BaseStream.ReadAsync(bytes);
if (result == 0)
{
// no data retrieved
}
else
{
// do something with the data
}
}
Upvotes: 7