add option for compression

This commit is contained in:
schreifuchs 2024-01-12 12:41:26 +01:00
parent 84a63e1f7e
commit 8a22a6659d
6 changed files with 53 additions and 14 deletions

2
.gitignore vendored
View file

@ -12,3 +12,5 @@ target/
# These are backup files generated by rustfmt # These are backup files generated by rustfmt
**/*.rs.bk **/*.rs.bk
.DS_Store

2
Cargo.lock generated
View file

@ -1916,7 +1916,7 @@ dependencies = [
[[package]] [[package]]
name = "spotify-dl" name = "spotify-dl"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"audiotags", "audiotags",
"flac-bound", "flac-bound",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "spotify-dl" name = "spotify-dl"
version = "0.1.0" version = "0.1.1"
authors = ["Guillem Castro <guillemcastro4@gmail.com>"] authors = ["Guillem Castro <guillemcastro4@gmail.com>"]
edition = "2018" edition = "2018"
#links = "FLAC" #links = "FLAC"

View file

@ -28,7 +28,7 @@ brew install flac
## Usage ## Usage
``` ```
spotify-dl 0.1.0 spotify-dl 0.1.1
A commandline utility to download music directly from Spotify A commandline utility to download music directly from Spotify
USAGE: USAGE:
@ -36,10 +36,13 @@ USAGE:
FLAGS: FLAGS:
-h, --help Prints help information -h, --help Prints help information
-o, --ordered Download songs in the order they are in the playlist, prfixing the filename with the track number -o, --ordered Prefixing the filename with its index in the playlist
-V, --version Prints version information -V, --version Prints version information
OPTIONS: OPTIONS:
-c, --compression <compression> Setting the flac compression level from 0 (fastest, least compression) to
8 (slowest, most compression). A value larger than 8 will be reated as 8.
Defaults to 4.
-d, --destination <destination> The directory where the songs will be downloaded [default: .] -d, --destination <destination> The directory where the songs will be downloaded [default: .]
-p, --password <password> Your Spotify password -p, --password <password> Your Spotify password
-u, --username <username> Your Spotify username -u, --username <username> Your Spotify username
@ -56,4 +59,4 @@ The usage of this software may infringe Spotify's ToS and/or your local legislat
## License ## License
spotify-dl is licensed under the MIT license. See [LICENSE](LICENSE). spotify-dl is lic:ewensed under the MIT license. See [LICENSE](LICENSE).

View file

@ -1,24 +1,33 @@
use std::path::Path; use std::path::Path;
use audiotags::{Tag, TagType}; use audiotags::{Tag, TagType};
use librespot::{playback::{audio_backend::{Open, Sink, SinkError}, config::AudioFormat, decoder::AudioPacket, convert::Converter}}; use librespot::playback::{
audio_backend::{Open, Sink, SinkError},
config::AudioFormat,
convert::Converter,
decoder::AudioPacket,
};
// extern crate flac_bound; // extern crate flac_bound;
use flac_bound::{FlacEncoder}; use flac_bound::FlacEncoder;
use crate::TrackMetadata; use crate::TrackMetadata;
pub struct FileSink { pub struct FileSink {
sink: String, sink: String,
content: Vec<i32>, content: Vec<i32>,
metadata: Option<TrackMetadata> metadata: Option<TrackMetadata>,
compression: u32,
} }
impl FileSink { impl FileSink {
pub fn add_metadata(&mut self, meta: TrackMetadata) { pub fn add_metadata(&mut self, meta: TrackMetadata) {
self.metadata = Some(meta); self.metadata = Some(meta);
} }
pub fn set_compression(&mut self, compression: u32) {
self.compression = compression;
}
} }
impl Open for FileSink { impl Open for FileSink {
@ -28,7 +37,8 @@ impl Open for FileSink {
FileSink { FileSink {
sink: file, sink: file,
content: Vec::new(), content: Vec::new(),
metadata: None metadata: None,
compression: 4,
} }
} else { } else {
panic!(); panic!();
@ -42,21 +52,33 @@ impl Sink for FileSink {
} }
fn stop(&mut self) -> Result<(), SinkError> { fn stop(&mut self) -> Result<(), SinkError> {
let mut encoder = FlacEncoder::new().unwrap().channels(2).bits_per_sample(16).compression_level(4).init_file(&self.sink).unwrap(); let mut encoder = FlacEncoder::new()
encoder.process_interleaved(self.content.as_slice(), (self.content.len()/2) as u32).unwrap(); .unwrap()
.channels(2)
.bits_per_sample(16)
.compression_level(*&self.compression)
.init_file(&self.sink)
.unwrap();
encoder
.process_interleaved(self.content.as_slice(), (self.content.len() / 2) as u32)
.unwrap();
encoder.finish().unwrap(); encoder.finish().unwrap();
match &self.metadata { match &self.metadata {
Some(meta) => { Some(meta) => {
let mut tag = Tag::new().with_tag_type(TagType::Flac).read_from_path(Path::new(&self.sink)).unwrap(); let mut tag = Tag::new()
.with_tag_type(TagType::Flac)
.read_from_path(Path::new(&self.sink))
.unwrap();
tag.set_album_title(&meta.album); tag.set_album_title(&meta.album);
for artist in &meta.artists { for artist in &meta.artists {
tag.add_artist(artist); tag.add_artist(artist);
} }
tag.set_title(&meta.track_name); tag.set_title(&meta.track_name);
tag.write_to_path(&self.sink).expect("Failed to write metadata"); tag.write_to_path(&self.sink)
}, .expect("Failed to write metadata");
}
None => (), None => (),
} }
Ok(()) Ok(())

View file

@ -45,6 +45,13 @@ struct Opt {
help = "Prefixing the filename with its index in the playlist" help = "Prefixing the filename with its index in the playlist"
)] )]
ordered: bool, ordered: bool,
#[structopt(
short = "c",
long = "compression",
help = "Setting the flac compression level from 0 (fastest, least compression) to
8 (slowest, most compression). A value larger than 8 will be reated as 8. Defaults to 4."
)]
compression: Option<u32>,
} }
#[derive(Clone)] #[derive(Clone)]
@ -67,6 +74,7 @@ async fn download_tracks(
destination: PathBuf, destination: PathBuf,
tracks: Vec<SpotifyId>, tracks: Vec<SpotifyId>,
ordered: bool, ordered: bool,
compression: Option<u32>,
) { ) {
let player_config = PlayerConfig::default(); let player_config = PlayerConfig::default();
let bar_style = ProgressStyle::default_bar() let bar_style = ProgressStyle::default_bar()
@ -116,6 +124,9 @@ async fn download_tracks(
librespot::playback::config::AudioFormat::S16, librespot::playback::config::AudioFormat::S16,
); );
file_sink.add_metadata(metadata); file_sink.add_metadata(metadata);
if let Some(compression) = compression {
file_sink.set_compression(compression);
}
let (mut player, _) = let (mut player, _) =
Player::new(player_config.clone(), session.clone(), None, move || { Player::new(player_config.clone(), session.clone(), None, move || {
Box::new(file_sink) Box::new(file_sink)
@ -184,6 +195,7 @@ async fn main() {
PathBuf::from(opt.destination), PathBuf::from(opt.destination),
tracks, tracks,
opt.ordered, opt.ordered,
opt.compression,
) )
.await; .await;
} }