aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Perry <avaglir@gmail.com>2019-02-17 23:02:16 -0500
committerNathan Perry <avaglir@gmail.com>2019-02-17 23:02:16 -0500
commit7cedad8e5b8e15a19951ed196b3e7e2f3c95ae8e (patch)
tree9686962d5daf9b3e7b3c523619fb933b710e90a7
parent3eecbaf1ff02122506ee8ee8c65e02ff1325aae0 (diff)
initial mp3 attempt
-rw-r--r--Cargo.lock12
-rw-r--r--Cargo.toml3
-rw-r--r--src/audio/play_queue.rs65
-rw-r--r--src/audio/ytdl.rs28
-rw-r--r--src/commands/meme.rs85
-rw-r--r--src/main.rs3
6 files changed, 168 insertions, 28 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 40a4324..4d49b89 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -662,6 +662,14 @@ dependencies = [
]
[[package]]
+name = "lame-sys"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "language-tags"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1717,6 +1725,7 @@ dependencies = [
name = "thulani"
version = "0.1.6"
dependencies = [
+ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1726,8 +1735,8 @@ dependencies = [
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"fern 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lame-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2147,6 +2156,7 @@ dependencies = [
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+"checksum lame-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ef7a865a9bc9bb053df35f36e426ccadca933d172fe131abf7a14d4084c7e38f"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
diff --git a/Cargo.toml b/Cargo.toml
index 83dad90..9cf5d3b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -28,7 +28,8 @@ regex = "1.1.0"
clap = "2.32.0"
itertools = "0.8.0"
serde_json = "~1.0"
-flate2 = "^1.0"
+lame-sys = "^0.1"
+byteorder = "^1.3"
[dependencies.serenity]
default-features = false
diff --git a/src/audio/play_queue.rs b/src/audio/play_queue.rs
index 119b8c5..4bb6ade 100644
--- a/src/audio/play_queue.rs
+++ b/src/audio/play_queue.rs
@@ -1,13 +1,20 @@
use std::{
collections::VecDeque,
- io::Cursor,
+ io::{self, Cursor},
+ iter,
+ process::{
+ Command,
+ Stdio,
+ },
sync::{Arc, RwLock},
thread,
time::Duration,
};
+use byteorder::{ByteOrder, NativeEndian};
use either::{Left, Right};
-use flate2::bufread::DeflateDecoder;
+use itertools::Itertools;
+use lame_sys;
use serenity::{
prelude::*,
voice,
@@ -94,9 +101,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,
@@ -107,8 +114,54 @@ impl PlayQueue {
}
}
},
- Right(ref vec) => {
- voice::pcm(true, DeflateDecoder::new(Cursor::new(vec.clone())))
+ 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")
+ .args(&[
+ "--decode", "-t",
+ "-", "-",
+ ])
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::piped())
+ .spawn()
+ .unwrap();
+
+ io::copy(&mut Cursor::new(v), &mut out.stdin.as_mut().unwrap());
+ let result = voice::pcm(true, Cursor::new("abc"));
+
+// out.stdout.as_mut().unwrap()
+
+ let status = out.wait_with_output().unwrap();
+ println!("{}", status.status);
+ println!("{}", String::from_utf8(status.stderr).unwrap());
+
+ result
}
};
diff --git a/src/audio/ytdl.rs b/src/audio/ytdl.rs
index e88d8f8..7333c18 100644
--- a/src/audio/ytdl.rs
+++ b/src/audio/ytdl.rs
@@ -46,6 +46,7 @@ pub(crate) trait CodecInfo {
pub(crate) struct Pcm {}
pub(crate) struct Opus {}
+pub(crate) struct Mp3 {}
impl CodecInfo for Pcm {
#[inline]
@@ -79,6 +80,22 @@ impl CodecInfo for Opus {
}
}
+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",
+ ];
+ }
+
+ &*OPTS
+ }
+}
+
pub fn ytdl_url(uri: &str) -> Result<String> {
let args = [
"-f",
@@ -113,7 +130,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<Box<dyn Read + Send>> {
+pub(crate) fn ffmpeg_dl<T: CodecInfo>(uri: &str, start: Option<Duration>, end: Option<Duration>, size_limit: Option<usize>) -> Result<Child> {
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,20 +163,19 @@ pub(crate) fn ffmpeg_dl<T: CodecInfo>(uri: &str, start: Option<Duration>, end: O
debug!("ffmpeg -i \"{}\" {}", uri, opts.join(" "));
- let command = Command::new("ffmpeg")
+ Command::new("ffmpeg")
.arg("-i")
.arg(uri)
.args(opts)
.stderr(Stdio::piped())
.stdin(Stdio::null())
.stdout(Stdio::piped())
- .spawn()?;
-
- Ok(Box::new(ChildContainer(command)))
+ .spawn()
+ .map_err(|e| e.into())
}
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))
+ Ok(pcm(true, command.stdout.unwrap()))
}
diff --git a/src/commands/meme.rs b/src/commands/meme.rs
index 160a652..a8ac417 100644
--- a/src/commands/meme.rs
+++ b/src/commands/meme.rs
@@ -1,14 +1,20 @@
use std::{
io::{BufReader, Read},
+ process::{
+ Command,
+ Stdio,
+ },
sync::RwLock,
};
+use byteorder::{
+ ByteOrder,
+ NativeEndian,
+};
use diesel::PgConnection;
use failure::Error;
-use flate2::{
- bufread::DeflateEncoder,
- Compression,
-};
+use lame_sys;
+use lame_sys::lame_set_brate;
use lazy_static::lazy_static;
use rand::{Rng, thread_rng};
use serenity::{
@@ -26,6 +32,7 @@ use crate::{
audio::{
CtxExt,
ffmpeg_dl,
+ Mp3,
Opus,
parse_times,
Pcm,
@@ -155,10 +162,21 @@ 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 mut audio_reader = DeflateEncoder::new(
- BufReader::new(ffmpeg_dl::<Pcm>(&youtube_url, start, end, None)?),
- Compression::best(),
- );
+ let ffmpeg_command = ffmpeg_dl::<Pcm>(&youtube_url, start, end, None)?;
+
+ let lame = Command::new("lame")
+ .args(&[
+ "-r",
+ "-m", "s",
+ "-s", "48",
+ "-V", "2",
+ "-b", "96",
+ "-", "-",
+ ])
+ .stdin(ffmpeg_command.stdout.unwrap())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::null())
+ .spawn()?;
let text = match args.multiple_quoted::<String>() {
Ok(text) => text.join(" "),
@@ -178,12 +196,53 @@ pub fn addaudiomeme(_: &mut Context, msg: &Message, mut args: Args) -> Result<()
.ok();
let mut audio_data = Vec::new();
- let bytes = audio_reader.read_to_end(&mut audio_data)?;
+ 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
+// };
- 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 5162015..5bfc36e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,6 @@
#![feature(impl_trait_in_bindings)]
+extern crate byteorder;
extern crate chrono;
#[cfg(feature = "diesel")]
#[macro_use] extern crate diesel;
@@ -8,8 +9,8 @@ extern crate dotenv;
extern crate either;
#[macro_use] extern crate failure;
extern crate fern;
-extern crate flate2;
#[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;