{"id":28508860,"url":"https://github.com/codeconscious/audio-tag-tools","last_synced_at":"2026-05-16T08:04:53.848Z","repository":{"id":291690881,"uuid":"977368984","full_name":"codeconscious/audio-tag-tools","owner":"codeconscious","description":"Cache audio tags, search for duplicates, and export genres.","archived":false,"fork":false,"pushed_at":"2026-04-13T08:52:11.000Z","size":127,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-13T10:34:50.355Z","etag":null,"topics":["audio-tags","dotnet","fsharp"],"latest_commit_sha":null,"homepage":"","language":"F#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codeconscious.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-04T03:31:42.000Z","updated_at":"2026-04-13T08:52:13.000Z","dependencies_parsed_at":"2025-05-07T02:07:18.796Z","dependency_job_id":"da47dfa7-00d6-49df-a22e-2efc0f81b1ba","html_url":"https://github.com/codeconscious/audio-tag-tools","commit_stats":null,"previous_names":["codeconscious/duplicate-tag-finder","codeconscious/audio-tag-tools"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/codeconscious/audio-tag-tools","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeconscious%2Faudio-tag-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeconscious%2Faudio-tag-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeconscious%2Faudio-tag-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeconscious%2Faudio-tag-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codeconscious","download_url":"https://codeload.github.com/codeconscious/audio-tag-tools/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeconscious%2Faudio-tag-tools/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32407164,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T19:38:08.556Z","status":"ssl_error","status_checked_at":"2026-04-28T19:37:55.688Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio-tags","dotnet","fsharp"],"created_at":"2025-06-08T22:00:46.630Z","updated_at":"2026-05-16T08:04:53.829Z","avatar_url":"https://github.com/codeconscious.png","language":"F#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Audio Tag Tools\n\nThis small command line application performs four tasks:\n1. Cache metadata tags from audio files into a \"library file\"\n2. Report likely duplicate files based on their tags\n3. Export a list of artists with their most common genres\n4. Analyze library files and display various statistics\n\nI originally created this tool to practice with F# [JSON type providers](https://fsprojects.github.io/FSharp.Data/library/JsonProvider.html), but it resolves a couple of small pain points for me as well.\n\n\n# Requirements\n\n- [.NET 10 runtime](https://dotnet.microsoft.com/en-us/download/dotnet/10.0)\n- JSON settings file (only for the duplicate search) — plus comfort manually editing such JSON files\n\n\n# Running\n\nEnsure you are in the `AudioTagTools.Console` directory in your terminal.\n\n\n## 1. Caching tags\n\nCreates a \"tag library,\" a JSON file containing the text tag data from the audio files in a specified directory.\n\n\u003e [!NOTE]\n\u003e If you have many files, especially on an external device, this process might take a while on its initial run, but will be much faster in subsequent ones.\n\nPass `cache-tags` with two arguments:\n\n1. The path of the directory containing your audio files\n2. The path of the library file that contains (or will contain, if it does not exist yet) your cached audio tags\n\nSample:\n\n```sh\ndotnet run -- cache-tags ~/Documents/Audio ~/Documents/Audio/tagLibrary.json\n```\n\n\u003e [!TIP]\n\u003e The `--` is necessary to indicate that the command and arguments are for this program and not for `dotnet`.\n\nIf a library file already exists at the specified path, a backup copy will automatically be created in the same directory.\n\nThe file will be in this JSON format:\n\n```json\n[\n  {\n    \"FileName\": \"FILENAME.m4a\",\n    \"DirectoryName\": \"FULL_DIRECTORY_NAME\",\n    \"Artists\": [\n      \"SAMPLE ARTIST NAME\"\n    ],\n    \"AlbumArtists\": [\n      \"SAMPLE ALBUM ARTIST NAME\"\n    ],\n    \"Album\": \"ALBUM_NAME\",\n    \"TrackNo\": 0,\n    \"Title\": \"TRACK_TITLE\",\n    \"Year\": 1950,\n    \"Genres\": [\n      \"GENRE\"\n    ],\n    \"Duration\": \"00:03:39.6610000\",\n    \"LastWriteTime\": \"2024-09-12T09:40:54+09:00\"\n  }\n]\n```\n\n\u003e [!NOTE]\n\u003e This is the basically same format that the `--cache-tags` option of [my AudioTagger utility](https://github.com/codeconscious/audiotagger) outputs. The advantage of using this tool instead is that it compares tag data against files' last-modified dates and only updates out-of-date tag information, making the operation considerably faster, particularly when your audio files are on a slow external drive, etc.\n\n\n## 2. Finding duplicates\n\nFirst, you must already have a tag library file containing your cached tag data. Check the section above if you don't have one yet.\n\nSecond, you must have a settings file containing exceptions—i.e., artists, track titles, and strings that you wish to exclude from the search. Actual entries are optional, but the file must be exist in the specified format. I have provided a sample you can use below.\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand the sample and notes...\u003c/summary\u003e\n\n```json\n{\n  \"playlist\": {\n    \"saveDirectory\": \"/Users/me/Downloads/NewAudio\",\n    \"pathSearchFor\": \"/Users/me/Documents/Media/\",\n    \"pathReplaceWith\": \"\"\n  },\n  \"exclusions\": [\n    {\n      \"artist\": \"SAMPLE_ARTIST_NAME\",\n      \"title\": \"SAMPLE_TRACK_NAME\"\n    },\n    {\n      \"artist\": \"SAMPLE_ARTIST_NAME\"\n    },\n    {\n      \"title\": \"SAMPLE_TRACK_NAME\"\n    }\n  ],\n  \"equivalentArtists\": [\n      [\"artistName\", \"equivalentArtistName\"]\n  ],\n  \"artistReplacements\": [\n    \" \",\n    \"　\",\n    \"The \",\n    \"ザ・\"\n  ],\n  \"titleReplacements\": [\n    \" \",\n    \"　\",\n    \"(\",\n    \")\",\n    \"（\",\n    \"）\",\n    \"[\",\n    \"]\",\n    \"'\",\n    \"’\",\n    \"\\\"\",\n    \"”\",\n    \"-\",\n    \"–\",\n    \"—\",\n    \"~\",\n    \"〜\",\n    \"/\",\n    \"／\",\n    \"|\",\n    \"｜\",\n    \"?\",\n    \"？\",\n    \"!\",\n    \"！\",\n    \"~\",\n    \"〜\",\n    \"～\",\n    \"=\",\n    \"＝\",\n    \"\u0026\",\n    \"＆\",\n    \"#\",\n    \"＃\",\n    \"•\",\n    \"・\",\n    \".\",\n    \"。\",\n    \",\",\n    \"、\",\n    \":\",\n    \"：\",\n    \"...\",\n    \"…\",\n    \"*\",\n    \"＊\",\n    \"+\",\n    \"＋\",\n    \"=\",\n    \"＝\",\n    \"✖︎\",\n    \"❌\"\n  ]\n}\n```\n\nNotes:\n\n1. Use `pathSearchFor` and `pathReplaceWith` if you wish to modify the base path of your media files in the playlist file—for example, if you wish the load the playlist on a different device where the files reside under a different base path. Otherwise, they may be left blank.\n\n2. Use `equivalentArtists` to register lists of artists that should be considered identical for the purposes of duplicate-checking. Results will be reported using the first artist in each group.\n\n\u003c/details\u003e\n\nTo start, use the `find-duplicates` command like this:\n\n```sh\ndotnet run -- find-duplicates ~/Documents/Audio/findDupeSettings.json ~/Documents/Audio/tagLibrary.json\n```\n\nIf any potential duplicates are found, they will be listed, grouped by artist. If you see false positives (i.e., tracks that were detected as duplicates, but are actually not), you can add entries to the exclusions in your settings to ignore them in the future.\n\n\n## 3. Exporting artist genres\n\nCreates a text file containing a list of artists with the genre that they are most associated with in your tag library.\n\nTo use it, pass `export-genres` with two arguments:\n\n1. The path of your library file\n2. The path of the text file that contains (or will contain, if it does not exist yet) your artists with corresponding genres\n\nSample:\n\n```sh\ndotnet run -- export-genres ~/Downloads/Audio/tagLibrary.json ~/Downloads/Audio/genres.txt\n```\n\nIf a genres file already exists at that path, a backup will be created automatically.\n\n\n## 4. Analyzing cached tags\n\nYou must already have a tag library file containing your cached tag data. Check above if you don't have one yet.\n\nTo start, simply use the `analyze-library` command like this:\n\n```sh\ndotnet run -- analyze-library ~/Downloads/Audio/tagLibrary.json\n```\n\nSeveral categories of data (e.g., most common artists, largest files) will be displayed.\n\n\n## Other\n\n### Exit codes\n\nThe program returns the following exit codes:\n\n| Code | Meaning                                           |\n|------|---------------------------------------------------|\n| 0    | Finished successfully                             |\n| 1    | Invalid argument count                            |\n| 2    | Invalid command                                   |\n| 3    | Failure during the requested command's operation  |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeconscious%2Faudio-tag-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodeconscious%2Faudio-tag-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeconscious%2Faudio-tag-tools/lists"}