The play method is playing the previous input source instead of the currecnt source.
phoxwupsh opened this issue · 3 comments
Songbird version: 0.3.2
Rust version (rustc -V
): 1.69.0
Serenity/Twilight version: 0.11.5
Output of ffmpeg -version
, yt-dlp --version
(if relevant):
ffmpeg -version
ffmpeg version 6.0-full_build-www.gyan.dev Copyright (c) 2000-2023 the FFmpeg developers
built with gcc 12.2.0 (Rev10, Built by MSYS2 project)
configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libaribb24 --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libjxl --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libvpl --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
libavutil 58. 2.100 / 58. 2.100
libavcodec 60. 3.100 / 60. 3.100
libavformat 60. 3.100 / 60. 3.100
libavdevice 60. 1.100 / 60. 1.100
libavfilter 9. 3.100 / 9. 3.100
libswscale 7. 1.100 / 7. 1.100
libswresample 4. 10.100 / 4. 10.100
libpostproc 57. 1.100 / 57. 1.100
yt-dlp --version
2023.03.04
Description:
The problem is like, for example, I send play
command and use YouTube link A
as an argument, it can play A
correctly, then I send play
command and use another YouTube link B
as argument while A
is still playing, it will stop A
and play A
again, instead of playing B
. While it is playing A
in the second time (that the input is actually B
), and I send play
command and use B
as argument again, then it stop A
and start playing B
. Consequently, if I need to stop the track playing currently and start playing another track by using play
, I have to send the play
command twice. In my code, I implement my play
command myself, and I'm not using the builtin-queue
feature, I implement a HashMap
to store what is playing for each guild instead. Below is my code:
#[command]
async fn play(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
let guild = msg.guild(&ctx.cache).unwrap();
let guild_id = guild.id;
// Check if url is provided
match args.single::<String>() {
// If url is provided
Ok(url) => {
// Check if the user is in a voice channel
let user_voice_channel_id = match guild.voice_states.get(&msg.author.id)
.and_then(|voice_channel| voice_channel.channel_id) {
Some(channel_id) => channel_id,
None => {
msg.reply(ctx, "You are not in a voice channel").await?;
return Ok(())
}
};
// Get the Songbird instance
let manager = songbird::get(ctx).await.expect("Songbird Voice client placed in at initialization.");
let handler_lock = match manager.get(guild_id) {
Some(handler_lock) => {
// If the bot is already in a voice channel
let current_channel_id = guild.voice_states.get(&ctx.cache.current_user_id())
.and_then(|voice_state| voice_state.channel_id)
.unwrap();
if current_channel_id != user_voice_channel_id {
// The bot is in another channel
msg.reply(ctx, format!("I'm currently in {}.", current_channel_id.mention())).await?;
return Ok(());
}
handler_lock
},
None => {
let (handler_lock, success) = manager.join(guild_id, user_voice_channel_id).await;
if let Ok(_) = success {
msg.channel_id.say(ctx, format!("Join {}", user_voice_channel_id.mention())).await?;
}
handler_lock
}
};
// Validate the URL
if !Url::parse(&url).is_ok() {
msg.reply(ctx, "You must provide a valid YouTube URL.").await?;
return Ok(());
}
let source = ytdl(&url).await?;
let mut handler = handler_lock.lock().await;
let track_handle = handler.play_only_source(source);
let title = track_handle.metadata().title.clone().unwrap();
// Update the current track
let playing_lock = {
let data_read = ctx.data.read().await;
data_read.get::<Playing>().expect("Expected Playing in TypeMap").clone()
};
{
let mut playing = playing_lock.write().await;
let _ = playing.insert(guild_id, track_handle);
}
// Inform the user about the song being played
msg.reply(ctx, format!("Now playing: {}", title)).await?;
},
Err(_) => {
// Check if there is a paused track
let playing_lock = {
let data_read = ctx.data.read().await;
data_read.get::<Playing>().expect("Expected Playing in TypeMap").clone()
};
{
let playing = playing_lock.read().await;
if let Some(current_track) = playing.get(&guild_id) {
match current_track.get_info().await {
Ok(track_state) => match track_state.playing {
PlayMode::Pause => {
let _ = current_track.play();
return Ok(())
},
_ => ()
},
Err(_) => ()
};
} else {
msg.reply(ctx, "You have to provide a url.").await?;
}
return Ok(())
}
}
};
Ok(())
}
Steps to reproduce:
You can reproduce this with this example code by using the play
command in it.
Following this thread as it seems we're also having this issue on our side.
Thanks for the report, I suspect this is coming from how youtube-dl/yt-dlc/yt-dlp behaves. Unfortunately, I don't have too much time for non-next
development -- If you can investigate and fix, then feel free!
@FelixMcFelix your suspicions are right, I update my yt-dlp version to 2023.04.27.022240
, which is a nightly version, and the problem is solved. Thanks a lot!