Fix #661: Support for M4A/AAC files
This commit is contained in:
parent
534eaeb4e8
commit
27b248df6e
|
@ -70,6 +70,45 @@ def clean_id3_pictures(apic):
|
||||||
return pictures
|
return pictures
|
||||||
|
|
||||||
|
|
||||||
|
def get_mp4_tag(f, k):
|
||||||
|
if k == "pictures":
|
||||||
|
return f.get("covr")
|
||||||
|
raw_value = f.get(k, None)
|
||||||
|
|
||||||
|
if not raw_value:
|
||||||
|
raise TagNotFound(k)
|
||||||
|
|
||||||
|
value = raw_value[0]
|
||||||
|
try:
|
||||||
|
return value.decode()
|
||||||
|
except AttributeError:
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def get_mp4_position(raw_value):
|
||||||
|
return raw_value[0]
|
||||||
|
|
||||||
|
|
||||||
|
def clean_mp4_pictures(raw_pictures):
|
||||||
|
pictures = []
|
||||||
|
for p in list(raw_pictures):
|
||||||
|
if p.imageformat == p.FORMAT_JPEG:
|
||||||
|
mimetype = "image/jpeg"
|
||||||
|
elif p.imageformat == p.FORMAT_PNG:
|
||||||
|
mimetype = "image/png"
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
pictures.append(
|
||||||
|
{
|
||||||
|
"mimetype": mimetype,
|
||||||
|
"content": bytes(p),
|
||||||
|
"description": "",
|
||||||
|
"type": mutagen.id3.PictureType.COVER_FRONT,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return pictures
|
||||||
|
|
||||||
|
|
||||||
def get_flac_tag(f, k):
|
def get_flac_tag(f, k):
|
||||||
if k == "pictures":
|
if k == "pictures":
|
||||||
return f.pictures
|
return f.pictures
|
||||||
|
@ -216,6 +255,33 @@ CONF = {
|
||||||
"copyright": {"field": "TCOP"},
|
"copyright": {"field": "TCOP"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"MP4": {
|
||||||
|
"getter": get_mp4_tag,
|
||||||
|
"clean_pictures": clean_mp4_pictures,
|
||||||
|
"fields": {
|
||||||
|
"position": {"field": "trkn", "to_application": get_mp4_position},
|
||||||
|
"disc_number": {"field": "disk", "to_application": get_mp4_position},
|
||||||
|
"title": {"field": "©nam"},
|
||||||
|
"artist": {"field": "©ART"},
|
||||||
|
"album_artist": {"field": "aART"},
|
||||||
|
"album": {"field": "©alb"},
|
||||||
|
"date": {"field": "©day"},
|
||||||
|
"musicbrainz_albumid": {
|
||||||
|
"field": "----:com.apple.iTunes:MusicBrainz Album Id"
|
||||||
|
},
|
||||||
|
"musicbrainz_artistid": {
|
||||||
|
"field": "----:com.apple.iTunes:MusicBrainz Artist Id"
|
||||||
|
},
|
||||||
|
"genre": {"field": "©gen"},
|
||||||
|
"musicbrainz_albumartistid": {
|
||||||
|
"field": "----:com.apple.iTunes:MusicBrainz Album Artist Id"
|
||||||
|
},
|
||||||
|
"mbid": {"field": "----:com.apple.iTunes:MusicBrainz Track Id"},
|
||||||
|
"pictures": {},
|
||||||
|
"license": {"field": "----:com.apple.iTunes:LICENSE"},
|
||||||
|
"copyright": {"field": "cprt"},
|
||||||
|
},
|
||||||
|
},
|
||||||
"FLAC": {
|
"FLAC": {
|
||||||
"getter": get_flac_tag,
|
"getter": get_flac_tag,
|
||||||
"clean_pictures": clean_flac_pictures,
|
"clean_pictures": clean_flac_pictures,
|
||||||
|
|
|
@ -34,6 +34,8 @@ AUDIO_EXTENSIONS_AND_MIMETYPE = [
|
||||||
("ogg", "audio/ogg"),
|
("ogg", "audio/ogg"),
|
||||||
("opus", "audio/opus"),
|
("opus", "audio/opus"),
|
||||||
("mp3", "audio/mpeg"),
|
("mp3", "audio/mpeg"),
|
||||||
|
("aac", "audio/x-m4a"),
|
||||||
|
("m4a", "audio/x-m4a"),
|
||||||
("flac", "audio/x-flac"),
|
("flac", "audio/x-flac"),
|
||||||
("flac", "audio/flac"),
|
("flac", "audio/flac"),
|
||||||
]
|
]
|
||||||
|
|
Binary file not shown.
|
@ -149,6 +149,7 @@ def test_can_get_metadata_from_id3_mp3_file(field, value):
|
||||||
"sample.flac",
|
"sample.flac",
|
||||||
"with_cover.ogg",
|
"with_cover.ogg",
|
||||||
"with_cover.opus",
|
"with_cover.opus",
|
||||||
|
"test.m4a",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_can_get_pictures(name):
|
def test_can_get_pictures(name):
|
||||||
|
@ -189,6 +190,35 @@ def test_can_get_metadata_from_flac_file(field, value):
|
||||||
assert data.get(field) == value
|
assert data.get(field) == value
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"field,value",
|
||||||
|
[
|
||||||
|
("title", "Peer Gynt Suite no. 1, op. 46: I. Morning"),
|
||||||
|
("artist", "Edvard Grieg"),
|
||||||
|
("album_artist", "Edvard Grieg; Musopen Symphony Orchestra"),
|
||||||
|
("album", "Peer Gynt Suite no. 1, op. 46"),
|
||||||
|
("date", "2012-08-15"),
|
||||||
|
("position", 1),
|
||||||
|
("disc_number", 2),
|
||||||
|
("musicbrainz_albumid", "a766da8b-8336-47aa-a3ee-371cc41ccc75"),
|
||||||
|
("mbid", "bd21ac48-46d8-4e78-925f-d9cc2a294656"),
|
||||||
|
("musicbrainz_artistid", "013c8e5b-d72a-4cd3-8dee-6c64d6125823"),
|
||||||
|
(
|
||||||
|
"musicbrainz_albumartistid",
|
||||||
|
"013c8e5b-d72a-4cd3-8dee-6c64d6125823;5b4d7d2d-36df-4b38-95e3-a964234f520f",
|
||||||
|
),
|
||||||
|
("license", "Dummy license: http://creativecommons.org/licenses/by-sa/4.0/"),
|
||||||
|
("copyright", "Someone"),
|
||||||
|
("genre", "Dubstep"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_can_get_metadata_from_m4a_file(field, value):
|
||||||
|
path = os.path.join(DATA_DIR, "test.m4a")
|
||||||
|
data = metadata.Metadata(path)
|
||||||
|
|
||||||
|
assert data.get(field) == value
|
||||||
|
|
||||||
|
|
||||||
def test_can_get_metadata_from_flac_file_not_crash_if_empty():
|
def test_can_get_metadata_from_flac_file_not_crash_if_empty():
|
||||||
path = os.path.join(DATA_DIR, "sample.flac")
|
path = os.path.join(DATA_DIR, "sample.flac")
|
||||||
data = metadata.Metadata(path)
|
data = metadata.Metadata(path)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Support for M4A/AAC files (#661)
|
|
@ -158,7 +158,7 @@ export default {
|
||||||
currentTab: "summary",
|
currentTab: "summary",
|
||||||
uploadUrl: this.$store.getters['instance/absoluteUrl']("/api/v1/uploads/"),
|
uploadUrl: this.$store.getters['instance/absoluteUrl']("/api/v1/uploads/"),
|
||||||
importReference,
|
importReference,
|
||||||
supportedExtensions: ["flac", "ogg", "mp3", "opus"],
|
supportedExtensions: ["flac", "ogg", "mp3", "opus", "aac", "m4a"],
|
||||||
isLoadingQuota: false,
|
isLoadingQuota: false,
|
||||||
quotaStatus: null,
|
quotaStatus: null,
|
||||||
uploads: {
|
uploads: {
|
||||||
|
|
Loading…
Reference in New Issue