콘텐츠로 이동

bostie.voice

bostie.voice

DECODE_RATES module-attribute

DECODE_RATES = frozenset(_native.DECODE_RATES)

Format

Format = PCM | Opus

OpusApplication

OpusApplication = Literal['audio', 'voip', 'lowdelay']

OpusBandwidth

OpusBandwidth = Literal['auto', 'narrow', 'medium', 'wide', 'superwide', 'full']

OpusSignal

OpusSignal = Literal['auto', 'voice', 'music']

Overflow

Overflow = Literal['drop_oldest', 'drop_newest']

ReceiveFormat

ReceiveFormat = PCM | Opus | Packets

ReceiveStall

ReceiveStall = Literal['wait', 'end']

Sample

Sample = Literal['s16le', 'f32le']

SinkStall

SinkStall = Literal['hold', 'drop']

StageRole

StageRole = Literal['listen', 'request', 'speak']

Loop

Loop = Literal['track', 'queue'] | None

ClosedReason

Bases: StrEnum

Why a receiver ended: closed, disconnected, moved or began reconnecting.

CLOSED class-attribute instance-attribute

CLOSED = 'closed'

DISCONNECTED class-attribute instance-attribute

DISCONNECTED = 'disconnected'

MOVED class-attribute instance-attribute

MOVED = 'moved'

RECONNECTING class-attribute instance-attribute

RECONNECTING = 'reconnecting'

Direction

Bases: StrEnum

SEND class-attribute instance-attribute

SEND = 'send'

RECEIVE class-attribute instance-attribute

RECEIVE = 'receive'

DisconnectReason

Bases: StrEnum

REQUESTED class-attribute instance-attribute

REQUESTED = 'requested'

REMOVED class-attribute instance-attribute

REMOVED = 'removed'

CALL_TERMINATED class-attribute instance-attribute

CALL_TERMINATED = 'call_terminated'

RATE_LIMITED class-attribute instance-attribute

RATE_LIMITED = 'rate_limited'

TIMEOUT class-attribute instance-attribute

TIMEOUT = 'timeout'

SESSION_INVALID class-attribute instance-attribute

SESSION_INVALID = 'session_invalid'

AUTHENTICATION_FAILED class-attribute instance-attribute

AUTHENTICATION_FAILED = 'authentication_failed'

DAVE_REQUIRED class-attribute instance-attribute

DAVE_REQUIRED = 'dave_required'

DAVE_FAILED class-attribute instance-attribute

DAVE_FAILED = 'dave_failed'

PROTOCOL_ERROR class-attribute instance-attribute

PROTOCOL_ERROR = 'protocol_error'

CLOSED class-attribute instance-attribute

CLOSED = 'closed'

EndReason

Bases: StrEnum

How a track ended: it finished, was stopped, failed, or its connection ended.

FINISHED class-attribute instance-attribute

FINISHED = 'finished'

STOPPED class-attribute instance-attribute

STOPPED = 'stopped'

ERROR class-attribute instance-attribute

ERROR = 'error'

CLEANUP class-attribute instance-attribute

CLEANUP = 'cleanup'

SpeakingFlags

Bases: DiscordIntFlag

MICROPHONE class-attribute instance-attribute

MICROPHONE = 1 << 0

SOUNDSHARE class-attribute instance-attribute

SOUNDSHARE = 1 << 1

PRIORITY class-attribute instance-attribute

PRIORITY = 1 << 2

State

Bases: StrEnum

CONNECTING class-attribute instance-attribute

CONNECTING = 'connecting'

READY class-attribute instance-attribute

READY = 'ready'

RESUMING class-attribute instance-attribute

RESUMING = 'resuming'

RECONNECTING class-attribute instance-attribute

RECONNECTING = 'reconnecting'

DISCONNECTED class-attribute instance-attribute

DISCONNECTED = 'disconnected'

AlreadyConnected

Bases: VoiceError, StateError

bostie already runs a voice connection in this guild.

BufferFull

Bases: VoiceError

The sink has no room for this write.

DaveError

Bases: VoiceError

A DAVE end-to-end encryption step failed.

Empty

Bases: VoiceError

Nothing is queued in the receiver.

NotInVoice

Bases: VoiceError

The user is not in a voice channel of this guild.

ReceiverClosed

Bases: VoiceError

The receiver ended and has nothing left to read.

SinkClosed

Bases: VoiceError

The sink is closed.

SourceError

SourceError(source: str, detail: str)

Bases: VoiceError

