Guest User

Untitled

a guest
Jun 5th, 2025
13
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.92 KB | None | 0 0
  1. // main.rs
  2.  
  3. use tokio_tungstenite::{connect_async, tungstenite::protocol::Message};
  4. use futures::{SinkExt, StreamExt};
  5. use url::Url;
  6. use serde_json::json;
  7. use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
  8. use audiopus::coder::Decoder as OpusDecoder;
  9. use std::{sync::{Arc, Mutex}, collections::VecDeque};
  10.  
  11. #[tokio::main]
  12. async fn main() -> Result<(), Box<dyn std::error::Error>> {
  13. println!("Connecting to Lavalink WS...");
  14.  
  15. let url = Url::parse("ws://localhost:2333")?;
  16. let (ws_stream, _) = connect_async(url).await?;
  17. let (mut write, mut read) = ws_stream.split();
  18.  
  19. // Fake Discord Voice State Update
  20. let voice_update = json!({
  21. "op": "voiceUpdate",
  22. "guildId": "1",
  23. "sessionId": "dummy",
  24. "event": {
  25. "token": "dummy",
  26. "guild_id": "1",
  27. "endpoint": "dummy"
  28. }
  29. });
  30. write.send(Message::Text(voice_update.to_string())).await?;
  31.  
  32. // Load and play track
  33. let track_id = fetch_track().await?;
  34.  
  35. let play = json!({
  36. "op": "play",
  37. "guildId": "1",
  38. "track": track_id
  39. });
  40. write.send(Message::Text(play.to_string())).await?;
  41.  
  42. println!("Playback started.");
  43.  
  44. // Setup Opus decoder
  45. let mut opus = OpusDecoder::new(48000, audiopus::Channels::Stereo)?;
  46. let pcm_buffer = Arc::new(Mutex::new(VecDeque::new()));
  47. let pcm_clone = pcm_buffer.clone();
  48.  
  49. // Setup CPAL audio output
  50. let host = cpal::default_host();
  51. let device = host.default_output_device().ok_or("No output device")?;
  52. let config = device.default_output_config()?;
  53. let stream = device.build_output_stream(
  54. &config.config(),
  55. move |data: &mut [f32], _| {
  56. let mut buf = pcm_clone.lock().unwrap();
  57. for sample in data.iter_mut() {
  58. *sample = buf.pop_front().unwrap_or(0.0);
  59. }
  60. },
  61. |err| eprintln!("Stream error: {err}"),
  62. None,
  63. )?;
  64. stream.play()?;
  65.  
  66. // Read and decode opus packets
  67. while let Some(msg) = read.next().await {
  68. if let Ok(Message::Binary(data)) = msg {
  69. let mut output = [0f32; 1920 * 2];
  70. let samples = opus.decode_float(&data, &mut output, false)?;
  71. pcm_buffer.lock().unwrap().extend(&output[..samples * 2]);
  72. } else if let Ok(Message::Text(txt)) = msg {
  73. println!("WS Message: {txt}");
  74. }
  75. }
  76.  
  77. Ok(())
  78. }
  79.  
  80. async fn fetch_track() -> Result<String, Box<dyn std::error::Error>> {
  81. let client = reqwest::Client::new();
  82. let res = client
  83. .get("http://localhost:2333/v4/loadtracks")
  84. .header("Authorization", "youshallnotpass")
  85. .query(&[("identifier", "ytsearch:Never Gonna Give You Up")])
  86. .send()
  87. .await?;
  88. let json: serde_json::Value = res.json().await?;
  89. let track = json["data"][0]["encoded"].as_str().unwrap().to_string();
  90. Ok(track)
  91. }
  92.  
Advertisement
Add Comment
Please, Sign In to add comment