C
C#2y ago
Sh1be

❔ ffmpeg pipes

Hello, I've been trying to get ffmpeg to work in my c# project for a few hours now.
private async void ExtractAudio(Stream input, Stream output)
{
var process = new Process
{
StartInfo =
{
FileName = "ffmpeg",
Arguments = "-i pipe:0 -f mp3 -codec:a libmp3lame -",
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = false,
}
};

process.Start();

var stdin = process.StandardInput.BaseStream;
input.CopyToAsync(stdin);
process.StandardOutput.BaseStream.CopyToAsync(output);

process.WaitForExit();
}
private async void ExtractAudio(Stream input, Stream output)
{
var process = new Process
{
StartInfo =
{
FileName = "ffmpeg",
Arguments = "-i pipe:0 -f mp3 -codec:a libmp3lame -",
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = false,
}
};

process.Start();

var stdin = process.StandardInput.BaseStream;
input.CopyToAsync(stdin);
process.StandardOutput.BaseStream.CopyToAsync(output);

process.WaitForExit();
}
I tried multiple different variations but none seem to work. I basically have a file in-memory and want to pass it to ffmpeg to extract the audio and then give it back to me in-memory. Everytime it runs it seemingly just gets stuck up and doesn't continue at all. Why could that be?
51 Replies
Chiyoko_S
Chiyoko_S2y ago
you do not seem to be await ing the async calls the CopyToAsync calls I mean if you need it to run on a different thread then you should run it on a different thread. async/await does not necessarily mean it involves spawning a new thread though wouldn't it be easy if you just saved the data to a file in a temporary location and pass the path to it instead
Sh1be
Sh1beOP2y ago
yeah, because I read that apparently while im inputting the file through a buffer its outputting stuff already which leads it to somehow fill up the buffer and makes it stuck up like i just have it right now? I will create a new thread for both the reading and inputting calls and try it that would make it easy probably, but it bugs me that I can't get it to work through pipes which would be much more efficient
Chiyoko_S
Chiyoko_S2y ago
as long as it's good enough™️
Sh1be
Sh1beOP2y ago
new Thread(async _ =>
{
await input.CopyToAsync(stdin);
}).Start();

new Thread(async _ =>
{
await process.StandardOutput.BaseStream.CopyToAsync(output);
}).Start();
new Thread(async _ =>
{
await input.CopyToAsync(stdin);
}).Start();