A source failed to open, decode or seek.

source instance-attribute

source = source

detail instance-attribute

detail = detail

VoiceConnectError

VoiceConnectError(reason: DisconnectReason, code: int | None, detail: str)

Bases: VoiceError

A voice connection ended before it was ready.

reason instance-attribute

reason = reason

code instance-attribute

code = code

detail instance-attribute

detail = detail

VoiceError

Bases: BostieError

Base class of voice errors.

VoiceNotConnected

Bases: VoiceError

The voice connection has ended.

VoiceQueueFull

Bases: VoiceError

The voice connection has too many commands waiting.

ContextVoice

ContextVoice(manager: VoiceManager, guild_id: int | None, user_id: int)

Voice for the guild and the user of an interaction.

current property

current: VoiceConnection | None

The bot's connection in this guild, or None.

connect async

connect(*, self_deaf: bool | None = None, self_mute: bool | None = None, timeout: float | None = None, server_change_delay: float | None = None, encoder: EncoderSettings | None = None, speaking_flags: SpeakingFlags | None = None, stage: StageRole | None = None, speech_hangover: float | None = None, speech_activity: bool | None = None, stall_after: float | None = None) -> VoiceConnection

Connect to the voice channel of the user who ran the command.

Dave dataclass

Dave(protocol_version: int, epoch: int | None, privacy_code: str | None, _verification_code: Callable[[int], Awaitable[str]])

The call's end-to-end encryption, off when protocol_version is 0.

protocol_version instance-attribute

protocol_version: int

epoch instance-attribute

epoch: int | None

privacy_code instance-attribute

privacy_code: str | None

verification_code async

verification_code(user_id: int) -> str

The code to compare with user_id out of band to verify their identity.

ExternalVoice dataclass

ExternalVoice(state: VoiceStateUpdate, server: VoiceServerUpdate, _bot: Bot, _guild_id: int)

The session and server an external voice engine connects with.

bostie has no media in that guild; updates() hands on what changes later.

state instance-attribute

server instance-attribute

updates async

Queue the guild's new voice servers and the bot's own voice states.

disconnect async

disconnect() -> None

Leave the voice channel.

VoiceConnection

VoiceConnection(manager: VoiceManager, guild_id: int, channel: Channel, settings: Defaults)

The bot's voice connection in one guild.

guild_id instance-attribute

guild_id = guild_id

manager instance-attribute

manager = manager

channel_id property

channel_id: int

state property

state: State

self_mute property

self_mute: bool

The bot's own mute, as Discord applied it.

self_deaf property

self_deaf: bool

The bot's own deafen, as Discord applied it.

mute property

mute: bool

Whether the server muted the bot.

suppress property

suppress: bool

Whether the bot may not speak on this stage.

deaf property

deaf: bool

Whether a moderator deafened the bot (it then receives nothing).

members property

members: frozenset[int]

The other users in the call.

speaking property

speaking: Mapping[int, float]

Users talking now, mapped to the time.monotonic() they started.

ssrcs property

ssrcs: Mapping[int, int]

Each SSRC in the call mapped to its user id.

sinks property

sinks: tuple[Sink, ...]

The open sinks, oldest first: every track and queue plays through one.

latency property

latency: Latency

dave property

dave: Dave

encoder property writable

encoder: EncoderSettings

speaking_flags property writable

speaking_flags: SpeakingFlags

speech_hangover property writable

speech_hangover: float

Seconds without speech before a user counts as stopped.

stall_after property writable

stall_after: float

Seconds media may stop flowing before MediaStalled reports it.

speech_activity property writable

speech_activity: bool

Whether speech events fire; off, audio is only decrypted for receivers.

sink

sink(format: Format = _DEFAULT_PCM, *, volume: float = 1.0, after: Sink | None = None, crossfade: float = 0.0, filters: Filters = _NO_FILTERS, buffer: float | None = None, stall: SinkStall | None = None) -> Sink

Open a bounded writer whose audio is mixed into this connection.

With after, it stays silent until after closes, or plays out what was written before its last drain(). With crossfade too, it starts that many seconds before after ends and fades across, buffering that much more.

receive

