I’ve been banging my head all the week trying to serve on my website an mp3 that is being converted.
It seemed really simple.
-
I first think: I will redirect the output of ffmpeg process to the web response, then realized that the output is corrupted whatever the encoding I choose: Windows version of ffmpeg stdout just outputs corrupted bytes, that’s weird for an important program like it, but that’s true. Probably an incompatibility with the fact that the Windows console doesn’t output in CP65001. Dunno.
-
I then tried to redirect the content of a file written by ffmpeg, but a lot of exceptions were raised, about the end of the stream being reached, or some file permission problem. I’ve read a lot of thread on SO about reading a file being written, but in several cases, people just choose to use another approach, less dirty.
-
I tried to use a program coded my NeoSmart, called UTFRedirect.exe, that has been created to allow outputing -REAL- UTF8 content to stdout. It was. But when it lauches the slave process, this program is using ‘WaitForSingleObject’ in C++, so it is not asynchronous. A synchronous method to output content is useless, since in that case, one would use a file and ‘ReadAllBytes’ from it.
-
I tried SoX. Same problem with the stdout encoding, and it handles URL very bad.
-
I tried: Streaming mp3 while it is being generated on the server. But that’s not similar to my problem, finally.
-
I tried to see if I had more chance if I created a file with a pipe-to-file with ffmpeg
ffmpeg -i input.mp3 -f mp3 - >output.mp3since it seemed I couldn’t really access the file created by ffmpeg withffmpeg -i input.mp3 -f mp3 output.mp3.
Is there someone that once faced the same problem?
[EDIT 09/29]
I decided to write my own redirect.exe program so I can redirect anything into it. I made it with two modes: either it writes the bytes into a FileShare.ReadWrite file, either it outputs HEX to the screen so that it is possible to convert it to bytes.
With this solution, I’m 95% sure I’ll be able to reach my goal, which is to use stdout of programs like ffmpeg or sox ‘on the fly’. I’ll probably come back with an answer. But I already know this solution is slow, since representing one hex = two bytes. Maybe I’ll use a another ‘base’ to represent my data, in other words, compress it, so it can be represented in ASCII or anything without null characters, but it takes less space.
For those interested, to read -REAL- bytes from the standard input, there’s this method:
using (Stream stdin = Console.OpenStandardInput())
using (Stream stdout = Console.OpenStandardOutput())
{
byte[] buffer = new byte[2048];
int bytes;
while ((bytes = stdin.Read(buffer, 0, buffer.Length)) > 0)
{
// Now you have a buffer of bytes in 'buffer'
}
}
[EDIT 09/30]
As I’m now able to get bytes, I’ll output the StandardOutput bytes as Ascii85. It should take 25% more space instead of 100%.
I made a C# console app that redirects a program’s stdout and outputs bytes as ascii85. So no more worries about Windows shell capacity to outputs bytes to a C# process.
I currently use it to redirect on the fly to a webresponse bytes from an MP3 converted in ffmpeg, and it works.
Ascii85 represents a 25% overhead versus bytes space, if you compare it to strings of hexs that represents a 100% overhead, and base64 that represents a 33% overhead on your datasize.
I used Jeff Atwood’s Ascii85 class found on his Coding Horror blog: http://www.codinghorror.com/blog/2005/10/c-implementation-of-ascii85.html