aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio/play_queue.rs90
-rw-r--r--src/audio/ytdl.rs47
-rw-r--r--src/commands/meme.rs98
-rw-r--r--src/main.rs3
4 files changed, 89 insertions, 149 deletions
diff --git a/src/audio/play_queue.rs b/src/audio/play_queue.rs
index 4bb6ade..fcbb4f9 100644
--- a/src/audio/play_queue.rs
+++ b/src/audio/play_queue.rs
@@ -1,20 +1,13 @@
use std::{
collections::VecDeque,
- io::{self, Cursor},
- iter,
- process::{
- Command,
- Stdio,
- },
+ io::{self, BufRead, BufReader, Cursor},
+ process,
sync::{Arc, RwLock},
thread,
time::Duration,
};
-use byteorder::{ByteOrder, NativeEndian};
use either::{Left, Right};
-use itertools::Itertools;
-use lame_sys;
use serenity::{
prelude::*,
voice,
@@ -114,52 +107,51 @@ impl PlayQueue {
}
}
},
- Right(ref mut v) => {
-
-// let out = unsafe {
-// let hip_t = lame_sys::hip_decode_init();
-//
-// let mut pcm_l = vec![0; 5 * 1024 * 1024 / 2];
-// let mut pcm_r = vec![0; 5 * 1024 * 1024 / 2];
-//
-// let count = lame_sys::hip_decode(hip_t,
-// v.as_mut_ptr(),
-// v.len(),
-// pcm_l.as_mut_ptr(),
-// pcm_r.as_mut_ptr());
-//
-// lame_sys::hip_decode_exit(hip_t);
-//
-// pcm_l.into_iter()
-// .interleave(pcm_r.into_iter())
-// .flat_map(|x| {
-// let mut b = vec![0u8; 2];
-// NativeEndian::write_i16(&mut b, x);
-//
-// b.into_iter()
-// })
-// .collect::<Vec<u8>>()
-// };
-
- let mut out = Command::new("lame")
+ Right(ref vec) => {
+ let mut transcoder = process::Command::new("ffmpeg")
.args(&[
- "--decode", "-t",
- "-", "-",
+ "-format", "opus",
+ "-i", "pipe:0",
+ "-acodec", "pcm_s16le",
+ "-f", "s16le",
+ "-"
])
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .stderr(Stdio::piped())
+ .stdin(process::Stdio::piped())
+ .stdout(process::Stdio::piped())
+ .stderr(process::Stdio::piped())
.spawn()
- .unwrap();
+ .expect("unable to call ffmpeg");
+
+ let process::Child {
+ stdin,
+ stderr,
+ stdout,
+ ..
+ } = transcoder;
+
+ thread::spawn(move || {
+ let stderr = BufReader::new(stderr.unwrap());
- io::copy(&mut Cursor::new(v), &mut out.stdin.as_mut().unwrap());
- let result = voice::pcm(true, Cursor::new("abc"));
+ for line in stderr.lines() {
+ let line = line.unwrap();
-// out.stdout.as_mut().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 status = out.wait_with_output().unwrap();
- println!("{}", status.status);
- println!("{}", String::from_utf8(status.stderr).unwrap());
+ let result = voice::pcm(true, stdout.unwrap());
result
}
diff --git a/src/audio/ytdl.rs b/src/audio/ytdl.rs
index 7333c18..8239683 100644
--- a/src/audio/ytdl.rs
+++ b/src/audio/ytdl.rs
@@ -45,8 +45,9 @@ pub(crate) trait CodecInfo {
}
pub(crate) struct Pcm {}
+
+#[allow(dead_code)]
pub(crate) struct Opus {}
-pub(crate) struct Mp3 {}
impl CodecInfo for Pcm {
#[inline]
@@ -67,28 +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",
- ];
- }
-
- &*OPTS
- }
-}
-
-impl CodecInfo for Mp3 {
- #[inline]
- fn ffmpeg_opts() -> &'static[&'static str] {
- lazy_static! {
- static ref OPTS: Vec<&'static str> = vec! [
- "-f", "aac",
- "-acodec", "libfdk_aac",
- "-b:a", "96k",
- "-sample_fmt", "s16",
+ "-b:a 96k",
];
}
@@ -130,7 +112,7 @@ pub fn ytdl_url(uri: &str) -> Result<String> {
}
}
-pub(crate) fn ffmpeg_dl<T: CodecInfo>(uri: &str, start: Option<Duration>, end: Option<Duration>, size_limit: Option<usize>) -> Result<Child> {
+pub(crate) fn ffmpeg_dl<T: CodecInfo>(uri: &str, start: Option<Duration>, end: Option<Duration>, size_limit: Option<usize>) -> Result<Box<dyn Read + Send>> {
let start = start.unwrap_or(Duration::zero());
let start_str = format!("{:02}:{:02}:{:02}", start.num_hours(), start.num_minutes() % 60, start.num_seconds() % 60);
@@ -146,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);
@@ -154,28 +141,24 @@ 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(" "));
- Command::new("ffmpeg")
+ let command = Command::new("ffmpeg")
.arg("-i")
.arg(uri)
.args(opts)
.stderr(Stdio::piped())
.stdin(Stdio::null())
.stdout(Stdio::piped())
- .spawn()
- .map_err(|e| e.into())
+ .spawn()?;
+
+ Ok(Box::new(ChildContainer(command)))
}
pub fn ytdl(uri: &str, start: Option<Duration>, end: Option<Duration>) -> Result<Box<AudioSource>> {
let youtube_uri = ytdl_url(uri)?;
let command = ffmpeg_dl::<Pcm>(&youtube_uri, start, end, None)?;
- Ok(pcm(true, command.stdout.unwrap()))
+ Ok(pcm(true, command))
}
diff --git a/src/commands/meme.rs b/src/commands/meme.rs
index a8ac417..913be00 100644
--- a/src/commands/meme.rs
+++ b/src/commands/meme.rs
@@ -1,5 +1,5 @@
use std::{
- io::{BufReader, Read},
+ io::Read,
process::{
Command,
Stdio,
@@ -7,14 +7,8 @@ use std::{
sync::RwLock,
};
-use byteorder::{
- ByteOrder,
- NativeEndian,
-};
use diesel::PgConnection;
use failure::Error;
-use lame_sys;
-use lame_sys::lame_set_brate;
use lazy_static::lazy_static;
use rand::{Rng, thread_rng};
use serenity::{
@@ -31,11 +25,7 @@ use audio::ytdl_url;
use crate::{
audio::{
CtxExt,
- ffmpeg_dl,
- Mp3,
- Opus,
parse_times,
- Pcm,
PlayArgs,
PlayQueue,
},
@@ -162,22 +152,39 @@ pub fn addaudiomeme(_: &mut Context, msg: &Message, mut args: Args) -> Result<()
let (start, end) = parse_times(opts);
let youtube_url = ytdl_url(audio_link.as_str())?;
- let ffmpeg_command = ffmpeg_dl::<Pcm>(&youtube_url, start, end, None)?;
- let lame = Command::new("lame")
+ let duration_opts = if let Some(e) = end {
+ vec! [
+ "-ss".to_owned(), start.map_or_else(
+ || "00:00:00".to_owned(),
+ |s| format!("{:02}:{:02}:{:02}", s.num_hours(), s.num_minutes() % 60, s.num_seconds() % 60)
+ ),
+
+ "-to".to_owned(), format!("{:02}:{:02}:{:02}", e.num_hours(), e.num_minutes() % 60, e.num_seconds() % 60),
+ ]
+ } else {
+ vec! []
+ };
+
+ let ffmpeg_command = Command::new("ffmpeg")
+ .arg("-i")
+ .arg(youtube_url)
+ .args(duration_opts)
.args(&[
- "-r",
- "-m", "s",
- "-s", "48",
- "-V", "2",
- "-b", "96",
- "-", "-",
+ "-ac", "2",
+ "-ar", "48000",
+ "-f", "opus",
+ "-acodec", "libopus",
+ "-b:a", "96k",
+ "-",
])
- .stdin(ffmpeg_command.stdout.unwrap())
.stdout(Stdio::piped())
.stderr(Stdio::null())
+ .stdin(Stdio::null())
.spawn()?;
+ let mut audio_reader = ffmpeg_command.stdout.unwrap();
+
let text = match args.multiple_quoted::<String>() {
Ok(text) => text.join(" "),
Err(_) => "".to_owned(),
@@ -196,53 +203,12 @@ pub fn addaudiomeme(_: &mut Context, msg: &Message, mut args: Args) -> Result<()
.ok();
let mut audio_data = Vec::new();
- lame.stdout.unwrap().read_to_end(&mut audio_data)?;
-
-// let mut i16_data: Vec<i16> = {
-// let mut audio_data = Vec::new();
-// let bytes = audio_reader.read_to_end(&mut audio_data)?;
-//
-// let mut i16_data = Vec::with_capacity(bytes / 2);
-// i16_data.resize(bytes / 2, 0);
-//
-// NativeEndian::read_i16_into(&audio_data, &mut i16_data);
-//
-// i16_data
-// };
-//
-// if i16_data.len() == 0 {
-// debug!("read 0 bytes from audio reader");
-// return send(msg.channel_id, "🔇🔇🔇🔕🔕🔕🔕🔕🔇🔕🔕🔇🔕🔕📣📢📣📢📣", msg.tts);
-// }
-//
-// let audio_data = unsafe {
-// let lame_flags = lame_sys::lame_init();
-//
-// lame_sys::lame_set_brate(lame_flags, 96000);
-// lame_sys::lame_set_num_channels(lame_flags, 2);
-// lame_sys::lame_set_num_samples(lame_flags, 48000);
-//
-// let mut out = Vec::<u8>::with_capacity(i16_data.len() * 2);
-// out.resize(i16_data.len() * 2, 0);
-//
-// let result = lame_sys::lame_encode_buffer_interleaved(
-// lame_flags,
-// i16_data.as_mut_ptr(),
-// (i16_data.len() / 2) as i32,
-// out.as_mut_ptr(),
-// out.len() as i32,
-// );
-//
-// if result <= 0 {
-// debug!("return code {} from lame", result);
-// return send(msg.channel_id, "wat", msg.tts);
-// }
-//
-// out.truncate(result as usize);
-//
-// out
-// };
+ let bytes = audio_reader.read_to_end(&mut audio_data)?;
+ if bytes == 0 {
+ debug!("read 0 bytes from audio reader");
+ return send(msg.channel_id, "🔇🔇🔇🔕🔕🔕🔕🔕🔇🔕🔕🔇🔕🔕📣📢📣📢📣", msg.tts);
+ }
let audio_id = Audio::create(&conn, audio_data, msg.author.id.0)?;
diff --git a/src/main.rs b/src/main.rs
index 5bfc36e..5637ecd 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,6 @@
#![feature(impl_trait_in_bindings)]
+#![feature(try_trait)]
-extern crate byteorder;
extern crate chrono;
#[cfg(feature = "diesel")]
#[macro_use] extern crate diesel;
@@ -10,7 +10,6 @@ extern crate either;
#[macro_use] extern crate failure;
extern crate fern;
#[cfg_attr(test, macro_use)] extern crate itertools;
-extern crate lame_sys;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;
extern crate rand;