sandreas / tone

tone is a cross platform audio tagger and metadata editor to dump and modify metadata for a wide variety of formats, including mp3, m4b, flac and more. It has no dependencies and can be downloaded as single binary for Windows, macOS, Linux and other common platforms.
https://pilabor.com
Apache License 2.0
410 stars 17 forks source link

a feature request for batch tagging #42

Open rockonedege opened 1 year ago

rockonedege commented 1 year ago

I wish to have this workflow

  1. dump a folder(optionally recursively) of audios into a json file and
  2. edit the json file with an editor or script
  3. import the json to update the original files

Is this already possible?

sandreas commented 1 year ago

Hey @rockonedege,

thank you, this is a good feature request. Unfortunately the dump part is not possible out of the box at the moment, but I will definitely give this a go for the next release 0.1.6. It is important to have such a thing.

If you are on Linux or macOS, you could try something like this for the dump:

find . -type f -name '*.m4b' -exec /bin/sh -c 'FULLPATH="{}";NOEXT="${FULLPATH%.m4b}" && tone dump "$FULLPATH" --format=json > "$NOEXT.tone.json"' \;

Basically this uses find and some shell kung fu to call tone dump for every m4b file and then exports it into <filename>.tone.json. Feel free to replace m4b with other extensions.

Oh, and backup your files before doing this recursively... it may lead to unexpected consequences :-)

rockonedege commented 1 year ago

Thanks, I will give it try.

Assuming it works as expect, what is the counterpart tag option to import the json and apply it to audio files?

sandreas commented 1 year ago
tone tag audiobooks/ --auto-import=ToneJson

If i remember correctly

rockonedege commented 1 year ago

looking at the examples in the documents

tone tag --debug --auto-import=covers --meta-additional-field ©st3=testing input.m4b --dry-run

--auto-import seems expect a field name, not a json file? I am not sure I understand teh auto- part in the naming.

there's another option --meta-tone-json-file seems more appropriate by name, but I fund no example.

sandreas commented 1 year ago

--auto-import is an Enumberable containing the following possible case insensitive supporting values (not filenames)

Given one of these, tone will look for a specific file beneath to the location of the file(s) to tag, where --meta-tone-json-file means ONE specific file.

So --auto-import=ToneJson is made for recursive scanning and will take every , look for an according <filename-without-extension>.tone.json and import it if it finds one.

Example:

Try it, it will do, what you want.

rockonedege commented 1 year ago

The dump command works perfectly and generates a tone.json file for each .mp3.

then I picked one of the tone json files. changed(cleared) some fields

  "meta": {
    "album": "¸ü¶à×ÊÔ´Çë¼Ócqhdy2016",
    "artist": "Ò»ÊÖ×ÊÔ´¹Ù·½Í¬²½¸üÐÂÇë¼Ó΢ÐÅ£ºcqhdy2016",
    "comment": "¸ü¶à×ÊÔ´Çë¼Ócqhdy2016",
    "genre": "Ò»ÊÖ×ÊÔ´¹Ù·½Í¬²½¸üÐÂÇë¼Ó΢ÐÅ£ºcqhdy2016",
    "recordingDate": "2017-01-01T00:00:00",
    "title": "1 - 李靖难成仙 下山当总兵"
  },

to

  "meta": {
    "album": "",
    "artist": "",
    "comment": "",
    "genre": "",
    "recordingDate": "2017-01-01T00:00:00",
    "title": "1 - 李靖难成仙 下山当总兵"
  },

then I tried to apply the changes back to the .mp3,

$ tone tag . --auto-import ToneJson
Tagging 193 files, continue? [y/n] (y): y
── unchanged: /mnt/g/audio-test/超极封神榜/1 - 李靖难成仙 下山当总兵.mp3 ──────────────────────────────────────────────────────────────────────

No luck.

I also tried

$ tone tag .  --auto-import Ffmetadata
Tagging 193 files, continue? [y/n] (y): y
Error: Object reference not set to an instance of an object.

no luck either.

BTW, I am testing on WSL(Ubuntu) on Windows 10

sandreas commented 1 year ago

then I picked one of the tone json files. changed(cleared) some fields

Ah, I see. Clearing fields is special... I can't simply remove fields that have an empty value or are not set, because in this case it would remove EVERY tag, that is not in the export file which is mostly not the wanted behaviour in most cases.

atldotnet treats "" (empty string) same as null in most cases and cannot differ between UNSET value and SET="". I already discussed this with the maintainer and was working on a fix/workaround, but I did not have the time to finish it.

To remove fields, use e.g. --meta-remove-property=album. Maybe I need to reinvestigate this for this feature.

rockonedege commented 1 year ago

I did not really mean to remove a field, just wanted to clear some ad being put there, but that's a triaval difference I could ignore and take either reaults.

So I put some random characters to test it, and it remains unchanged still. To give you more context, here's the complete exported tone json file to be imported

{
  "audio": {
    "bitrate": 160,
    "format": "MPEG Audio (Layer III)",
    "formatShort": "MPEG",
    "sampleRate": 44100.0,
    "duration": 710920.0,
    "channels": {
      "count": 2,
      "description": "Joint Stereo"
    },
    "frames": {
      "offset": 193,
      "length": 14218449
    },
    "metaFormat": [
      "id3V23"
    ]
  },
  "meta": {
    "album": "fghdf",
    "artist": "dfffffsd",
    "comment": "sdfgfg",
    "genre": "sdfgd",
    "recordingDate": "2017-01-01T00:00:00",
    "title": "1 - 李靖难成仙 下山当总兵"
  },
  "file": {
    "size": 14218642,
    "created": "2019-11-19T07:59:40.4762029+08:00",
    "modified": "2019-11-19T07:59:40.4762029+08:00",
    "accessed": "2023-04-12T22:25:12.4108919+08:00",
    "path": "/mnt/g/audio-test/超极封神榜",
    "name": "1 - 李靖难成仙 下山当总兵.mp3"
  }
}
sandreas commented 1 year ago

Phew, you give me a lot to investigate. According to this line of code, it should work like expected.

I updated the featurette in my first comment - so I have to check, what is wrong here. Sorry, might take a while.

rockonedege commented 1 year ago

Never mind. Thanks for the help indeed.

If you need me to test, just let me know... and take your time. I am in no hurry.