receive(format: Packets, *, users: Iterable[int] | None = None, exclude: Iterable[int] = (), include_self: bool = False, markers: Literal[False] = False, buffer: float | None = None, overflow: Overflow | None = None, stall: ReceiveStall | None = None) -> Receiver[Packet]
receive(format: Packets, *, users: Iterable[int] | None = None, exclude: Iterable[int] = (), include_self: bool = False, markers: Literal[True], buffer: float | None = None, overflow: Overflow | None = None, stall: ReceiveStall | None = None) -> Receiver[Packet | SpeechStart | SpeechStop | UserLeave]
receive(format: Packets, *, users: Iterable[int] | None = None, exclude: Iterable[int] = (), include_self: bool = False, markers: bool, buffer: float | None = None, overflow: Overflow | None = None, stall: ReceiveStall | None = None) -> Receiver[Packet | SpeechStart | SpeechStop | UserLeave]
receive(format: PCM | Opus = _DEFAULT_PCM, *, users: Iterable[int] | None = None, exclude: Iterable[int] = (), include_self: bool = False, markers: Literal[False] = False, mix: bool = False, buffer: float | None = None, jitter: float | None = None, overflow: Overflow | None = None, stall: ReceiveStall | None = None) -> Receiver[Frame]
receive(format: PCM | Opus = _DEFAULT_PCM, *, users: Iterable[int] | None = None, exclude: Iterable[int] = (), include_self: bool = False, markers: Literal[True], mix: bool = False, buffer: float | None = None, jitter: float | None = None, overflow: Overflow | None = None, stall: ReceiveStall | None = None) -> Receiver[Frame | SpeechStart | SpeechStop | UserLeave]
receive(format: PCM | Opus = _DEFAULT_PCM, *, users: Iterable[int] | None = None, exclude: Iterable[int] = (), include_self: bool = False, markers: bool, mix: bool = False, buffer: float | None = None, jitter: float | None = None, overflow: Overflow | None = None, stall: ReceiveStall | None = None) -> Receiver[Frame | SpeechStart | SpeechStop | UserLeave]
receive(format: ReceiveFormat = _DEFAULT_PCM, *, users: Iterable[int] | None = None, exclude: Iterable[int] = (), include_self: bool = False, markers: bool = False, mix: bool = False, buffer: float | None = None, jitter: float | None = None, overflow: Overflow | None = None, stall: ReceiveStall | None = None) -> Receiver[Any]

Open a bounded iterator over the audio this connection receives.

play async

play(source: Source, *, volume: float = 1.0, filters: Filters = _NO_FILTERS, meta: Any = None, buffer: float | None = None, stall: SinkStall | None = None) -> Track

Play a source on its own sink, mixed with anything else playing.

stop

stop() -> None

Close every sink so that nothing plays; their tracks end with STOPPED.

move async

move(channel_id: int, *, timeout: float | None = None) -> None

Move to another voice or stage channel and wait until media flows there.

edit async

edit(*, self_mute: bool | None = None, self_deaf: bool | None = None, timeout: float | None = None) -> None

Change the bot's own mute or deafen, and return once Discord applied it.

stage async

stage(role: StageRole) -> None

Listen, ask to speak, or speak on this stage channel.

wait_until async

wait_until(state: State) -> None

Wait until the connection reaches state; VoiceNotConnected if it ends.

Bound the wait with asyncio.timeout().

reconnect

reconnect() -> None

Drop the voice WebSocket and resume on a new one.

disconnect async

disconnect() -> None

Leave the channel and return once the connection ended, within 2 s.

VoiceManager

VoiceManager(bot: Bot, defaults: Defaults, core: Callable[[], Core | None])

The bot's voice connections, at most one per guild.

defaults instance-attribute

defaults = defaults

connections property

connections: tuple[VoiceConnection, ...]

get

get(guild_id: int) -> VoiceConnection | None

connect async

connect(channel_id: int, *, self_deaf: bool | None = None, self_mute: bool | None = None, timeout: float | None = None, server_change_delay: float | None = None, encoder: EncoderSettings | None = None, speaking_flags: SpeakingFlags | None = None, stage: StageRole | None = None, speech_hangover: float | None = None, speech_activity: bool | None = None, stall_after: float | None = None) -> VoiceConnection

Connect to a voice or stage channel and return once media can flow.

Each setting given overrides voice.Defaults. In a guild where the bot is already connected, this moves it and applies only the settings given.

connect_external async

connect_external(guild_id: int, channel_id: int, *, self_deaf: bool | None = None, self_mute: bool | None = None, timeout: float | None = None) -> ExternalVoice

Join a voice channel for an external voice engine and return its credentials.

bostie then has no media in that guild; external.updates() hands on what changes later.

close async

close() -> None

Disconnect every connection, waiting up to 2 s for them to end.

