Notice
Recent Posts
Recent Comments
NeuroWhAI의 잡블로그
[Rust] Youtube playlist를 mp3 파일들로 다운로드 본문
대충 아래처럼 작동 합니다.
Playlist ID: PLETWVpERkQEiFcR61q36BMeOI6prNr0ci
1. 【廃墟系】けもフレEDを最終回っぽくしてみた【アレンジ】
2. Kemono Friends ED - Boku no Friend (Simpsonill Remix)
Choose the video number to download.
(0: All, q: exit): 0
Start download.
Download MbjtzH9JIKo
Title: 【廃墟系】けもフレEDを最終回っぽくしてみた【アレンジ】
Quality: 128030
2121970 / 2121970 ╢▌▌▌▌▌▌▌▌▌▌▌╟ 100.00 % 79234.86/s
Start conversion.
Conversion complete.
Done.
Download mOznRejcPfs
Title: Kemono Friends ED - Boku no Friend (Simpsonill Remix)
Quality: 128081
2529085 / 2529085 ╢▌▌▌▌▌▌▌▌▌▌▌╟ 100.00 % 74822.94/s
Start conversion.
Conversion complete.
Done.
Complete!
라이브러리만 가져다 쓴거라서 딱히 기술적으로 어려운 코드는 없습니다.
m4a 파일을 mp3로 변환하려고 ffmpeg를 썼는데그래서 실행하려면 작업 경로에 ffmpeg.exe가 있어야 합니다 ㅠㅠ
아래는 소스코드랑 의존성.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | extern crate reqwest; extern crate serde_json; extern crate rafy; use serde_json::Value; use std::io::{stdin, stdout, Read, Write}; use rafy::Rafy; use std::process::Command; struct VideoInfo { id: String, title: String, } fn get_json(uri: &String) -> Option<Value> { let mut res = reqwest::get(uri).unwrap(); if res.status().is_success() { let mut data = Vec::new(); res.read_to_end(&mut data).unwrap(); Some(serde_json::from_slice(&data.as_slice()).unwrap()) } else { None } } fn get_playlist_items(playlist_id: &str) -> Vec<VideoInfo> { let mut result = Vec::new(); let uri = format!("https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId={}&key={}", playlist_id, "YOUR_API_KEY"); if let Some(list_json) = get_json(&uri) { let items = list_json["items"].as_array().unwrap(); for info in items { let video_id = info["snippet"]["resourceId"]["videoId"].as_str().unwrap(); let video_title = info["snippet"]["title"].as_str().unwrap(); result.push(VideoInfo { id: video_id.to_owned(), title: video_title.to_owned(), }); } } else { println!("Fail to get a playlist."); } result } fn download(id: &String, title: &String) { println!(" Download {}", id); println!(" Title: {}", title); let uri = format!("https://www.youtube.com/watch?v={}", id); let content = Rafy::new(&uri).unwrap(); let title = content.title; let audiostreams = content.audiostreams; println!(" Quality: {}", audiostreams[0].quality); audiostreams[0].download(&title).unwrap(); println!(""); convert(&format!("{}.{}", title, audiostreams[0].extension), &title); println!(" Done."); } fn convert(file: &String, title: &String) { println!(" Start conversion."); // https://www.ffmpeg.org/ let mut ffmpeg = std::env::current_dir().unwrap(); ffmpeg.push("ffmpeg"); let output = Command::new(ffmpeg) .arg("-i").arg(file) .arg("-acodec").arg("libmp3lame") .arg("-aq").arg("2") .arg(format!("{}.mp3", title)) .output() .expect("Failed to run ffmpeg."); if output.status.success() { std::fs::remove_file(file).unwrap(); println!(" Conversion complete."); } else { println!(" Failed to convert {}", file); } } fn main() { print!("Playlist ID: "); stdout().flush().unwrap(); let mut playlist_id = String::new(); stdin().read_line(&mut playlist_id).unwrap(); let list = get_playlist_items(&playlist_id.trim()); loop { for (index, info) in list.iter().enumerate() { println!("{}. {}", index + 1, &info.title); } println!("Choose the video number to download."); print!("(0: All, q: exit): "); stdout().flush().unwrap(); let mut buf = String::new(); stdin().read_line(&mut buf).unwrap(); let choice: i32 = match buf.trim() { "q" | "Q" | "quit" | "Quit" | "exit" | "Exit" => break, numstr @ _ => numstr.parse().unwrap_or(-1), }; if choice < 0 || choice as usize > list.len() { println!(""); continue; } println!("Start download."); if choice == 0 { // Download all. for info in &list { download(&info.id, &info.title); } println!("Complete!"); break; } else { // Download one. let ref one = list[choice as usize - 1]; download(&one.id, &one.title); } println!(""); } } | cs |
[dependencies]
reqwest = "0.7.3"
serde_json = "1.0.2"
rafy = "0.2"
reqwest = "0.7.3"
serde_json = "1.0.2"
rafy = "0.2"
원래 친구님이 필요하다고해서 묵혀뒀다가 Rust 공부할 겸 만들기 시작했는데
이미 좋은 툴이 많아서 그냥 그거 쓰라고하고 이렇게 올린겁니다.
하핫...
아 전체공개 되어있지 않은 재생목록은 안됩니다...
이미 좋은 툴이 많아서 그냥 그거 쓰라고하고 이렇게 올린겁니다.
하핫...
아 전체공개 되어있지 않은 재생목록은 안됩니다...
'개발 및 공부 > 언어' 카테고리의 다른 글
[Rust] std::iter::IntoIterator (0) | 2018.01.03 |
---|---|
[Rust] 빌드 스크립트 (0) | 2018.01.02 |
[Rust] 문자의 아스키코드 출력 (0) | 2018.01.02 |
[C#] WPF 책 샀었던걸 반쯤 봤는데 (2) | 2018.01.02 |
[C#] DevChat - 원격 개발용 디스코드 봇 (0) | 2018.01.02 |
Comments