Added coverart support

Added Readme
Added requirements.txt
This commit is contained in:
Sebastian 2017-01-15 04:12:45 +01:00
parent 0b83358e37
commit 57933a1815
6 changed files with 99 additions and 3 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*.ogg
*.opus
*.mp3
*.mp4
/virtenv

42
README.md Normal file
View File

@ -0,0 +1,42 @@
Multitag
========
A simple tool for adding metadata to multiple audio files in different formats.
Metadata is read from a yaml file and an additional jpg (for coverart)
and can be applied to multiple files at once.
It was developed with linux in mind, but might work on other platforms as well.
**Warning:** This is tool is a quick and dirty one day hack and has only been tested using mpv.
Expect bugs and other random weirdness.
Features
---------
Support audio formats:
* mp3
* mp4
* ogg vorbis
* ogg opus
Supported metadata entries:
* Title
* Artist
* Date
* Language
* Coverart (only jpg format supported)
* Chapters
Usage
-----
`multitag.py metadatafile audiofile1 audiofile2 ... audiofileN`
Dependencies
------------
* python3
* pyyaml
* mutagen
* libm4v2 (for the m4chaps utility)

BIN
cover.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -3,7 +3,6 @@ artist: "Tony the tester"
date: "2017-01-14"
comment: "This is comment"
language: "de"
cover: "cover.jpg"
chapters:

View File

@ -3,16 +3,19 @@
import sys
import os
import subprocess
import base64
import yaml
import mutagen
from mutagen.id3 import ID3, CTOC, CHAP, TIT2, CTOCFlags
from mutagen.id3 import ID3, CTOC, CHAP, TIT2, CTOCFlags, APIC
from mutagen.easyid3 import EasyID3
from mutagen.easymp4 import EasyMP4
YAML_KEYS = ["title", "artist", "date", "comment", "cover", "language", "chapters"]
def time_to_milliseconds(time_str):
time_parts = list(map(lambda t: float(t), time_str.split(':')))
time = 0
@ -23,6 +26,7 @@ def time_to_milliseconds(time_str):
return time
def read_tag_file(chapter_file):
if not os.path.isfile(chapter_file):
raise RuntimeError("Chapter file %s does not exist" % chapter_file)
@ -50,6 +54,16 @@ def make_mp3_tags(tags, path):
id3.save()
def make_mp3_cover(cover, path):
audio = mutagen.File(path)
jpeg_data = open(cover, "rb").read()
image_tag = APIC(3, 'image/jpeg', 3, 'Cover', jpeg_data)
audio[image_tag.HashKey] = image_tag
audio.save()
def make_mp3_chapters(chapters, path):
audio = mutagen.File(path)
@ -88,6 +102,17 @@ def make_mp4_tags(tags, path):
mp4.save()
def make_mp4_cover(cover, path):
jpeg_data = open(cover, "rb").read()
cover = mutagen.mp4.MP4Cover(jpeg_data)
mp4 = mutagen.mp4.MP4(path)
mp4.tags['covr'] = [cover]
mp4.save()
def make_mp4_chapters(chapters, path):
chap_path = "%s.chapters.txt" % os.path.splitext(path)[0]
chapter_file = open(chap_path, 'w')
@ -100,6 +125,8 @@ def make_mp4_chapters(chapters, path):
os.remove(chap_path)
def make_ogg_tags(tags, audio):
audio.tags['TITLE'] = tags['title']
audio.tags['ARTIST'] = tags['artist']
@ -109,8 +136,19 @@ def make_ogg_tags(tags, audio):
audio.save()
def make_ogg_chapters(chapters, audio):
def make_ogg_cover(cover, audio):
jpeg_data = open(cover, "rb").read()
audio['coverartmime'] = 'image/jpeg'
audio['coverartdescription'] = 'Cover'
audio['coverarttype'] = '3'
audio['coverart'] = base64.b64encode(jpeg_data).decode("utf-8")
audio.save()
def make_ogg_chapters(chapters, audio):
for i in range(0, len(chapters)):
num = str(i).zfill(3)
audio.tags['CHAPTER%s' % num] = chapters[i][0]
@ -119,6 +157,7 @@ def make_ogg_chapters(chapters, audio):
audio.save()
def main():
if len(sys.argv) < 3:
@ -130,6 +169,12 @@ def main():
tags = read_tag_file(tag_file_path)
if not os.path.isfile(tags['cover']):
raise RuntimeError("%s does not exist" % cover)
if os.path.splitext(tags['cover'])[1] != ".jpg":
raise RuntimeError("Only jpgs are supported as covers")
for path in media_files:
print("Adding chapters to: %s" % path)
@ -137,12 +182,15 @@ def main():
if isinstance(audio, mutagen.mp3.MP3):
make_mp3_tags(tags, path)
make_mp3_cover(tags['cover'], path)
make_mp3_chapters(tags['chapters'], path)
elif isinstance(audio, mutagen.mp4.MP4):
make_mp4_tags(tags, path)
make_mp4_cover(tags['cover'], path)
make_mp4_chapters(tags['chapters'], path)
elif isinstance(audio, mutagen.oggvorbis.OggVorbis) or isinstance(audio, mutagen.oggopus.OggOpus):
make_ogg_tags(tags, audio)
make_ogg_cover(tags['cover'], audio)
make_ogg_chapters(tags['chapters'], audio)
else:
print("Skipping unsupported file: %s" % path)

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
mutagen==1.36
PyYAML==3.12