OpusEncoder

OpusEncoder(format: PCM = _DEFAULT_PCM, *, encoder: EncoderSettings = _DEFAULT_ENCODER)

Encodes PCM into the 20 ms 48 kHz stereo packets an Opus() sink passes through.

bitrate=None means 64 kbps here, since there is no channel to follow.

encode

encode(data: Buffer) -> list[bytes]

The complete packets so far; the rest waits for the next call.

flush

flush() -> list[bytes]

Pad the remainder with silence and return the last packets.

DaveTransition

Bases: VoiceEvent

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

NAME class-attribute instance-attribute

NAME = 'voice.dave_transition'

protocol_version instance-attribute

protocol_version: int

epoch instance-attribute

epoch: int | None

transition_id instance-attribute

transition_id: int

MediaResumed

Bases: VoiceEvent

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

NAME class-attribute instance-attribute

NAME = 'voice.media_resumed'

direction instance-attribute

direction: Direction

duration instance-attribute

duration: float

MediaStalled

Bases: VoiceEvent

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

NAME class-attribute instance-attribute

NAME = 'voice.media_stalled'

direction instance-attribute

direction: Direction

duration instance-attribute

duration: float

Moved

Bases: VoiceEvent

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

NAME class-attribute instance-attribute

NAME = 'voice.moved'

old_channel_id instance-attribute

old_channel_id: int

new_channel_id instance-attribute

new_channel_id: int

by_us instance-attribute

by_us: bool

ReceptionReport

Bases: Struct

How one stream reaches whoever sent the report, as RFC 3550 measures it.

ssrc instance-attribute

ssrc: int

user_id instance-attribute

user_id: int | None

fraction_lost instance-attribute

fraction_lost: float

lost instance-attribute

lost: int

highest_sequence instance-attribute

highest_sequence: int

jitter instance-attribute

jitter: float

last_sender_report instance-attribute

last_sender_report: int

delay instance-attribute

delay: float

RtcpPacket

Bases: VoiceEvent

An RTCP packet from the voice server, decrypted, with its reports read.

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

NAME class-attribute instance-attribute

NAME = 'voice.rtcp_packet'

packet_type instance-attribute

packet_type: int

count instance-attribute

count: int

ssrc instance-attribute

ssrc: int

user_id instance-attribute

user_id: int | None

reports instance-attribute

reports: tuple[ReceptionReport, ...]

data instance-attribute

data: bytes

SpeakingUpdate

Bases: VoiceEvent

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

NAME class-attribute instance-attribute

NAME = 'voice.speaking_update'

user_id instance-attribute

user_id: int

ssrc instance-attribute

ssrc: int

flags instance-attribute

SpeechStart

Bases: VoiceEvent

A user started speaking.

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

NAME class-attribute instance-attribute

NAME = 'voice.speech_start'

user_id instance-attribute

user_id: int

ssrc instance-attribute

ssrc: int

at instance-attribute

at: float

offset class-attribute instance-attribute

offset: int | None = None

SpeechStop

Bases: VoiceEvent

A user stopped speaking.

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

NAME class-attribute instance-attribute

NAME = 'voice.speech_stop'

user_id instance-attribute

user_id: int

ssrc instance-attribute

ssrc: int

at instance-attribute

at: float

duration instance-attribute

duration: float

offset class-attribute instance-attribute

offset: int | None = None

StateChange

Bases: VoiceEvent

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

NAME class-attribute instance-attribute

NAME = 'voice.state_change'

old instance-attribute

old: State

new instance-attribute

new: State

reason instance-attribute

reason: DisconnectReason | None

code instance-attribute

code: int | None

detail instance-attribute

detail: str

UserJoin

Bases: VoiceEvent

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

NAME class-attribute instance-attribute

NAME = 'voice.user_join'

user_id instance-attribute

user_id: int

UserLeave

Bases: VoiceEvent

A user left the call; from a receiver, offset is the time on its clock.

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

NAME class-attribute instance-attribute

NAME = 'voice.user_leave'

user_id instance-attribute

user_id: int

offset class-attribute instance-attribute

offset: int | None = None

VoiceEvent

Bases: Struct

Base of the events a voice connection emits.

NAME class-attribute

NAME: str

INTENTS class-attribute

INTENTS: Intents = Intents(0)

guild_id instance-attribute

guild_id: int

PCM dataclass

PCM(rate: int = _SAMPLE_RATE, channels: Literal[1, 2] = 2, sample: Sample = 's16le')

