Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AudioOutStream hangs when being written to #1008

Closed
DouglasDwyer opened this issue Mar 28, 2018 · 14 comments
Closed

AudioOutStream hangs when being written to #1008

DouglasDwyer opened this issue Mar 28, 2018 · 14 comments

Comments

@DouglasDwyer
Copy link

DouglasDwyer commented Mar 28, 2018

I've been playing around with Discord.NET's audio functionalities, and I'm trying to play an MP3 file on an audio channel. The bot connects to the channel successfully, however, no sound occurs. After further investigation (and a couple hours of headache) it seems that writing to the AudioOutStream hangs when a certain amount has been written to it. Here's some code:

    public async Task SendAsync(string path)
    {
        using (var ffmpeg = CreateStream(path))
        using (var stream = audioClient.CreatePCMStream(AudioApplication.Music))
        {
            try { CopyStream(ffmpeg.StandardOutput.BaseStream, stream); } // <- This hangs on the output.Write() call
            try { await ffmpeg.StandardOutput.BaseStream.CopyToAsync(stream); } // <- This line just hangs
            finally { await stream.FlushAsync(); }
        }
    }

    public static void CopyStream(Stream input, Stream output)
    {
        byte[] buffer = new byte[32768];
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            output.Write(buffer, 0, read);
        }
    }

The problem is, according to the debugger when using the CopyStream method, seems to be that output.Write() simply hangs and doesn't return. CopyToAsync() doesn't work either, probably for the same underlying reasons. I can stream data from the ffmpeg process just fine, it's simply that writing it doesn't work and no sound comes through to the Discord channel. I have no idea how to solve this.

@DouglasDwyer DouglasDwyer changed the title AudioOutStream hangs on when being written to AudioOutStream hangs when being written to Mar 28, 2018
@LDSpits
Copy link

LDSpits commented Mar 28, 2018

I have been using ffmpeg for my conversion too. It has to do with having to both read and write iirc. Basically when you copy to ffmpeg it immediately tries to write to stdout (which has been redirected by your process I'm assuming). However this is blocked since a copy operation to stdin of ffmpeg is occurring. The solution I found is to CopyAsync to both streams in parralel with Task.WhenAny

@DouglasDwyer
Copy link
Author

@LDSpits It's odd because even when I write other data (not from ffmpeg) it still seems to hang. Also, it hangs on writing to the Discord stream (which seems independent of ffmpeg's process). Also, can you provide me with some code? I'm not sure what you mean by copying async with both streams.

@ComputerMaster1st
Copy link
Contributor

ComputerMaster1st commented Mar 29, 2018

Hi There,

Can we see how you've rigged up your ffmpeg process please?

Also, if you're planning on using a buffer for read/write operations, you're buffer count is way too high.

Should be ... new Byte[((48000 * 20) / 1000) * 2];

48000 = Sample Frequency. Should be the same on your FFMPEG options.
20 = OpusFrameSize. Must be 20 afaik.
1000 = remove all the zeroes basically.
2 = Stereo aka 2 channels. FFMPEG should have audio channels set to 2 aswell.

FFMPEG should be encoding to PCM (s16le) too.

@DouglasDwyer
Copy link
Author

Here's the code for CreateStream() which generates the ffmpeg process:

private Process CreateStream(string path)
    {
        return Process.Start(new ProcessStartInfo
        {
            FileName = "ffmpeg.exe",
            Arguments = $"-hide_banner -loglevel panic -i \"{path}\" -ac 2 -f s16le -ar 48000 pipe:1",
            UseShellExecute = false,
            RedirectStandardOutput = true
        });
    }

Also, thanks for the information about the buffer size, though I was using that simply to try and figure out what was causing the issue.
I'd highly doubt that ffmpeg is the problem, because it's writing to the PCM stream which causes it to hang, but perhaps it's something to do with the data written?
Changing the buffer size doesn't do anything, unfortunately. It still hangs.

@ComputerMaster1st
Copy link
Contributor

Hi There,

That CopyToAsync() should be awaited. Also, I'm not sure if having quotes wrapping the file path is bad or not since I never wrapped in quotes before.

Other than that, I'm starting to run out of possible ideas. :(

@DouglasDwyer
Copy link
Author

@ComputerMaster1st Awaiting the CopyToAsync() changes nothing, though it indeed should be awaited. De-quoting the file path causes the Task to continue, and not hang, but it completes the Task immediately no matter the MP3 length, and no audio is played in Discord, so I'd assume that underneath there's a FileNotFound error. I really have no idea what's going wrong here. Is it my project setup, or has something in this API gone bad?

@ComputerMaster1st
Copy link
Contributor

ComputerMaster1st commented Mar 30, 2018

Check the file path. If the mp3 is in your project's root directory (same directory where your code is for dotnet core), then just use file.mp3 as the filepath.

@DouglasDwyer
Copy link
Author

@ComputerMaster1st Putting the file in the root directory as well as eliminating spaces from the file path does nothing no matter the quotations or not.

@ComputerMaster1st
Copy link
Contributor

Ok, I have one more possible solution...

Do you have libsodium.dll & opus.dll downloaded & placed within your project's root directory?

@Joe4evr
Copy link
Contributor

Joe4evr commented Mar 31, 2018

Better yet, are they set to copy on build?

@DouglasDwyer
Copy link
Author

DouglasDwyer commented Mar 31, 2018

Though I didn't have libsodium.dll in my output folder, adding it did not help anything. The music-playing thread still hangs. Now I have both opus.dll and libsodium.dll:
untitled
Perhaps the source which I obtained the libraries from is old or outdated. Could someone provide me with a link to the most updated DLLs?

@Joe4evr
Copy link
Contributor

Joe4evr commented Mar 31, 2018

Native builds (be sure to rename libopus to opus). Also, just to make sure, follow this flowchart to get the right version:

@DouglasDwyer
Copy link
Author

Hmm... redownloading the libraries actually did help. I am now able to play a short (5 second long) MP3 file over Discord. However, when I attempt to play larger files, nothing is outputted to the Discord channel, seemingly bringing me back to the previous situation. I'm going to try and play some other audio files. Perhaps ffmpeg doesn't like these..?

@DouglasDwyer
Copy link
Author

Wonderful! This issue seems to be resolved by getting the correct audio libraries. If it's possible, though, I would appreciate if the documentation was updated with that flow chart and link because I wan't sure where to get the libraries. Sometimes there's still silence, but re-opening the program solves that, so it's probably an unrelated issue. Thanks for the help, everyone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants