Writting metadata
This commit is contained in:
+7
-4
@@ -16,11 +16,14 @@ target_include_directories(YTMusicDL26 PUBLIC
|
|||||||
|
|
||||||
include(cmake/CPM.cmake)
|
include(cmake/CPM.cmake)
|
||||||
|
|
||||||
CPMAddPackage("gh:nlohmann/json#v3.12.0")
|
# CPMAddPackage(
|
||||||
|
# NAME id3v2lib
|
||||||
|
# GIT_REPOSITORY https://github.com/larsbs/id3v2lib.git
|
||||||
|
# GIT_TAG master
|
||||||
|
# )
|
||||||
|
|
||||||
target_link_libraries(YTMusicDL26 PUBLIC
|
# target_link_libraries(YTMusicDL26 PUBLIC
|
||||||
nlohmann_json::nlohmann_json
|
# )
|
||||||
)
|
|
||||||
|
|
||||||
file(COPY ${CMAKE_SOURCE_DIR}/bin DESTINATION ${CMAKE_BINARY_DIR})
|
file(COPY ${CMAKE_SOURCE_DIR}/bin DESTINATION ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
|
|||||||
Executable
BIN
Binary file not shown.
+76
-12
@@ -5,27 +5,34 @@
|
|||||||
#include <format>
|
#include <format>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// This may come in handy later
|
|
||||||
// `yt-dlp` supports the following audio codecs:
|
|
||||||
// `mp3`: MP3 (MPEG Audio Layer 3)
|
|
||||||
// `m4a`: MPEG-4 Audio
|
|
||||||
// `ogg`: Ogg Vorbis
|
|
||||||
// `flac`: FLAC (Free Lossless Audio Codec)
|
|
||||||
// `opus`: Opus
|
|
||||||
// `aac`: AAC (Advanced Audio Coding)
|
|
||||||
|
|
||||||
#define TMP_DOWNLOAD_FOLDER "tmp/download"
|
#define TMP_DOWNLOAD_FOLDER "tmp/download"
|
||||||
#define MAX_THREADS 4
|
#define MAX_THREADS 4
|
||||||
|
|
||||||
// This runs in shell, if put through a website interface it would allow for injection
|
// This runs in shell, if put through a website interface it would allow for injection
|
||||||
auto ytdlp(std::string args) -> bool {
|
auto ytdlp(const std::string& args) -> bool {
|
||||||
system(std::format("bin/linux/yt-dlp {}", args).c_str());
|
system(std::format("bin/linux/yt-dlp {}", args).c_str());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto metadata(const std::string& file, const std::string& artist, const std::string& album, size_t index) {
|
||||||
|
std::string name = std::filesystem::path(file).filename().string();
|
||||||
|
|
||||||
|
system(std::format("bin/linux/ffmpeg "
|
||||||
|
"-hide_banner -loglevel error "
|
||||||
|
"-i \"{}\" -c copy "
|
||||||
|
"-metadata title=\"{}\" "
|
||||||
|
"-metadata artist=\"{}\" "
|
||||||
|
"-metadata album=\"{}\" "
|
||||||
|
"-metadata track=\"{}\" "
|
||||||
|
"\"{}/{}_{}.mp3\"",
|
||||||
|
file, name, artist, album, index, TMP_DOWNLOAD_FOLDER, index, name)
|
||||||
|
.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
auto cleanTmpDownloadFolder() -> bool {
|
auto cleanTmpDownloadFolder() -> bool {
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(TMP_DOWNLOAD_FOLDER)) {
|
for (const auto& entry : std::filesystem::directory_iterator(TMP_DOWNLOAD_FOLDER)) {
|
||||||
std::filesystem::remove_all(entry.path());
|
std::filesystem::remove_all(entry.path());
|
||||||
@@ -61,6 +68,41 @@ auto urlsFromPlaylist(const std::string& url) -> std::vector<std::string> {
|
|||||||
return urls;
|
return urls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto dataFromYtdlpPlaylist(const std::string& playlistUrl, const std::string& data) -> std::string {
|
||||||
|
ytdlp(
|
||||||
|
std::format("--quiet "
|
||||||
|
"--no-warnings "
|
||||||
|
"--flat-playlist "
|
||||||
|
"--playlist-items 1 "
|
||||||
|
"--print-to-file \"%({})s\" data.txt \"{}\"",
|
||||||
|
data, playlistUrl));
|
||||||
|
|
||||||
|
std::ifstream f("data.txt");
|
||||||
|
if (!f.is_open()) {
|
||||||
|
printf("ERROR: Couldn't open data.txt\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string s;
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(f, line)) {
|
||||||
|
s = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto playlistTitle(const std::string& playlistUrl) {
|
||||||
|
std::string s = dataFromYtdlpPlaylist(playlistUrl, "playlist_title");
|
||||||
|
s = std::regex_replace(s, std::regex("Album - "), "");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto channelName(const std::string& playlistUrl) {
|
||||||
|
std::string s = dataFromYtdlpPlaylist(playlistUrl, "channel");
|
||||||
|
s = std::regex_replace(s, std::regex(" - Topic"), "");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
auto downloadVideo(const std::string& url) -> bool {
|
auto downloadVideo(const std::string& url) -> bool {
|
||||||
if (url == "") {
|
if (url == "") {
|
||||||
printf("ERROR: Cannot download video with empty url\n");
|
printf("ERROR: Cannot download video with empty url\n");
|
||||||
@@ -80,7 +122,7 @@ auto downloadVideo(const std::string& url) -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto downloadPlaylist(const std::string& playlistUrl) -> bool {
|
auto downloadPlaylist(std::string playlistUrl) -> bool {
|
||||||
std::vector<std::string> videoUrls = urlsFromPlaylist(playlistUrl);
|
std::vector<std::string> videoUrls = urlsFromPlaylist(playlistUrl);
|
||||||
|
|
||||||
if (videoUrls.empty()) {
|
if (videoUrls.empty()) {
|
||||||
@@ -93,6 +135,8 @@ auto downloadPlaylist(const std::string& playlistUrl) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
playlistUrl = std::regex_replace(playlistUrl, std::regex("music.youtube"), "www.youtube");
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < videoUrls.size(); i += MAX_THREADS) {
|
for (size_t i = 0; i < videoUrls.size(); i += MAX_THREADS) {
|
||||||
@@ -116,11 +160,31 @@ auto downloadPlaylist(const std::string& playlistUrl) -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto writeAlbumMetadataToTmpFolder(const std::string& playlistUrl) -> bool {
|
||||||
|
std::string artist = channelName(playlistUrl);
|
||||||
|
std::string album = playlistTitle(playlistUrl);
|
||||||
|
printf("Starting to write metadata for %s by %s.\n", album.c_str(), artist.c_str());
|
||||||
|
|
||||||
|
size_t index = 1;
|
||||||
|
for (const auto& entry : std::filesystem::directory_iterator(TMP_DOWNLOAD_FOLDER)) {
|
||||||
|
metadata(entry.path(), artist, album, index);
|
||||||
|
printf("Finished writting metadata for %s.\n", entry.path().c_str());
|
||||||
|
std::filesystem::remove(entry.path());
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Finished writing metadata for %s by %s.\n", album.c_str(), artist.c_str());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
auto main(int argc, char* argv[]) -> int {
|
auto main(int argc, char* argv[]) -> int {
|
||||||
auto musicDir = "/home/ethanscharlie/Downloads/tmp";
|
auto musicDir = "/home/ethanscharlie/Downloads/tmp";
|
||||||
auto url = "https://music.youtube.com/playlist?list=OLAK5uy_kwG9Ln_fS_R-Oa8F-JIgs8PPBoRgDe8ok";
|
std::string url = "https://music.youtube.com/playlist?list=OLAK5uy_kwG9Ln_fS_R-Oa8F-JIgs8PPBoRgDe8ok";
|
||||||
|
|
||||||
std::filesystem::create_directories(TMP_DOWNLOAD_FOLDER);
|
std::filesystem::create_directories(TMP_DOWNLOAD_FOLDER);
|
||||||
|
|
||||||
|
url = std::regex_replace(url, std::regex("music.youtube"), "www.youtube");
|
||||||
downloadPlaylist(url);
|
downloadPlaylist(url);
|
||||||
|
writeAlbumMetadataToTmpFolder(url);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user