Raw audio samples, interleaved, little endian.

rate class-attribute instance-attribute

rate: int = _SAMPLE_RATE

channels class-attribute instance-attribute

channels: Literal[1, 2] = 2

sample class-attribute instance-attribute

sample: Sample = 's16le'

Defaults dataclass

Defaults(*, self_deaf: bool = False, self_mute: bool = False, timeout: float = 10.0, server_change_delay: float = 0.0, encoder: EncoderSettings = EncoderSettings(), speaking_flags: SpeakingFlags = MICROPHONE, stage: StageRole = 'listen', sink_buffer: float = 0.2, stall: SinkStall = 'hold', speech_hangover: float = 0.2, speech_activity: bool = True, stall_after: float = 2.0, receive_buffer: float = 2.0, jitter: float = 0.1, overflow: Overflow = 'drop_oldest', receive_stall: ReceiveStall = 'wait', crossfade: float = 0.0, history: int = 0)

Voice settings every connection starts from.

self_deaf class-attribute instance-attribute

self_deaf: bool = False

self_mute class-attribute instance-attribute

self_mute: bool = False

timeout class-attribute instance-attribute

timeout: float = 10.0

server_change_delay class-attribute instance-attribute

server_change_delay: float = 0.0

encoder class-attribute instance-attribute

speaking_flags class-attribute instance-attribute

stage class-attribute instance-attribute

stage: StageRole = 'listen'

sink_buffer class-attribute instance-attribute

sink_buffer: float = 0.2

stall class-attribute instance-attribute

stall: SinkStall = 'hold'

speech_hangover class-attribute instance-attribute

speech_hangover: float = 0.2

speech_activity class-attribute instance-attribute

speech_activity: bool = True

stall_after class-attribute instance-attribute

stall_after: float = 2.0

receive_buffer class-attribute instance-attribute

receive_buffer: float = 2.0

jitter class-attribute instance-attribute

jitter: float = 0.1

overflow class-attribute instance-attribute

overflow: Overflow = 'drop_oldest'

receive_stall class-attribute instance-attribute

receive_stall: ReceiveStall = 'wait'

crossfade class-attribute instance-attribute

crossfade: float = 0.0

history class-attribute instance-attribute

history: int = 0

EncoderSettings dataclass

EncoderSettings(*, bitrate: int | None = None, application: OpusApplication = 'audio', fec: bool = True, packet_loss: float = 0.1, complexity: int = 10, bandwidth: OpusBandwidth = 'auto', signal_type: OpusSignal = 'auto')

Opus encoder settings; bitrate=None follows the channel.

bandwidth caps the audio band and signal_type tunes for voice or music; "auto" leaves both to libopus.

bitrate class-attribute instance-attribute

bitrate: int | None = None

application class-attribute instance-attribute

application: OpusApplication = 'audio'

fec class-attribute instance-attribute

fec: bool = True

packet_loss class-attribute instance-attribute

packet_loss: float = 0.1

complexity class-attribute instance-attribute

complexity: int = 10

bandwidth class-attribute instance-attribute

bandwidth: OpusBandwidth = 'auto'

signal_type class-attribute instance-attribute

signal_type: OpusSignal = 'auto'

Filters dataclass

Filters(*, equalizer: Mapping[float, float] = MappingProxyType({}), bass: float = 0.0, speed: float = 1.0, pitch: float = 1.0)

Effects applied in Rust as a sink plays; the defaults change nothing.

equalizer maps band centres in Hz to gains in dB, each an octave wide; bass is a gain in dB below 100 Hz; speed keeps the pitch and pitch the tempo.

equalizer class-attribute instance-attribute

equalizer: Mapping[float, float] = MappingProxyType({})

bass class-attribute instance-attribute

bass: float = 0.0

speed class-attribute instance-attribute

speed: float = 1.0

pitch class-attribute instance-attribute

pitch: float = 1.0

Latency dataclass

Latency(ws: float | None, udp: float | None)

Voice WebSocket and UDP round trips in seconds, None until measured.

ws instance-attribute

ws: float | None

udp instance-attribute

udp: float | None

Opus dataclass

Opus()

One Opus packet per write or item.

Packets dataclass

Packets()

Decrypted packets in arrival order, before the jitter buffer.

Frame

Bases: Struct

A piece of one user's audio, or of the mix, on the receiver's 48 kHz clock.

user_id instance-attribute

user_id: int | None

ssrc instance-attribute

ssrc: int | None

