Class: Discordrb::Voice::Encoder

Inherits:
Object
  • Object
show all
Defined in:
lib/discordrb/voice/encoder.rb

Overview

This class conveniently abstracts opus and ffmpeg/avconv, for easy implementation of voice sending. It's not very useful for most users, but I guess it can be useful sometimes.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeEncoder

Create a new encoder



31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/discordrb/voice/encoder.rb', line 31

def initialize
  @sample_rate = 48_000
  @frame_size = 960
  @channels = 2
  @volume = 1.0

  if OPUS_AVAILABLE
    @opus = Opus::Encoder.new(@sample_rate, @frame_size, @channels)
  else
    fail LoadError, 'Opus unavailable - voice not supported! Please install opus for voice support to work.'
  end
end

Instance Attribute Details

#use_avconvtrue, false

Whether or not avconv should be used instead of ffmpeg. If possible, it is recommended to use ffmpeg instead, as it is better supported and has a wider range of possible volume settings (see #volume).

Returns:

  • (true, false)

    whether avconv should be used instead of ffmpeg.



28
29
30
# File 'lib/discordrb/voice/encoder.rb', line 28

def use_avconv
  @use_avconv
end

#volumeString, Number

The volume that should be used with future ffmpeg conversions. If ffmpeg is used, this can be specified as:

  • A number, where 1 is no change in volume, 0 is completely silent, 0.5 is half the default volume and 2 is twice the default.
  • A string representation of the above number.
  • A string representing a change in gain given in decibels, in the format -6dB or 6dB.

If avconv is used (see #use_avconv) then it can only be given as a number from 0 to 1, where 1 is no change and 0 is completely silent.

Returns:

  • (String, Number)

    the volume for future playbacks, 1.0 by default.



23
24
25
# File 'lib/discordrb/voice/encoder.rb', line 23

def volume
  @volume
end

Instance Method Details

#destroyObject

Destroys this encoder and the opus connection, preventing any future encodings.



52
53
54
# File 'lib/discordrb/voice/encoder.rb', line 52

def destroy
  @opus.destroy
end

#encode(buffer) ⇒ String

Encodes the given buffer using opus.

Parameters:

  • buffer (String)

    An unencoded PCM (s16le) buffer.

Returns:

  • (String)

    A buffer encoded using opus.



47
48
49
# File 'lib/discordrb/voice/encoder.rb', line 47

def encode(buffer)
  @opus.encode(buffer, 1920)
end

#encode_file(file) ⇒ IO

Encodes a given file (or rather, decodes it) using ffmpeg. This accepts pretty much any format, even videos with an audio track. For a list of supported formats, see https://ffmpeg.org/general.html#Audio-Codecs. It even accepts URLs, though encoding them is pretty slow - I recommend to make a stream of it and then use #encode_io instead.

Parameters:

  • file (String)

    The path or URL to encode.

Returns:

  • (IO)

    the audio, encoded as s16le PCM



61
62
63
64
# File 'lib/discordrb/voice/encoder.rb', line 61

def encode_file(file)
  command = "#{ffmpeg_command} -loglevel 0 -i \"#{file}\" -f s16le -ar 48000 -ac 2 #{ffmpeg_volume} pipe:1"
  IO.popen(command)
end

#encode_io(io) ⇒ IO

Encodes an arbitrary IO audio stream using ffmpeg. Accepts pretty much any media format, even videos with audio tracks. For a list of supported audio formats, see https://ffmpeg.org/general.html#Audio-Codecs.

Parameters:

  • io (IO)

    The stream to encode.

Returns:

  • (IO)

    the audio, encoded as s16le PCM



70
71
72
73
74
75
# File 'lib/discordrb/voice/encoder.rb', line 70

def encode_io(io)
  ret_io, writer = IO.pipe
  command = "#{ffmpeg_command} -loglevel 0 -i - -f s16le -ar 48000 -ac 2 #{ffmpeg_volume} pipe:1"
  spawn(command, in: io, out: writer)
  ret_io
end