aboutsummaryrefslogtreecommitdiff
path: root/src/audio
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio')
-rw-r--r--src/audio/play_queue.rs69
-rw-r--r--src/audio/ytdl.rs19
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(" "));