timestamp instance-attribute

timestamp: int | None

offset instance-attribute

offset: int

samples instance-attribute

samples: int

received_at instance-attribute

received_at: float

data instance-attribute

data: bytes

lost instance-attribute

lost: bool

level class-attribute instance-attribute

level: float | None = None

Packet

Bases: Struct

One decrypted Opus packet with its RTP fields and header extensions.

user_id instance-attribute

user_id: int

ssrc instance-attribute

ssrc: int

sequence instance-attribute

sequence: int

timestamp instance-attribute

timestamp: int

received_at instance-attribute

received_at: float

opus instance-attribute

opus: bytes

extensions instance-attribute

extensions: tuple[tuple[int, bytes], ...]

Queue

Queue(vc: VoiceConnection, *, volume: float = 1.0, filters: Filters = _NO_FILTERS, crossfade: float | None = None, history: int | None = None, buffer: float | None = None, stall: SinkStall | None = None)

Plays tracks back to back without gaps, or overlapping by crossfade seconds.

vc instance-attribute

vc = vc

crossfade instance-attribute

crossfade = _check_crossfade(defaults.crossfade if crossfade is None else crossfade)

closed property

closed: bool

Whether the connection ended; a closed queue takes no more tracks.

now property

now: Track | None

upcoming property

upcoming: tuple[Track, ...]

history property

history: tuple[Track, ...]

The tracks that played, oldest first, as many as history keeps.

paused property

paused: bool

Whether pause() holds the tracks back.

volume property writable

volume: float

filters property writable

filters: Filters

The effects on every track: equalizer, bass, speed and pitch.

loop property writable

loop: Loop

What plays again: the current "track", the whole "queue", or None.

add

add(source: Source, *, meta: Any = None, index: int | None = None) -> Track

Queue a source at the end, or at index among the upcoming tracks.

move

move(track: Track, index: int) -> None

Move an upcoming track to index among the upcoming tracks.

shuffle

shuffle() -> None

Put the upcoming tracks in a random order.

skip

skip() -> None

End the current track and go on with the next one.

back

back() -> Track | None

Play the last track of the history again, then the current one anew.

None when the history is empty; SourceError when that track cannot play again.

remove

remove(track: Track) -> None

clear

clear() -> None

End every upcoming track; the current one keeps playing.

pause

pause() -> None

resume

resume() -> None

stop

stop() -> None

End every track and close the sink; tracks added later play again.

join async

join() -> None

Wait until nothing is queued or playing.

Track

Track(queue: Queue, entry: _Entry, *, current: Callable[[_Entry], bool], seek: Callable[[_Entry, float], Awaitable[None]], stop: Callable[[_Entry], None])

A source playing, or waiting to play, on a voice connection.

source instance-attribute

source = entry.source

meta instance-attribute

meta = entry.meta

sink property

sink: Sink

The sink this track is written to; StateError until it starts.

ended property

ended: TrackEnd | None

position property

position: float

Seconds into the source that have played.

passthrough property

passthrough: bool

paused property

paused: bool

volume property writable

volume: float

filters property writable

filters: Filters

wait async

wait() -> TrackEnd

Wait for the end; cancelling one wait never cancels the track.

started async

started() -> bool

Wait until the track starts playing; False if it ended first.

pause

pause() -> None

Stop feeding the sink; the audio it already holds still plays.

resume

resume() -> None

seek async

seek(position: float) -> None

stop

stop() -> None

TrackEnd dataclass

TrackEnd(track: Track, reason: EndReason, error: BaseException | None, may_start_next: bool)

How a track ended; may_start_next says whether a player should go on.

track instance-attribute

track: Track

reason instance-attribute

reason: EndReason

error instance-attribute

error: BaseException | None

may_start_next instance-attribute

may_start_next: bool

Receiver

Receiver(connection: VoiceConnection, native: Receiver, handle: Handle, format: ReceiveFormat, *, on_close: Callable[[Receiver[Any]], None], users: frozenset[int] | None, exclude: frozenset[int], include_self: bool, buffer: float, jitter: float, markers: bool, mix: bool, overflow: Overflow, stall: ReceiveStall)

A bounded async iterator over received audio, one for each subscriber.

format instance-attribute

format: Final = format

users instance-attribute

users: Final = users

exclude instance-attribute

exclude: Final = exclude

include_self instance-attribute

include_self: Final = include_self

buffer instance-attribute

buffer: Final = buffer

jitter instance-attribute

jitter: Final = jitter

