-
Notifications
You must be signed in to change notification settings - Fork 129
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
Implement playing audio through discord voice connections. #180
Conversation
docs/static/Intro.md
Outdated
@@ -1,7 +1,7 @@ | |||
# Intro | |||
Nostrum is a an Elixir library that can be used to interact with Discord. | |||
|
|||
Nostrum currently supports the latest stable version of Elixir, v. 1.7. | |||
Nostrum currently supports the latest stable version of Elixir, v. 1.9. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't latest stable 1.10?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just changed it to what mix.exs is set to
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going to change the wording as well as some other fixes, stay tuned, very spicy commits inbound
Just wanted to say thanks first and foremost! This looks like it took a lot of work. I'll have some time this weekend to go over the code and check it out! |
1337 lines added (nice). If you average one line a minute, it should only take a little over 22 hours. |
This is sick! I tested it out locally and things worked flawlessly. My only complaint would be with the errors related to ffmpeg or youtube-dl not being available. Right now if you don't have those configured properly you get what I believe is probably a porcelain error saying the command isn't available. ** (ArgumentError) argument error
:erlang.apply({:error, "Command not found: ffmpeg"}, :out, [])
** (MatchError) no match of right hand side value: {:error, "Command not found: youtube-dl"} I think we should probably improve these a bit, or even prevent them from happening in the first place. We can either be proactive or reactive and I'm not sure what's the best approach. ProactiveMy first idea is that we could check somewhere that the user has the two programs in their path, or at the path they specify in the config. However, I'm not sure where it would be best to do this. We could optionally have the user set an option in the config that specifies that they want to use voice and then just check that the programs exist on startup if they intend to use voice. Or we could also just do it every time the voice supervisor starts up. This might be problematic because I don't think we'd want to I can't think of a way to check before the function calls themselves that doesn't involve spinning up porcelain every time so this might be out of the picture. ReactiveAlternatively, and this is probably the better idea, we could just check for those errors and throw an exception. Things aren't going to continue anyways without those tools so blowing it up seems reasonable. This doesn't change much from how it acts now, but it tells the user explicitly what is wrong! |
…if configured and not found.
I've done some of both: I've added a suppressible warning message upon startup if the configured executable(s) weren't found in the system path, and running either No ffmpeg
ffmpeg without youtube-dl
Voice.play/3 without ffmpeg
If the |
…pdate events on start/stop.
End of input will be automatically detected for playing audio with pipe/ytdl. |
end | ||
|
||
def try_send_data(%VoiceState{} = voice, init?) do | ||
wait = if(init?, do: 20_000, else: 200) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this work? If someone plays a short song (under 20s) will we not send the event until after the 20s has elapsed? Or is this for some other functionality entirely? Not sure what stalling
means in this context!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stalling
occurs when the ffmpeg
process stays open waiting for data to be piped into stdin
. Calling Enum.take/2
on the process's output stream will hang indefinitely in this case. When playing from a url/file, ffmpeg
closes automatically and a "stall" never occurs. The 20 second init timer means that if we are just beginning to play a sound, allow up to 20 seconds for ffmpeg
, youtube-dl
, or whatever source you might use with :pipe
option, to download/buffer data from the source to start playing. Otherwise, if we're already playing audio (init? == false
) only wait 200 milliseconds until we consider ffmpeg to have stalled. This is how we detect our non-url source has terminated, as this isn't required when using :url
option. On stall, we simply close the ffmpeg
process, and this allows the Enum.take/2
call to continue, and the player process will exit normally. If playing a short audio sample, from youtube-dl
for example, after the first burst of frames, all subsequent watchdogs will have the 200 millisecond timer, so the event will be sent right as we detect the audio concludes.
Thanks! |
Implement voice 👍
closes #84