Author Topic: FFMPEG in EncoderCMDLN not playing nice (but actually playing noise)  (Read 321 times)

GTHvidsten

  • Posts: 23
I've found some other posts relating to BASS and FFMPEG, like this, this and this. With the help of these I feel I'm on the edge of getting the EncoderCMDLN to work with FFMPEG, but SomethingTM is missing.

So I've set up the EncoderCMDLN like this, where "mixer" is a mixer that is currently playing music (I checked by using -1 in Initialize() and I can hear music out of my speakers). BASS is Initialized with frequency=44100, and the mixer is set up with frequency=44100 and noOfChannels=2

Code: [Select]
EncoderCMDLN encoder = new EncoderCMDLN(mixer);
encoder.EncoderDirectory = "C:\\Path\\To\\FFMPEG;
encoder.CMDLN_Executable = "ffmpeg.exe";
encoder.CMDLN_CBRString = "-f s16le -ar 44100 -ac 2 -i ${input} -c:a mp3 -b:a ${kbps}k -vn -f mp3 ${output}";
encoder.CMDLN_EncoderType = BASSChannelType.BASS_CTYPE_STREAM_MP3;
encoder.CMDLN_DefaultOutputExtension = ".mp3";
encoder.CMDLN_Bitrate = 320;
encoder.CMDLN_SupportsSTDOUT = true;
encoder.CMDLN_ParamSTDIN = "-";
encoder.CMDLN_ParamSTDOUT = "-";

Just below this I'm starting the encoder:

Code: [Select]
if (!encoder.Start(null, IntPtr.Zero, false))
{
    _log.LogError("Failed to start encoder");
}

This gives no errors, so one would assume the encoder is working properly.

if I check the "encoder.EncoderCommandLine" property, and try to run the command in a command prompt, it also starts just fine with no errors.
This is the actual value of "EncoderCommandLine":
Code: [Select]
"C:\Path\To\FFMPEG\ffmpeg.exe" -f s16le -ar 44100 -ac 2 -i - -c:a mp3 -b:a 320k -vn -f mp3 -

I then attach the encoder to an Icecast broadcaster:

Code: [Select]
ICEcast icecast = new ICEcast(encoder, true)
{
    ServerAddress = "localhost",
    ServerPort = 8008,
    AdminPassword = "adminuser",
    AdminUsername = "adminpassword",
    PublicFlag = false,
    MountPoint = "/stream",
    Password = "MyPassword",
    StreamGenre = "Some Genre",
    StreamName = Some Name",
    StreamDescription = "Some Description"
};

BroadCast broadCast = new BroadCast(icecast)
{
    AutoReconnect = true,
    ReconnectTimeout = 5
};

broadCast.Notification += BroadCastOnNotification;

if (!_broadCast.AutoConnect())
{
    _log.LogError("Could not autoconnect to broadcast server: {0} ({1})", icecast.LastError, icecast.LastErrorMessage);
}

Now, when this code is run, it always fails on the AutoConnect call, where .LastError = "Error_EncoderError" and .LastErrorMessage="Some mystery problem occurred when trying to start the encoder!".
The BroadCastOnNotificationEvent then fires with "EncoderStartError, "EncoderStopped" and "Disconnected". After a few seconds it tries to autoreconnect and I can see "ReconnectTry", "EncoderStarted", "Reconnected". So the encoder works after all even if it can apparently start it, but couldn't _really_ start it, but can start it again on a reconnect. I don't undestand why it is happening like this.

I can now see in the Icecast admin interface that bytes are being sent, so everything seems good on paper... however, if I actually connect to the stream I'm getting only (almost white) noise, so something is obviously wrong with the format somewhere, but I just can't figure out what.
Based on the other posts I linked it seems that using "s16le" (PCM Signed 16 bit, Little Endian) is the way to go, but I'm already using this and I only get noise. I tried changing to Big Endian, but that didn't help. I tried to specify to FFMPEG that the data from STDIN is "Waveform Audio" (wav) but then the encoder gets stuck in an AutoConnect loop:
Code: [Select]
EncoderStopped
Disconnected
ReconnectTry
EncoderStarted
Reconnected
ConnectionLost
EncoderStopped
Disconnected
...

So how can I get FFMPEG to work properly with EncoderCMDLN. What is the correct output format from a mixer. Preferrably without any errors when first starting it, and getting actual output from Icecast instead of noise.

Ian @ un4seen

  • Administrator
  • Posts: 24589
For MP3 encoding, using the BASSenc_MP3 add-on (based on LAME) instead of FFMPEG may be a better way to do it. If you would like to stick with FFMPEG, then to narrow down where the problem is, can you try sending the FFMPEG output to a file instead of Icecast? If the written file also contains the noise then we know it's unrelated to the Icecast stuff. Also make sure you're not setting the BASS_SAMPLE_FLOAT or BASS_SAMPLE_8BITS flag on the mixer, so that its format matches what you're telling FFMPEG to expect (s16le).

If the problem persists, you could also try using BASSenc directly via BASS_Encode_Start instead of via the EncoderCMDLN class, eg. call BASS_Encode_Start with the same command-line as you got from EncoderCommandLine.

GTHvidsten

  • Posts: 23
Removing BASS_SAMPLE_FLOAT from the mixer helped greatly. I probably saw it in an example somewhere, but probably didn't need it. Removing it makes the output from Icecast actual music now, not just noise. Thanks! :)

Now, for the second problem of the encoder starting, but not really starting, then restarting. Do you have any good information I can use to debug this, so that everything starts perfectly the first time?

As for FFMPEG vs. MP3 addon: FFMPEG has quite big format support and I intend to support more than just MP3 in the future... MP3 is just a good starting point ;)

GTHvidsten

  • Posts: 23
I think I figured it out. If I removed the following code, the errors disappeared:

Code: [Select]
if (!encoder.Start(null, IntPtr.Zero, false))
{
    _log.LogError("Failed to start encoder");
}

So I guess the encoder is started, then the Broadcast.AutoConnect() tries to start it again, and fails... then it shuts it down and restarts it, and this time it works because it was shut down before hand.
Now, when it tries to start it, it is not already started, so startup succeeds.

Ian @ un4seen

  • Administrator
  • Posts: 24589
I'm not very familiar with BASS.Net's BroadCast class, so I'm not sure but from the "AutoConnect" documentation, it does look like it will start the encoder automatically, meaning there's no need for you to also do it. Anyway, good that you've got it working now!