markers instance-attribute

markers: Final = markers

mix instance-attribute

mix: Final = mix

overflow instance-attribute

overflow: Final = overflow

stall instance-attribute

stall: Final = stall

queued property

queued: float

Seconds the oldest queued item has waited: this is the consumer's lag.

closed property

closed: bool

Whether the receiver ended and nothing is left to read.

closed_reason property

closed_reason: ClosedReason | None

None while open, else why it ended.

get_nowait

get_nowait() -> T

Return the next item, or raise voice.Empty.

clear

clear() -> None

Drop everything queued and continue live.

mark

mark() -> Awaitable[bool]

True once prior audio is queued or dropped, else False by 1.2s + 2*jitter.

close

close() -> None

Stop receiving and discard what is queued.

stats

stats() -> ReceiverStats

The latest counters, or the last ones read before the receiver ended.

ReceiverStats dataclass

ReceiverStats(delivered: int, dropped: int, lost: int)

What this receiver delivered, dropped and saw lost.

delivered instance-attribute

delivered: int

dropped instance-attribute

dropped: int

lost instance-attribute

lost: int

Recorder

Recorder(vc: VoiceConnection, path: str | PathLike[str], *, users: Iterable[int] | None = None, exclude: Iterable[int] = (), include_self: bool = False, align: bool = True, mix: bool = False, format: PCM = _DEFAULT_PCM, buffer: float = 30.0, jitter: float = 0.3, max_duration: float | None = None, max_size: int | None = None)

Record each user, or with mix=True the whole call, to Ogg Opus or WAV.

The path's extension picks the container; format is the WAV sample format. It ends on its own after max_duration seconds or once its files hold max_size bytes.

files property

files: Mapping[int | None, Path]

The files written so far by user id; a mixed recording's key is None.

stats

stats() -> ReceiverStats

The receiver's counters; it drops frames when the disk falls behind.

stop async

stop() -> dict[int | None, Path]

Write the audio heard so far, then stop and return the files.

wait async

wait() -> dict[int | None, Path]

Wait until the recording ends on its own, then return the files.

Marker

Marker(id: int, position: float, future: Future[bool])

A point in a sink's audio; awaiting it says whether all audio before it played.

Await it as often as you like; cancelling one wait leaves the others intact.

id instance-attribute

id = id

position instance-attribute

position = position

done

done() -> bool

Sink

Sink(native: Sink, handle: Handle, format: Format, *, buffer: float, stall: SinkStall, volume: float, crossfade: float = 0.0, filters: Filters = _NO_FILTERS, on_audio: Callable[[], None], on_close: Callable[[Sink], None])

A bounded writer whose audio is mixed into a voice connection.

format instance-attribute

format: Final = format

buffer instance-attribute

buffer: Final = buffer

stall instance-attribute

stall: Final = stall

crossfade instance-attribute

crossfade: Final = crossfade

filters property writable

filters: Filters

The effects Rust applies as this sink plays; changes take effect at once.

queued property

queued: float

Seconds of audio waiting to be sent.

passthrough property

passthrough: bool

Whether the last packet went out as written, without decoding.

closed property

closed: bool

volume property writable

volume: float

write async

write(data: Buffer) -> None

Queue audio, waiting while the sink holds buffer seconds or more.

write_nowait

write_nowait(data: Buffer) -> None

Queue the whole chunk in one native write, or raise BufferFull.

A large chunk overshoots buffer and converts in one call; write() slices it.

mark

mark() -> Marker

A marker after the audio written so far.

drain async

drain() -> bool

Wait until everything written so far has left; False if any was dropped.

clear

clear(*, until: Marker | None = None, since: Marker | None = None) -> None

Drop the queued audio, only the part before until, or after since.

close

close() -> None

Discard the queued audio and close; async with drains first.

stats

stats() -> SinkStats

The latest counters, or the last ones read before the sink closed.

SinkStats dataclass

SinkStats(sent: float, position: float, underruns: int, held_ticks: int, dropped: float, passthrough_packets: int)

A sink's counters in seconds; position is the playhead markers use.

sent instance-attribute

sent: float

position instance-attribute

position: float

underruns instance-attribute

underruns: int

held_ticks instance-attribute

held_ticks: int

dropped instance-attribute

dropped: float

passthrough_packets instance-attribute

passthrough_packets: int

Bytes

Bytes(data: bytes, *, hint: str | None = None)

Bases: _DecodedSource

Audio file contents in memory; hint is a file extension such as "ogg".

