aboutsummaryrefslogtreecommitdiff
path: root/src/audio
diff options
context:
space:
mode:
authorNathan Perry <avaglir@gmail.com>2019-02-18 00:39:27 -0500
committerNathan Perry <avaglir@gmail.com>2019-02-18 00:39:27 -0500
commite589e6ee73bcdf25e1e73640792aa95ab92667f2 (patch)
tree0a2b270d9de4b97df22f884f1a90234a824a1212 /src/audio
parent3eecbaf1ff02122506ee8ee8c65e02ff1325aae0 (diff)
encode/decode audio memes with ffmpeg to improve storage
Diffstat (limited to 'src/audio')
-rw-r--r--src/audio/play_queue.rs55
-rw-r--r--src/audio/ytdl.rs19
2 files changed, 59 insertions, 15 deletions
diff --git a/src/audio/play_queue.rs b/src/audio/play_queue.rs
index 119b8c5..fcbb4f9 100644
--- a/src/audio/play_queue.rs
+++ b/src/audio/play_queue.rs
@@ -1,13 +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 flate2::bufread::DeflateDecoder;
use serenity::{
prelude::*,
voice,
@@ -94,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,
@@ -108,7 +108,52 @@ impl PlayQueue {
}
},
Right(ref vec) => {
- voice::pcm(true, DeflateDecoder::new(Cursor::new(vec.clone())))
+ 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());
+
+ for line in stderr.lines() {
+ let line = line.unwrap();
+
+ 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());
+
+ 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(" "));