{"id":16688068,"url":"https://github.com/freestrings/markdang","last_synced_at":"2025-07-06T13:37:44.129Z","repository":{"id":150428049,"uuid":"81810343","full_name":"freestrings/markdang","owner":"freestrings","description":"Console base ID3 tagger.","archived":false,"fork":false,"pushed_at":"2017-04-25T09:27:43.000Z","size":636,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-01T07:06:15.248Z","etag":null,"topics":["id3","id3-reader","id3-search","id3-writer"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/freestrings.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}},"created_at":"2017-02-13T09:59:04.000Z","updated_at":"2023-08-30T14:55:10.000Z","dependencies_parsed_at":"2023-04-09T01:34:18.951Z","dependency_job_id":null,"html_url":"https://github.com/freestrings/markdang","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/freestrings/markdang","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freestrings%2Fmarkdang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freestrings%2Fmarkdang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freestrings%2Fmarkdang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freestrings%2Fmarkdang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/freestrings","download_url":"https://codeload.github.com/freestrings/markdang/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freestrings%2Fmarkdang/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263908991,"owners_count":23528561,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["id3","id3-reader","id3-search","id3-writer"],"created_at":"2024-10-12T15:26:44.665Z","updated_at":"2025-07-06T13:37:44.112Z","avatar_url":"https://github.com/freestrings.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# What\n\n`Markdang` is shell base application to read and to write a ID3 tag. \n- it based on **[rtag](https://github.com/freestrings/rtag) library**\n\n# Why\n\nTo learn rust!\n\n# Usage\n\n## On Synology NAS\n\n### 1. Install docker on your local machine\n\n- https://docs.docker.com/engine/installation/\n\n\n### 2. Compile\n\n```bash\n$ git clone https://github.com/freestrings/markdang.git\n$ cd markdang\n$ docker run --rm -it -v \"$PWD\":/work freestrings/rust-build-armv7\n```\n\n### 3. Upload executalbe to synology NAS\n\n```bash\nscp -P 22 \"$PWD/target/armv7-unknown-linux-gnueabihf/release/markdang\" \\\n    admin-user@your-host:/usr/local/bin/markdang\n```\n\n## On Local machine\n\n### 1. Install Rust\n\n- https://www.rust-lang.org/en-US/install.html\n\n```bash\n$ curl https://sh.rustup.rs -sSf | sh\n```\n\n### 2. Compile and install\n\n```bash\n$ git clone https://github.com/freestrings/markdang.git\n$ cd markdang\n$ cargo build --release\n$ echo \"export PATH=$PWD/target/release:\\$PATH\" \u003e .markdang\n$ source .markdang\n```\n\n## Basic usage\n\n### --help option\n\n```bash\n$ markdang --help\n\nmarkdang 0.3\nChangseok Han \u003cfreestrings@gmail.com\u003e\n\nUSAGE:\n    markdang [FLAGS] [OPTIONS] \u003cINPUT\u003e...\n\nFLAGS:\n    -h, --help         Prints help information\n    -t, --transform    ff format convert to jj format\n    -V, --version      Prints version information\n    -w, --write        write mode on\n\nOPTIONS:\n    -f, --format \u003cFORMAT\u003e    default value is text. (t|tt|j|jj|f|ff) t=simple text, tt=text, j=simple json, jj=json, f=file, ff=the absolute file path with a basic metadata\n    -m, --match \u003cMATCH\u003e      it find to match id. ex) -m \"!APIC | TALB.text~'Dio'\" see more example at README.md\n\nARGS:\n    \u003cINPUT\u003e...    mp3 file pathes. ex) ./markdang file1 file2\n\n```\n\n[Reference - properties of ID3 frames](https://github.com/freestrings/rtag/blob/master/src/frame.rs#L946)\n\n### Reading: -f (--format) option\n\n- `t` simple text\n- `tt` rich text\n- `j` simple json\n- `jj` rich json\n- `f` file name only\n\n```bash\n$ find . -type f -name \"*.mp3\" -printf \"\\\"%p\\\"\\n\" | xargs markdang -f tt # tt =\u003e rich text\n/home/han/Musics/14.mp3\n\tversion: 3\n\tTIT2(TEXT { text_encoding: ISO88591, text: \"Track 14\" })\n\tTALB(TEXT { text_encoding: ISO88591, text: \"CD3\" })\n\tTPE1(TEXT { text_encoding: ISO88591, text: \"Various\" })\n\tTRCK(TEXT { text_encoding: ISO88591, text: \"14/20\" })\n    ...\n\n/home/han/Musics/...mp3\n..\n```\n\n```bash\n$ find . -type f -name \"*.mp3\" -printf \"\\\"%p\\\"\\n\" | xargs markdang -f jj # jj =\u003e rich json\n//\u003c\n{\n  \"file\": \"/home/han/Musics/4.mp3\",\n  \"head\": {\n    \"version\": \"3\",\n    \"flags\": null\n  },\n  \"frames\": [\n    {\n      \"flags\": null,\n      \"body\": {\n        \"TIT2\": {\n          \"text_encoding\": \"ISO88591\",\n          \"text\": \"Track  4\"\n        }\n      }\n    },\n    {\n      \"flags\": null,\n      \"body\": {\n        \"TALB\": {\n          \"text_encoding\": \"ISO88591\",\n          \"text\": \"CD3\"\n        }\n      }\n    },\n    ...\n  ],\n  \"frame1\": null\n}\n//\u003e\n//\u003c\n...\n//\u003e\n```\n\n### Find: -m (--match) option\n\n### `!`(not) op\n\n'!' operator can be used both for a frame id and frame property.\n\nex) To find that a album image is empty.\n\n```bash\n$ find . -type f -name \"*.mp3\" -printf \"\\\"%p\\\"\\n\" | xargs markdang -f tt -m \"\\!APIC\"\n```\n\nex) To find that a album image is empty and a track is not '2/20'. \n\n```bash\n$ find . -type f -name \"*.mp3\" -printf \"\\\"%p\\\"\\n\" | xargs markdang -f tt -m \"!APIC \u0026 TRCK.text\\!'2/20'\"\n```\n\na `text` is property of TRCK frame above example.\n - [TRCK](https://github.com/freestrings/rtag/blob/master/src/frame.rs#L2278)\n - [TEXT](https://github.com/freestrings/rtag/blob/master/src/frame.rs#L1381)\n\n###  `^`, `$`, `=`, `~` is for only property\n\n- `^`(start with)\n- `$`(end with)\n- `=`(equal)\n- `~`(contain)\n\nex) To find that a 'text_encoding' of album is 'UTF16LE' and a title contains 'Dio'\n\n```bash\n$ find . -type f -name \"*.mp3\" -printf \"\\\"%p\\\"\\n\" | xargs markdang -f tt -m \"TIT2.text~'Dio' \u0026 TALB.text_encoding='UTF16LE'\"\n```\n\n### Complex condition\n\nex) A album image is empty and a artist is 'Dio' or a artist is 'Metallica'\n\n```bash\n$ find . -type f -name \"*.mp3\" -printf \"\\\"%p\\\"\\n\" | xargs markdang -f tt -m \"\\!APIC \u0026 (TPE1~'Dio' | TPE1~'Metallica')\"\n```\n\n### Write: -w (--write) flag\n\n```bash\n$ markdang ./\u003cJSON FILE\u003e -w\n```\n\nThe format of json file. **(it is the same to `-f jj` option output)**\n\n```text\n$ markdang x.mp3 -f jj \u003e X.txt\n$ markdang X.txt -w\n```\n\n- [HeadFlag](https://github.com/freestrings/rtag/blob/master/src/frame.rs#L1939)\n- [FrameHeaderFlag](https://github.com/freestrings/rtag/blob/master/src/frame.rs#L1916)\n\n```\n//\u003c                                         // start\n{\n    \"file\": \"\",                             // \u003cfile name\u003e   type: string, madatory\n    \"head\": {                               // \u003cid3 header\u003e  type: object, optional\n        \"version\": \"\"                       // type: string\n        \"flags\": \"\"                         // type: string, comma seperated\n    },\n    \"frames\": [                             // \u003cframe v2\u003e    type: array, optional\n        {\n            \"flags\": \"\"                     // type: string, comma seperated\n            \"body\": {\n                \"FRAME ID\": {               // type: string\n                    \"PROPERTY\": \"\"          // type: string\n                }\n            }\n        },\n        ...\n    ],\n    \"frame1\": {                             // \u003cframe v1\u003e    type: object\n        \"title\": \"\",                        // type: string\n        \"artist\": \"\",                       // type: string\n        \"album\": \"\",                        // type: string\n        \"year\": \"\",                         // type: string\n        \"comment\": \"\",                      // type: string\n        \"track\": \"\",                        // type: string\n        \"genre\": \"\"                         // type: string\n    }\n}\n//\u003e                                         // end\n//\u003c\n...\n//\u003e\n```\n\n### Clean writing\n\nThe meaning of 'clean writing' is remove frame1 and re-write as version 4. see a detail explain in rtag library.\n\n- [See1](https://github.com/freestrings/rtag/blob/master/src/metadata.rs#L394)\n- [See2](https://github.com/freestrings/rtag#rewrite-how-to-rewrite-a-id3-information-to-version-4)\n\nadd `clean` option in the start.\n\n\u003e //\u003cclean\n\n```json\n//\u003cclean\n{\n  \"file\": \"\u003cabsolute path\u003e/tests/v1-v2.mp3\",\n  \"frames\": [\n    {\n      \"flags\": null,\n      \"body\": {\n        \"TIT2\": {\n          \"text_encoding\": \"UTF8\",\n          \"text\": \"타이틀\"\n        }\n      }\n    }\n  ]\n}\n//\u003e\n```\n\n```bash\n$ markdang ./tests/clean.json -w\n```\n\n### Image\n\nTo change or add image to mp3, it must use a placeholder `#{}` in a `description` property of APIC, PIC frame.\n\n\u003e The https protocol does not support. because of OpenSSL version problem on ARM.\n\nex) \n- \"description\": \"This description of artwork. #{file:/path/to/image.png}\"\n- \"description\": \"This description of artwork. #{http://path.to/image.png}\"\n- [clean.json](https://github.com/freestrings/markdang/blob/test/tests/clean.json)\n\n- [See Picture type](https://github.com/freestrings/rtag/blob/master/src/frame.rs#L1780)\n\n```bash\n{\n    ...\n    \"frames\": [\n        {\n        \"flags\": null,\n        \"body\": {\n                \"APIC\": {\n                    \"text_encoding\": \"UTF8\",\n                    \"mime_type\": \"image/jpeg\",\n                    \"picture_type\": \"CoverFront\",\n                    \"description\": \"... ${URL} ...\",\n                    \"picture_data\": [],\n                }\n            }\n        }\n    ]\n}\n```\n\n## Tagging Basic\n\n### `-f ff` option and `-t` option\n\n```bash\nmarkdang file_path -f ff\nfile: /.../xxx.mp3\nartwork: /.../Corver.jpg\ntitle:\nalbum:\nartist:\nband:\ntrack:\nyear:\n\nfind . -name \"*.mp3\" -type f -printf \"\\%p\\\"\\n\" | xargs markdang -f ff \u003e basic.txt\n\n# fill the basic.txt file\n\nmarkdang ./basic.txt -t \u003e meta.txt\nmarkdang ./meta.txt -w\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffreestrings%2Fmarkdang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffreestrings%2Fmarkdang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffreestrings%2Fmarkdang/lists"}