Lingo.Voice (Lingo v0.4.2)

Copy Markdown View Source

Voice: joining channels, playing audio and receiving it.

Audio is Opus all the way through. Lingo has no native dependencies, so it can't encode or decode raw PCM itself; play Ogg, WebM or Matroska Opus files with play_file/2, anything ffmpeg understands with play_url/3, or any enumerable of Opus packets with play/2. Received audio arrives as Opus packets per user.

End-to-end encryption (DAVE) is handled transparently: Discord requires it, and media is never sent unencrypted while it is on.

{:ok, _connection} = Lingo.Voice.join(guild_id, channel_id)
Lingo.Voice.play_file(guild_id, "hello.opus")

Lingo.Voice.listen(guild_id)

receive do
  {:lingo_voice, ^guild_id, {:audio, user_id, %{opus: opus}}} -> ...
end

Summary

Functions

Joins a voice channel and waits until audio can flow.

Sends voice events for the guild to the calling process, including every Opus packet received. See Lingo.Voice.Connection for the messages.

Plays an enumerable of Opus packets, replacing whatever is playing.

Plays an Opus file without transcoding: Ogg (.opus, .ogg) or WebM and Matroska (.webm, .mkv), told apart by their contents.

Plays anything ffmpeg can read, transcoding it on the fly. Needs ffmpeg installed.

Functions

connection(guild_id)

@spec connection(String.t() | integer()) :: pid() | nil

join(guild_id, channel_id, opts \\ [])

@spec join(String.t() | integer(), String.t() | integer(), keyword()) ::
  {:ok, pid()} | {:error, term()}

Joins a voice channel and waits until audio can flow.

Options: :self_mute, :self_deaf and :timeout (ms, default 20000).

leave(guild_id)

@spec leave(String.t() | integer()) :: :ok

listen(guild_id)

@spec listen(String.t() | integer()) :: :ok | {:error, :not_connected}

Sends voice events for the guild to the calling process, including every Opus packet received. See Lingo.Voice.Connection for the messages.

play(guild_id, packets)

@spec play(String.t() | integer(), Enumerable.t()) :: :ok | {:error, :not_connected}

Plays an enumerable of Opus packets, replacing whatever is playing.

play_file(guild_id, path)

@spec play_file(String.t() | integer(), Path.t()) ::
  :ok | {:error, :not_connected | :unsupported_format | File.posix()}

Plays an Opus file without transcoding: Ogg (.opus, .ogg) or WebM and Matroska (.webm, .mkv), told apart by their contents.

play_url(guild_id, input, opts \\ [])

@spec play_url(String.t() | integer(), String.t(), keyword()) ::
  :ok | {:error, :not_connected}

Plays anything ffmpeg can read, transcoding it on the fly. Needs ffmpeg installed.

stop(guild_id)

@spec stop(String.t() | integer()) :: :ok | {:error, :not_connected}