new Thread(async _ =>
{
await process.StandardOutput.BaseStream.CopyToAsync(output);
}).Start();
okay this doesn't work either, guess I will try to save the data to a file and pass the path to it then
Chiyoko_S
Chiyoko_S2y ago
better ways to do it would be to use Task.Run probably. But I'm actually curious
Sh1be
Sh1beOP2y ago
task.run does the same thing afaik
Chiyoko_S
Chiyoko_S2y ago
how are you getting the console output if you're redirecting the stdout for receiving the file yeah but task run is prettier grinowo
Sh1be
Sh1beOP2y ago
I genuinely have no idea, I was confused at first as well it doesn't make sense at all this is kind of pissing me off
Chiyoko_S
Chiyoko_S2y ago
is the output from the ffmpeg actually going anywhere just genuinely curious. Usually when I used ffmpeg I'd specify some sort of output explicitly
Sh1be
Sh1beOP2y ago
if I remove the standardOutput copying and set the redirectStandardOutput to false, then I get this in my console which looks like the actual data
Sh1be
Sh1beOP2y ago
so it is being piped out
Chiyoko_S
Chiyoko_S2y ago
huh. ok
Sh1be
Sh1beOP2y ago
if you look at the arguments, there is a "-" at the end which tells ffmpeg to spit it out instead of making a file
Chiyoko_S
Chiyoko_S2y ago
oh ok. apparently it is since it is running in a separate thread might as well as get rid of Async from the copying threads? so it copies synchronously it looks like the stdin copy part works because it works when you disable stdout redirection
Sh1be
Sh1beOP2y ago
i can try that yeah it works, it only seems to have a problem piping my stuff back in
Chiyoko_S
Chiyoko_S2y ago
....or that would be my guess if it was me I'd just write to a file
Sh1be
Sh1beOP2y ago
.... aand it does the same thing (doesn't work)
Chiyoko_S
Chiyoko_S2y ago
sad
Sh1be
Sh1beOP2y ago
why do they have a piping feature if it doesn't work 😭 hopefully somebody more experienced comes around and passes on the knowledge else I have seriously wasted 4 hours of my life on practically nothing
Chiyoko_S
Chiyoko_S2y ago
aaaaaactually hm nevermind. gimme a min
Sh1be
Sh1beOP2y ago
sure, if you have some time maybe you could try something, I mean the MVP code is further up
Chiyoko_S
Chiyoko_S2y ago
what happens if you call a CopyTo on an empty stream I'm guessing it does nothing so if my theory is correct, process.StandardOutput.BaseStream.CopyToAsync(output); returns immediately because it has nothing to read and because nothing is being read from the buffer ffmpeg waits for the buffer to be emptied but there is noone to empty the buffer deadlock? or is it supposed to block until the end of stream is reached probably it is hmmmmmmmmmmmmmm oh also async void :(
Sh1be
Sh1beOP2y ago
so, any ideas on what to do now?
Chiyoko_S
Chiyoko_S2y ago
I'm actually trying to do it myself as well. kinda stuck here too
Sh1be
Sh1beOP2y ago
its kind of confusing, since it works perfectly fine if only 1 pipe is used and the other one is file based
Chiyoko_S
Chiyoko_S2y ago
so if you feed it a file it works? ok I think I figured it out I think you need to explicitly close the stdin
Sh1be
Sh1beOP2y ago
huh
Chiyoko_S
Chiyoko_S2y ago
dunno what's going on but I think that must be it
Sh1be
Sh1beOP2y ago
can i see your code? what did you change?
Chiyoko_S
Chiyoko_S2y ago
so if I do:
var stdin = process.StandardInput.BaseStream;
Task copyToStdin = Task.Run(() => { input.CopyTo(stdin); });
var stdin = process.StandardInput.BaseStream;
Task copyToStdin = Task.Run(() => { input.CopyTo(stdin); });
this is what we had before the copyto finishes and copyToStdin is complete but stdin is not closed yet so I guess it waits for extra data to be transmitted
Sh1be
Sh1beOP2y ago
did you try it with bigger files as well or only small ones?
Chiyoko_S
Chiyoko_S2y ago
but if we do
var stdin = process.StandardInput.BaseStream;
Task copyToStdin = Task.Run(() => { input.CopyTo(stdin); stdin.Close(); });
var stdin = process.StandardInput.BaseStream;
Task copyToStdin = Task.Run(() => { input.CopyTo(stdin); stdin.Close(); });
then it finishes once the close call is made yeah, I think ffmpeg just holds until the stdin is actually closed I tried it with some audio file
Sh1be
Sh1beOP2y ago
NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH
Chiyoko_S
Chiyoko_S2y ago
about 5 minutes long, expanded to a wav file that's about 50mb
Sh1be
Sh1beOP2y ago
you can't tell me that was the fucking issue
Chiyoko_S
Chiyoko_S2y ago
lol so is it working now what's funny is that I got it very close the first time, thinking it must be because I haven't closed the stream yet but I did input.Close() instead of stdin.Close() and was wondering "hmm why does it still get stuck"
Sh1be
Sh1beOP2y ago
I just tried it with some small file as well and a big but one but it's currently still encoding
Chiyoko_S
Chiyoko_S2y ago
full code?
Sh1be
Sh1beOP2y ago
private async void ExtractAudio(Stream input, Stream output)
{
var process = new Process
{
StartInfo =
{
FileName = "ffmpeg",
Arguments = "-i pipe:0 -f mp3 -codec:a libmp3lame -",
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = false,
}
};

process.Start();

var stdin = process.StandardInput.BaseStream;

new Thread(_ =>
{
input.CopyTo(stdin);
stdin.Close();
}).Start();

new Thread(_ =>
{
process.StandardOutput.BaseStream.CopyTo(output);
}).Start();
process.WaitForExit();
}
private async void ExtractAudio(Stream input, Stream output)
{
var process = new Process
{
StartInfo =
{
FileName = "ffmpeg",
Arguments = "-i pipe:0 -f mp3 -codec:a libmp3lame -",
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = false,
}
};

process.Start();

var stdin = process.StandardInput.BaseStream;

new Thread(_ =>
{
input.CopyTo(stdin);
stdin.Close();
}).Start();

new Thread(_ =>
{
process.StandardOutput.BaseStream.CopyTo(output);
}).Start();
process.WaitForExit();
}
this seems to work, thank you so much ❤️ I would have never figured out that it could still wait because of the pipe still being open 😭 I thought it would close the pipe once it's done transmitting what it already has so it could move on @not Aoba thank you so much again, I would have had to quit this project if I wouldn't have figured this out
Chiyoko_S
Chiyoko_S2y ago
async void ExtractAudio(Stream input, Stream output)
{
var process = new Process
{
StartInfo =
{
FileName = @"C:\a\local64\bin-video\ffmpeg.exe",
Arguments = "-i pipe:0 -f wav -",
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = false,
}
};

process.Start();

var stdin = process.StandardInput.BaseStream;

new Thread(_ =>
{
input.CopyTo(stdin);
stdin.Close();
}).Start();

new Thread(_ =>
{
process.StandardOutput.BaseStream.CopyTo(output);
}).Start();
process.WaitForExit();
}

ExtractAudio(File.OpenRead(@"music"), File.Create(@"C:\Users\gotos\Desktop\a.wav"));
async void ExtractAudio(Stream input, Stream output)
{
var process = new Process
{
StartInfo =
{
FileName = @"C:\a\local64\bin-video\ffmpeg.exe",
Arguments = "-i pipe:0 -f wav -",
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = false,
}
};

process.Start();

var stdin = process.StandardInput.BaseStream;

new Thread(_ =>
{
input.CopyTo(stdin);
stdin.Close();
}).Start();

new Thread(_ =>
{
process.StandardOutput.BaseStream.CopyTo(output);
}).Start();
process.WaitForExit();
}

ExtractAudio(File.OpenRead(@"music"), File.Create(@"C:\Users\gotos\Desktop\a.wav"));
oh so it is working good
Sh1be
Sh1beOP2y ago
the idolmaster hahah
Chiyoko_S
Chiyoko_S2y ago
grinowo
Sh1be
Sh1beOP2y ago
pretty good music
Chiyoko_S
Chiyoko_S2y ago
well. that took like 45 minutes to get it working good thing we got there eventually
Sh1be
Sh1beOP2y ago
yep I feel kind of stupid now
Chiyoko_S
Chiyoko_S2y ago
I mean I still feel stupid for trying to close the input instead of stdin too omegalul took like 90% I bet need sleep. it's 2:47am here
Sh1be
Sh1beOP2y ago
oh, sorry for keeping you up this long
Chiyoko_S
Chiyoko_S2y ago
anyway, good luck
Sh1be
Sh1beOP2y ago
you should really go to sleep, thanks again sleep well
Chiyoko_S
Chiyoko_S2y ago
nah I signed up for it
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server