gaato/discord/voice does not have a README file
pub(open) trait AudioSource {
async fn next_frame(Self) -> Bytes?
}trait DaveBackendpub(open) trait VoiceTransport {
async fn recv(Self) -> VoiceFrame
async fn send_text(Self, String) -> Unit
async fn send_binary(Self, Bytes) -> Unit
async fn close(Self, code~ : Int) -> Unit
}pub(open) trait VoiceUdp {
async fn recv(Self, FixedArray[Byte]) -> Int
async fn send(Self, Bytes) -> Unit
async fn close(Self) -> Unit
}pub(all) suberror VoiceTransportClosed {
VoiceTransportClosed(code~ : Int?, reason~ : String)
} derive(Debug)pub struct DaveMachine {
// private fields
}fn DaveMachine::encrypt_opus_frame(self : DaveMachine, ssrc~ : UInt, frame : Bytes) -> Bytes raise DaveErrorfn DaveMachine::handle(self : DaveMachine, message : VoiceMessage) -> Array[DaveAction] raise DaveErrorfn DaveMachine::new(protocol_version~ : Int, self_user_id~ : String, channel_id~ : UInt64, roster? : Array[String]) -> DaveMachine raise DaveErrorpub struct OggOpusSource {
// private fields
}impl AudioSource for OggOpusSourceasync test {
let file = @fs.open("voice.ogg")
defer file.close()
let source = @voice.OggOpusSource::from_reader(file)
let audio : &@voice.AudioSource = source
while audio.next_frame() is Some(frame) {
play_opus_frame(frame)
}
}pub struct OggOpusWriter {
// private fields
}fn OggOpusWriter::new(channels? : Int, pre_skip? : Int, serial? : UInt, max_packets_per_page? : Int) -> OggOpusWriterasync test {
let writer = @voice.OggOpusWriter::new(channels=2, pre_skip=312)
for frame in recorded_opus_frames() {
writer.write_frame(frame)
}
writer.finish()
let file = @fs.create("recording.ogg")
defer file.close()
file.write(writer.take_output())
}fn OggOpusWriter::write_frame(self : OggOpusWriter, opus : Bytes, samples? : Int) -> Unit raise OggOpusErrorpub struct OggPacketReader {
// private fields
}pub struct ReorderBuffer[T] {
// private fields
}fn[T] ReorderBuffer::push(self : ReorderBuffer[T], seq~ : Int, arrival_ms~ : Int64, packet : T) -> Array[ReorderOutput[T]]pub struct TransportCipher {
// private fields
}fn TransportCipher::new(mode : EncryptionMode, secret_key : Bytes) -> TransportCipher raise VoiceCryptoErrorfn TransportCipher::open(self : TransportCipher, packet : Bytes, header_len~ : Int) -> Bytes raise VoiceCryptoErrorfn TransportCipher::seal(self : TransportCipher, header~ : Bytes, plaintext : Bytes) -> Bytes raise VoiceCryptoErrorpub struct VoiceConnection {
// private fields
}fn[X] VoiceConnection::start(group : TaskGroup[X], credentials : VoiceCredentials, user_id~ : String, channel_id~ : UInt64, leave~ : async () -> Unit, rejoin~ : async () -> VoiceCredentials, connector? : async (String) -> &VoiceTransport, udp_opener? : async (String, Int) -> &VoiceUdp, receive? : Bool, telemetry? : (VoiceTelemetry) -> Unit, sleeper? : async (Int) -> Unit, rand? : Rand) -> VoiceConnectionfn VoiceConnection::subscribe(self : VoiceConnection, user_id~ : String, end_after_silence_ms? : Int?) -> VoiceReceiveStreamasync test {
// Echo one speaker until they are silent for one second.
connection.play(
connection.subscribe(user_id="1234", end_after_silence_ms=Some(1000)),
)
// Or record the same stream into an Ogg/Opus file.
let stream = connection.subscribe(user_id="1234")
let audio : &@voice.AudioSource = stream
let writer = @voice.OggOpusWriter::new(channels=2)
while audio.next_frame() is Some(frame) {
writer.write_frame(frame)
}
writer.finish()
}async fn VoiceConnection::wait_ready(self : VoiceConnection, timeout_ms? : Int) -> Unit raise VoiceErrorpub(all) enum VoiceEvent {
OpusReceived(user_id~ : String?, ssrc~ : UInt, sequence~ : Int, timestamp~ : UInt, opus~ : Bytes)
PacketsLost(user_id~ : String?, ssrc~ : UInt, count~ : Int)
SpeakingChanged(user_id~ : String, ssrc~ : UInt, flags~ : Int)
UserConnected(user_id~ : String)
UserDisconnected(user_id~ : String)
ConnectionReady
ConnectionResumed
} derive(Eq, Debug)pub struct VoiceGateway {
// private fields
}fn[X] VoiceGateway::start(group : TaskGroup[X], server_id~ : String, user_id~ : String, session_id~ : String, token~ : String, endpoint~ : String, max_dave_protocol_version? : UInt16, select_protocol~ : async (UInt, String, Int, Array[String]) -> (String, Int, String), connector? : async (String) -> &VoiceTransport, queue_capacity? : Int, telemetry? : (VoiceGatewayEvent) -> Unit, sleeper? : async (Int) -> Unit, rand? : Rand) -> VoiceGatewaypub(all) enum VoiceGatewayEvent {
ReadyReceived
SessionEstablished(mode~ : String, secret_key~ : Bytes, dave_protocol_version~ : Int)
Message(VoiceMessage)
Connected(resumed~ : Bool)
Disconnected(code~ : Int?, resuming~ : Bool)
ConnectFailed(reason~ : String)
NeedsRejoin(code~ : Int?)
FatallyClosed(code~ : Int)
} derive(Eq, Debug)pub(all) enum VoiceMessage {
Ready(ssrc~ : UInt, ip~ : String, port~ : Int, modes~ : Array[String])
Hello(heartbeat_interval~ : Int)
SessionDescription(mode~ : String, secret_key~ : Bytes, dave_protocol_version~ : Int)
HeartbeatAck(nonce~ : Int64)
Speaking(ssrc~ : UInt, user_id~ : String, flags~ : Int)
ClientsConnect(user_ids~ : Array[String])
ClientDisconnect(user_id~ : String)
Resumed
DavePrepareTransition(transition_id~ : Int, protocol_version~ : Int)
DaveExecuteTransition(transition_id~ : Int)
DavePrepareEpoch(epoch~ : Int, protocol_version~ : Int)
DaveMlsExternalSender(payload~ : Bytes)
DaveMlsProposals(payload~ : Bytes)
DaveMlsAnnounceCommitTransition(transition_id~ : Int, commit~ : Bytes)
DaveMlsWelcome(transition_id~ : Int, welcome~ : Bytes)
Unknown(op~ : Int)
} derive(Eq, Debug)pub struct VoiceReceiveStream {
// private fields
}impl AudioSource for VoiceReceiveStreampub(all) enum VoiceTelemetry {
GatewayEvent(VoiceGatewayEvent)
DaveMediaContextActivated(protocol_version~ : Int)
DaveBinaryControlSent(opcode~ : Int, payload_bytes~ : Int)
PacketDropped(reason~ : String)
DaveEncryptDropped(reason~ : String)
DaveDecryptDropped(user_id~ : String?, ssrc~ : UInt, count~ : Int, reason~ : String)
} derive(Eq, Debug)fn build_ip_discovery_request(ssrc : UInt) -> Bytesfn build_rtp_header(sequence~ : UInt16, timestamp~ : UInt, ssrc~ : UInt) -> Bytesasync fn discover_external_address(udp : &VoiceUdp, ssrc : UInt, retries? : Int, timeout_ms? : Int) -> (String, Int)fn encode_binary_client_frame(op : Int, payload : Bytes) -> Bytesfn encode_identify(server_id~ : String, user_id~ : String, session_id~ : String, token~ : String, max_dave_protocol_version? : UInt16) -> Jsonfn encode_resume(server_id~ : String, session_id~ : String, token~ : String, seq_ack~ : Int) -> Jsonfn parse_ip_discovery_response(bytes : Bytes, expected_ssrc~ : UInt) -> (String, Int) raise VoiceUdpErrorfn rtpsize_header_len(bytes : Bytes) -> Intasync fn run_send_loop(source : &AudioSource, cipher : TransportCipher, udp : &VoiceUdp, gateway : VoiceGateway, ssrc~ : UInt, initial_sequence? : UInt16, initial_timestamp? : UInt, stop? : Ref[Bool], frame_duration_ms? : Int, dave? : DaveMachine, on_dave_error? : (String) -> Unit) -> Unitfn shim_available() -> Boolfn shim_unavailable_reason() -> String?Install
Download zipAn experimental Discord library for MoonBit: typed APIs, a native gateway with voice (DAVE E2EE), and JS/serverless HTTP interactions.
Dependencies