diff options
Diffstat (limited to 'src/audio')
| -rw-r--r-- | src/audio/play_queue.rs | 69 | ||||
| -rw-r--r-- | src/audio/ytdl.rs | 19 |
2 files changed, 56 insertions, 32 deletions
diff --git a/src/audio/play_queue.rs b/src/audio/play_queue.rs index 0ddcb93..fcbb4f9 100644 --- a/src/audio/play_queue.rs +++ b/src/audio/play_queue.rs @@ -1,16 +1,13 @@ use std::{ collections::VecDeque, - io::Cursor, + io::{self, BufRead, BufReader, Cursor}, + process, sync::{Arc, RwLock}, thread, time::Duration, }; use either::{Left, Right}; -use opus::{ - Channels, - Decoder as OpusDecoder, -}; use serenity::{ prelude::*, voice, @@ -62,7 +59,6 @@ impl PlayQueue { thread::spawn(move || { let queue_lck = Arc::clone(&queue); let voice_manager = voice_manager; - let mut opus_dec = OpusDecoder::new(48000, Channels::Stereo).unwrap(); loop { thread::sleep(Duration::from_millis(250)); @@ -98,9 +94,9 @@ impl PlayQueue { } let mut queue = queue_lck.write().unwrap(); - let item = queue.queue.pop_front().unwrap(); + let mut item = queue.queue.pop_front().unwrap(); - let src = match item.data { + let src = match &mut item.data { Left(ref url) => { match ytdl(url, item.start, item.end) { Ok(src) => src, @@ -111,24 +107,53 @@ impl PlayQueue { } } }, - Right(ref v) => { - let mut out = Vec::new(); + Right(ref vec) => { + let mut transcoder = process::Command::new("ffmpeg") + .args(&[ + "-format", "opus", + "-i", "pipe:0", + "-acodec", "pcm_s16le", + "-f", "s16le", + "-" + ]) + .stdin(process::Stdio::piped()) + .stdout(process::Stdio::piped()) + .stderr(process::Stdio::piped()) + .spawn() + .expect("unable to call ffmpeg"); + + let process::Child { + stdin, + stderr, + stdout, + .. + } = transcoder; + + thread::spawn(move || { + let stderr = BufReader::new(stderr.unwrap()); - let mut acc: usize = 0; - while acc < v.len() { - dbg!(acc); - let mut wr = vec![0i16; 960]; - match opus_dec.decode(&v[acc..], &mut wr, true) { - Ok(len) => acc += len, + for line in stderr.lines() { + let line = line.unwrap(); - Err(e) => { - info!("decoding opus packet: {}", e); - break; - }, + trace!("{}", line); } - } + }); + + let v = vec.clone(); + thread::spawn(move || { + if let Err(e) = io::copy(&mut Cursor::new(v), &mut stdin.unwrap()) { + use std::io::ErrorKind; + if e.kind() == ErrorKind::BrokenPipe { + debug!("ffmpeg closed unexpectedly"); + } else { + error!("copying audio to ffmpeg {}", e); + } + } + }); + + let result = voice::pcm(true, stdout.unwrap()); - voice::pcm(true, Cursor::new(out)) + result } }; diff --git a/src/audio/ytdl.rs b/src/audio/ytdl.rs index e88d8f8..8239683 100644 --- a/src/audio/ytdl.rs +++ b/src/audio/ytdl.rs @@ -45,6 +45,8 @@ pub(crate) trait CodecInfo { } pub(crate) struct Pcm {} + +#[allow(dead_code)] pub(crate) struct Opus {} impl CodecInfo for Pcm { @@ -66,12 +68,9 @@ impl CodecInfo for Opus { fn ffmpeg_opts() -> &'static[&'static str] { lazy_static! { static ref OPTS: Vec<&'static str> = vec! [ -// "-f", "s16le", + "-f", "opus", "-acodec", "libopus", - "-sample_fmt", "s16", - "-vbr", "off", -// "-b:a 96k", -// "-vn", + "-b:a 96k", ]; } @@ -129,6 +128,11 @@ pub(crate) fn ffmpeg_dl<T: CodecInfo>(uri: &str, start: Option<Duration>, end: O .map(|s| s.to_owned()) .collect::<Vec<_>>(); + if let Some(e) = end { + opts.push("-to".to_owned()); + opts.push(format!("{:02}:{:02}:{:02}", e.num_hours(), e.num_minutes() % 60, e.num_seconds() % 60)); + } + let codec_opts = T::ffmpeg_opts().into_iter().map(|&s| s.to_owned()).collect::<Vec<_>>(); opts.extend(codec_opts); @@ -137,11 +141,6 @@ pub(crate) fn ffmpeg_dl<T: CodecInfo>(uri: &str, start: Option<Duration>, end: O opts.push(format!("{}", limit)); } - if let Some(e) = end { - opts.push("-to".to_owned()); - opts.push(format!("{:02}:{:02}:{:02}", e.num_hours(), e.num_minutes() % 60, e.num_seconds() % 60)); - } - opts.push("-".to_owned()); debug!("ffmpeg -i \"{}\" {}", uri, opts.join(" ")); |