format property

format: Format

opened property

opened: bool

Whether open() ran, so the format and the rest are known.

duration property

duration: float | None

Length in seconds, or None when unknown.

seekable property

seekable: bool

tags property

tags: Tags

The title, artist and album the file names, read by open().

open async

open(manager: VoiceManager) -> None

seek async

seek(position: float) -> None

aclose async

aclose() -> None

again

again() -> Bytes

FFmpeg

FFmpeg(args: Sequence[str], *, executable: str = 'ffmpeg')

Bases: Source

The output of an ffmpeg command, read as 48 kHz stereo s16le; it cannot seek.

format property

format: Format

opened property

opened: bool

Whether open() ran, so the format and the rest are known.

duration property

duration: float | None

Length in seconds, or None when unknown.

seekable property

seekable: bool

tags property

tags: Tags

The title, artist and album the file names, read by open().

seek async

seek(position: float) -> None

Continue from position seconds.

again

again() -> FFmpeg

open async

open(manager: VoiceManager) -> None

aclose async

aclose() -> None

File

File(path: str | PathLike[str])

Bases: _DecodedSource

A local audio file, decoded in Rust.

format property

format: Format

opened property

opened: bool

Whether open() ran, so the format and the rest are known.

duration property

duration: float | None

Length in seconds, or None when unknown.

seekable property

seekable: bool

tags property

tags: Tags

The title, artist and album the file names, read by open().

open async

open(manager: VoiceManager) -> None

seek async

seek(position: float) -> None

aclose async

aclose() -> None

again

again() -> File

Source

Bases: ABC

Audio to play, single use: open() once, iterate, aclose().

Items are Opus packets or PCM chunks in format.

format property

format: Format

opened property

opened: bool

Whether open() ran, so the format and the rest are known.

duration property

duration: float | None

Length in seconds, or None when unknown.

seekable property

seekable: bool

tags property

tags: Tags

The title, artist and album the file names, read by open().

open abstractmethod async

open(manager: VoiceManager) -> None

Prepare the source; vc.play() calls this, or call it with bot.voice.

seek async

seek(position: float) -> None

Continue from position seconds.

again

again() -> Source

A new source that plays the same audio from the start.

aclose async

aclose() -> None

Stream

Stream(items: AsyncIterable[bytes], format: Format)

Bases: Source

Chunks from any async iterable, already in format; it cannot seek.

format property

format: Format

opened property

opened: bool

Whether open() ran, so the format and the rest are known.

duration property

duration: float | None

Length in seconds, or None when unknown.

seekable property

seekable: bool

tags property

tags: Tags

The title, artist and album the file names, read by open().

seek async

seek(position: float) -> None

Continue from position seconds.

again

again() -> Source

A new source that plays the same audio from the start.

open async

open(manager: VoiceManager) -> None

aclose async

aclose() -> None

Tags dataclass

Tags(title: str | None = None, artist: str | None = None, album: str | None = None)

What a file's tags say about it; None where they are silent.

title class-attribute instance-attribute

title: str | None = None

artist class-attribute instance-attribute

artist: str | None = None

album class-attribute instance-attribute

album: str | None = None

Url

Url(url: str, *, headers: Mapping[str, str] | None = None)

Bases: _DecodedSource

A direct HTTP(S) media URL, streamed and decoded in Rust.

format property

format: Format

opened property

opened: bool

Whether open() ran, so the format and the rest are known.

duration property

duration: float | None

Length in seconds, or None when unknown.

seekable property

seekable: bool

tags property

tags: Tags

The title, artist and album the file names, read by open().

open async

open(manager: VoiceManager) -> None

seek async

seek(position: float) -> None

aclose async

aclose() -> None

again

again() -> Url

Utterance dataclass

Utterance(user_id: int, data: bytes, offset: int, duration: float, lost: float)

One user's speech from start to end, in the receiver's PCM format.

user_id instance-attribute

user_id: int

data instance-attribute

data: bytes

offset instance-attribute

offset: int

duration instance-attribute

duration: float

lost instance-attribute

lost: float

versions

versions() -> dict[str, str]

Versions of bostie, libopus, davey and the DAVE protocol in this build.

broadcast async

broadcast(source: Source, connections: Iterable[VoiceConnection], *, encoder: EncoderSettings = _DEFAULT_ENCODER, stall: SinkStall = 'drop') -> None

Play one source on every given connection, encoding PCM once.

Connections that join later are not added; one that ends leaves the set.