diff options
| author | Nathan Perry <avaglir@gmail.com> | 2019-02-17 23:02:16 -0500 |
|---|---|---|
| committer | Nathan Perry <avaglir@gmail.com> | 2019-02-17 23:02:16 -0500 |
| commit | 7cedad8e5b8e15a19951ed196b3e7e2f3c95ae8e (patch) | |
| tree | 9686962d5daf9b3e7b3c523619fb933b710e90a7 | |
| parent | 3eecbaf1ff02122506ee8ee8c65e02ff1325aae0 (diff) | |
initial mp3 attempt
| -rw-r--r-- | Cargo.lock | 12 | ||||
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | src/audio/play_queue.rs | 65 | ||||
| -rw-r--r-- | src/audio/ytdl.rs | 28 | ||||
| -rw-r--r-- | src/commands/meme.rs | 85 | ||||
| -rw-r--r-- | src/main.rs | 3 |
6 files changed, 168 insertions, 28 deletions
@@ -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" @@ -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; |
