0
# MP3 and ID3 Tags
1
2
This document covers MP3 audio format support and complete ID3v2 tag implementation in Mutagen. MP3 is one of the most widely supported formats with comprehensive metadata capabilities through ID3 tags.
3
4
## Imports
5
6
```python { .api }
7
# MP3 format classes
8
from mutagen.mp3 import MP3, EasyMP3, MPEGInfo, BitrateMode
9
from mutagen.mp3 import Open, delete
10
from mutagen.mp3 import STEREO, JOINTSTEREO, DUALCHANNEL, MONO
11
12
# ID3v2 tag classes and frames
13
from mutagen.id3 import ID3, ID3FileType, Frame, TextFrame, UrlFrame, BinaryFrame
14
from mutagen.id3 import Encoding, PictureType, ID3NoHeaderError, ID3UnsupportedVersionError
15
16
# Common ID3 frames
17
from mutagen.id3 import TIT2, TPE1, TALB, TRCK, TYER, TCON, APIC, COMM, GEOB
18
19
# Easy interface for ID3
20
from mutagen.easyid3 import EasyID3
21
```
22
23
## MP3 Format
24
25
### MP3 Class
26
27
```python { .api }
28
class MP3(ID3FileType):
29
"""MPEG audio file with ID3v2 tags.
30
31
Supports MPEG-1, MPEG-2, and MPEG-2.5 audio layers I, II, and III.
32
Provides access to ID3v2 tags and MPEG stream information.
33
34
Attributes:
35
info: MPEGInfo instance with stream details
36
tags: ID3 tag container (ID3 instance)
37
filename: Path to the MP3 file
38
"""
39
40
def __init__(self, filename: str) -> None:
41
"""Load MP3 file and parse ID3 tags and stream info.
42
43
Args:
44
filename: Path to MP3 file
45
46
Raises:
47
MutagenError: If file is not valid MP3 or corrupted
48
IOError: If file cannot be accessed
49
"""
50
51
def add_tags(self) -> None:
52
"""Add empty ID3v2.4 tag if no tags exist."""
53
54
def save(self, v1=1, v2_version=4, v23_sep='/', v2_padding=None, **kwargs) -> None:
55
"""Save ID3 tags to file.
56
57
Args:
58
v1: ID3v1 handling (0=none, 1=update, 2=create)
59
v2_version: ID3v2 version (3 or 4)
60
v23_sep: Text separator for ID3v2.3 multi-values
61
v2_padding: Padding strategy function or None for default
62
"""
63
64
class EasyMP3(MP3):
65
"""MP3 with EasyID3 interface for simplified tag access.
66
67
Uses dictionary-like tag names instead of ID3 frame names.
68
"""
69
70
# Function aliases
71
Open = MP3 # Alternative constructor name
72
73
def delete(filename: str) -> None:
74
"""Remove ID3 tags from MP3 file.
75
76
Args:
77
filename: Path to MP3 file
78
"""
79
80
# Usage examples
81
from mutagen.mp3 import MP3
82
83
# Load MP3 file
84
mp3_file = MP3("song.mp3")
85
86
# Access stream info
87
print(f"Duration: {mp3_file.info.length} seconds")
88
print(f"Bitrate: {mp3_file.info.bitrate} bps")
89
90
# Access ID3 tags
91
print(mp3_file["TIT2"]) # Title
92
print(mp3_file["TPE1"]) # Artist
93
94
# Modify tags
95
mp3_file["TIT2"] = "New Title"
96
mp3_file["TPE1"] = "New Artist"
97
mp3_file.save()
98
99
# Delete all tags
100
from mutagen.mp3 import delete
101
delete("song.mp3")
102
```
103
104
### MPEG Stream Information
105
106
```python { .api }
107
class MPEGInfo:
108
"""MPEG audio stream information.
109
110
Contains technical details about the MP3 audio stream including
111
bitrate, sample rate, duration, and encoding parameters.
112
113
Attributes:
114
length: Duration in seconds (float)
115
bitrate: Bitrate in bits per second (int)
116
sample_rate: Sample rate in Hz (int)
117
channels: Number of audio channels (int)
118
layer: MPEG layer (1, 2, or 3)
119
version: MPEG version (1, 2, or 2.5)
120
mode: Channel mode (STEREO, JOINTSTEREO, DUALCHANNEL, MONO)
121
bitrate_mode: BitrateMode enum (CBR, VBR, ABR, or UNKNOWN)
122
encoder_info: Encoder identification string
123
encoder_settings: Encoder settings string
124
sketchy: True if stream has potential issues
125
"""
126
127
class BitrateMode:
128
"""MPEG bitrate mode enumeration."""
129
UNKNOWN = 0
130
CBR = 1 # Constant Bitrate
131
VBR = 2 # Variable Bitrate
132
ABR = 3 # Average Bitrate
133
134
# Channel mode constants
135
STEREO = 0
136
JOINTSTEREO = 1
137
DUALCHANNEL = 2
138
MONO = 3
139
140
# Usage examples
141
mp3_file = MP3("song.mp3")
142
info = mp3_file.info
143
144
print(f"MPEG Layer: {info.layer}")
145
print(f"Version: {info.version}")
146
print(f"Sample rate: {info.sample_rate} Hz")
147
print(f"Channels: {info.channels}")
148
print(f"Mode: {info.mode}")
149
print(f"Bitrate mode: {info.bitrate_mode}")
150
151
if hasattr(info, 'encoder_info'):
152
print(f"Encoder: {info.encoder_info}")
153
```
154
155
## ID3v2 Tags
156
157
### ID3 Container
158
159
```python { .api }
160
class ID3:
161
"""ID3v2 tag container.
162
163
Dictionary-like container for ID3v2 frames. Supports ID3v2.2, 2.3, and 2.4.
164
Frame access uses 4-character ID3v2.4 frame names (e.g., TIT2, TPE1).
165
166
Attributes:
167
version: ID3v2 version tuple (major, minor)
168
unknown_frames: List of frames not recognized by Mutagen
169
"""
170
171
def __init__(self, filename: str = None) -> None:
172
"""Load ID3 tags from file.
173
174
Args:
175
filename: Path to file with ID3 tags (optional)
176
"""
177
178
def save(self, filename: str, v1=1, v2_version=4, v23_sep='/',
179
v2_padding=None, **kwargs) -> None:
180
"""Save ID3 tags to file.
181
182
Args:
183
filename: Target file path
184
v1: ID3v1 mode (0=none, 1=update existing, 2=always create)
185
v2_version: ID3v2 version to write (3 or 4)
186
v23_sep: Separator for multi-value frames in ID3v2.3
187
v2_padding: Padding function or None
188
"""
189
190
def delete(self, filename: str) -> None:
191
"""Remove ID3 tags from file."""
192
193
def update_to_v24(self) -> None:
194
"""Update frame names from older ID3 versions to v2.4."""
195
196
def update_to_v23(self) -> None:
197
"""Update frame names from v2.4 to v2.3 for compatibility."""
198
199
# Usage examples
200
from mutagen.id3 import ID3
201
202
# Load ID3 tags
203
tags = ID3("song.mp3")
204
205
# Check version
206
print(f"ID3v2.{tags.version[0]}.{tags.version[1]}")
207
208
# Frame access
209
title_frame = tags.get("TIT2")
210
if title_frame:
211
print(f"Title: {title_frame.text[0]}")
212
213
# Add frame
214
from mutagen.id3 import TIT2
215
tags["TIT2"] = TIT2(encoding=3, text="Song Title")
216
tags.save("song.mp3")
217
```
218
219
### Frame Classes
220
221
```python { .api }
222
class Frame:
223
"""Base class for all ID3v2 frames.
224
225
Each frame type has specific attributes and methods for handling
226
its particular data format and encoding requirements.
227
"""
228
229
class TextFrame(Frame):
230
"""Base class for text information frames.
231
232
Attributes:
233
encoding: Text encoding (0=latin1, 1=utf16, 2=utf16be, 3=utf8)
234
text: List of text strings
235
"""
236
237
class UrlFrame(Frame):
238
"""Base class for URL link frames.
239
240
Attributes:
241
url: URL string
242
"""
243
244
class BinaryFrame(Frame):
245
"""Base class for frames containing arbitrary binary data.
246
247
Attributes:
248
data: Raw bytes data
249
"""
250
251
# Common text frames
252
class TIT2(TextFrame):
253
"""Title/Song name/Content description frame."""
254
255
class TPE1(TextFrame):
256
"""Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group frame."""
257
258
class TALB(TextFrame):
259
"""Album/Movie/Show title frame."""
260
261
class TRCK(TextFrame):
262
"""Track number/Position in set frame."""
263
264
class TYER(TextFrame):
265
"""Year frame (deprecated in ID3v2.4, use TDRC)."""
266
267
class TCON(TextFrame):
268
"""Content type (genre) frame."""
269
270
# Attached picture frame
271
class APIC(Frame):
272
"""Attached picture frame.
273
274
Attributes:
275
encoding: Text encoding for description
276
mime: MIME type (e.g., 'image/jpeg')
277
type: Picture type (PictureType enum)
278
desc: Picture description string
279
data: Image data bytes
280
"""
281
282
class PictureType:
283
"""Picture type enumeration for APIC frames."""
284
OTHER = 0
285
FILE_ICON = 1
286
OTHER_FILE_ICON = 2
287
COVER_FRONT = 3
288
COVER_BACK = 4
289
LEAFLET_PAGE = 5
290
MEDIA = 6
291
LEAD_ARTIST = 7
292
ARTIST = 8
293
CONDUCTOR = 9
294
BAND = 10
295
COMPOSER = 11
296
LYRICIST = 12
297
RECORDING_LOCATION = 13
298
DURING_RECORDING = 14
299
DURING_PERFORMANCE = 15
300
VIDEO_SCREEN_CAPTURE = 16
301
BRIGHT_COLORED_FISH = 17
302
ILLUSTRATION = 18
303
BAND_LOGOTYPE = 19
304
PUBLISHER_LOGOTYPE = 20
305
306
# Comment frame
307
class COMM(Frame):
308
"""Comments frame.
309
310
Attributes:
311
encoding: Text encoding
312
lang: 3-character language code
313
desc: Short description
314
text: List of comment strings
315
"""
316
317
# Additional important frame types
318
class TBPM(TextFrame):
319
"""Beats per minute frame."""
320
321
class TCOM(TextFrame):
322
"""Composer frame."""
323
324
class TCOP(TextFrame):
325
"""Copyright message frame."""
326
327
class TDAT(TextFrame):
328
"""Date frame (DDMM format)."""
329
330
class TENC(TextFrame):
331
"""Encoded by frame."""
332
333
class TKEY(TextFrame):
334
"""Initial key frame."""
335
336
class TLAN(TextFrame):
337
"""Language frame."""
338
339
class TLEN(TextFrame):
340
"""Length frame (in milliseconds)."""
341
342
class TPOS(TextFrame):
343
"""Part of set frame (disc number)."""
344
345
class TPUB(TextFrame):
346
"""Publisher frame."""
347
348
class TXXX(TextFrame):
349
"""User-defined text frame.
350
351
Attributes:
352
encoding: Text encoding
353
desc: Description string
354
text: List of text strings
355
"""
356
357
class WXXX(UrlFrame):
358
"""User-defined URL frame.
359
360
Attributes:
361
encoding: Text encoding
362
desc: Description string
363
url: URL string
364
"""
365
366
class GEOB(Frame):
367
"""General encapsulated object frame.
368
369
Attributes:
370
encoding: Text encoding
371
mime: MIME type
372
filename: Filename
373
desc: Description
374
data: Binary data
375
"""
376
377
class PRIV(Frame):
378
"""Private frame.
379
380
Attributes:
381
owner: Owner identifier string
382
data: Binary private data
383
"""
384
385
class USLT(Frame):
386
"""Unsynchronized lyrics/text transcription frame.
387
388
Attributes:
389
encoding: Text encoding
390
lang: 3-character language code
391
desc: Content descriptor
392
text: Lyrics text
393
"""
394
395
# Usage examples
396
from mutagen.id3 import TIT2, TPE1, APIC, PictureType
397
398
# Create text frames
399
title = TIT2(encoding=3, text=["Song Title"])
400
artist = TPE1(encoding=3, text=["Artist Name"])
401
402
# Create picture frame
403
with open("cover.jpg", "rb") as f:
404
cover_data = f.read()
405
406
cover = APIC(
407
encoding=3,
408
mime="image/jpeg",
409
type=PictureType.COVER_FRONT,
410
desc="Front Cover",
411
data=cover_data
412
)
413
414
# Add to MP3
415
mp3_file = MP3("song.mp3")
416
mp3_file["TIT2"] = title
417
mp3_file["TPE1"] = artist
418
mp3_file["APIC:"] = cover
419
mp3_file.save()
420
```
421
422
## Easy ID3 Interface
423
424
```python { .api }
425
class EasyID3(ID3):
426
"""Dictionary-like ID3 interface with normalized tag names.
427
428
Provides simple string-based tag names instead of ID3 frame names.
429
Automatically handles encoding and multi-value conversion.
430
431
Supported keys:
432
title, artist, album, date, tracknumber, discnumber, genre,
433
albumartist, composer, performer, lyricist, conductor, etc.
434
"""
435
436
# Available tag mappings
437
valid_keys = {
438
'title': 'TIT2',
439
'artist': 'TPE1',
440
'album': 'TALB',
441
'date': 'TDRC',
442
'tracknumber': 'TRCK',
443
'discnumber': 'TPOS',
444
'genre': 'TCON',
445
'albumartist': 'TPE2',
446
# ... many more
447
}
448
449
# Usage examples
450
from mutagen.easyid3 import EasyID3
451
452
# Load with easy interface
453
easy_tags = EasyID3("song.mp3")
454
455
# Simple tag access
456
easy_tags["title"] = ["Song Title"]
457
easy_tags["artist"] = ["Artist Name"]
458
easy_tags["album"] = ["Album Name"]
459
easy_tags["date"] = ["2023"]
460
easy_tags["tracknumber"] = ["1/12"]
461
462
# Multi-value tags
463
easy_tags["genre"] = ["Rock", "Alternative"]
464
easy_tags["artist"] = ["Primary Artist", "Featured Artist"]
465
466
# Save changes
467
easy_tags.save()
468
469
# Read tags
470
print(f"Title: {easy_tags['title'][0]}")
471
print(f"Artist: {', '.join(easy_tags['artist'])}")
472
473
# List available keys
474
print("Available keys:", list(EasyID3.valid_keys.keys()))
475
```
476
477
## Advanced ID3 Features
478
479
### Custom Frames
480
481
```python { .api }
482
# User-defined text frames
483
from mutagen.id3 import TXXX
484
485
custom_text = TXXX(
486
encoding=3,
487
desc="Custom Field",
488
text=["Custom Value"]
489
)
490
mp3_file["TXXX:Custom Field"] = custom_text
491
492
# User-defined URL frames
493
from mutagen.id3 import WXXX
494
495
custom_url = WXXX(
496
encoding=3,
497
desc="Band Website",
498
url="https://example.com"
499
)
500
mp3_file["WXXX:Band Website"] = custom_url
501
502
# General encapsulated object
503
from mutagen.id3 import GEOB
504
505
embedded_file = GEOB(
506
encoding=3,
507
mime="text/plain",
508
filename="lyrics.txt",
509
desc="Song Lyrics",
510
data=b"Lyric text content here"
511
)
512
mp3_file["GEOB:"] = embedded_file
513
```
514
515
### Multiple Frame Instances
516
517
```python
518
# Multiple comment frames with different descriptions
519
from mutagen.id3 import COMM
520
521
mp3_file["COMM::eng"] = COMM(
522
encoding=3, lang="eng", desc="", text=["Main comment"]
523
)
524
525
mp3_file["COMM:Review:eng"] = COMM(
526
encoding=3, lang="eng", desc="Review", text=["Album review text"]
527
)
528
529
# Multiple attached pictures
530
mp3_file["APIC:"] = APIC(type=PictureType.COVER_FRONT, ...)
531
mp3_file["APIC:Back"] = APIC(type=PictureType.COVER_BACK, ...)
532
```
533
534
### ID3 Version Handling
535
536
```python
537
# Force specific ID3 version when saving
538
mp3_file.save(v2_version=3) # Save as ID3v2.3
539
mp3_file.save(v2_version=4) # Save as ID3v2.4
540
541
# Handle version-specific frames
542
tags = mp3_file.tags
543
if tags.version >= (2, 4):
544
# Use TDRC for date in ID3v2.4+
545
tags["TDRC"] = "2023-03-15"
546
else:
547
# Use TYER for date in ID3v2.3
548
tags["TYER"] = "2023"
549
550
# Convert between versions
551
tags.update_to_v24() # Convert to v2.4 frame names
552
tags.update_to_v23() # Convert to v2.3 frame names
553
```
554
555
## Error Handling
556
557
```python { .api }
558
from mutagen.id3 import ID3NoHeaderError, ID3UnsupportedVersionError
559
560
try:
561
mp3_file = MP3("song.mp3")
562
563
except ID3NoHeaderError:
564
print("No ID3 header found")
565
# Add tags if needed
566
mp3_file.add_tags()
567
568
except ID3UnsupportedVersionError as e:
569
print(f"Unsupported ID3 version: {e}")
570
571
except MutagenError as e:
572
print(f"ID3 error: {e}")
573
```
574
575
## Practical Examples
576
577
### Complete MP3 Tagging
578
579
```python
580
from mutagen.mp3 import MP3
581
from mutagen.id3 import TIT2, TPE1, TALB, TRCK, TDRC, TCON, APIC, PictureType
582
583
# Load MP3
584
mp3_file = MP3("song.mp3")
585
586
# Add basic tags
587
mp3_file["TIT2"] = TIT2(encoding=3, text=["Song Title"])
588
mp3_file["TPE1"] = TPE1(encoding=3, text=["Artist Name"])
589
mp3_file["TALB"] = TALB(encoding=3, text=["Album Name"])
590
mp3_file["TRCK"] = TRCK(encoding=3, text=["1/12"])
591
mp3_file["TDRC"] = TDRC(encoding=3, text=["2023"])
592
mp3_file["TCON"] = TCON(encoding=3, text=["Rock"])
593
594
# Add cover art
595
with open("cover.jpg", "rb") as f:
596
cover_data = f.read()
597
598
mp3_file["APIC:"] = APIC(
599
encoding=3,
600
mime="image/jpeg",
601
type=PictureType.COVER_FRONT,
602
desc="Cover",
603
data=cover_data
604
)
605
606
# Save with ID3v2.4
607
mp3_file.save(v2_version=4)
608
609
print("MP3 tagged successfully!")
610
```
611
612
### Cross-Format Compatibility
613
614
```python
615
def tag_mp3_file(filename, metadata):
616
"""Tag MP3 file with metadata dict."""
617
mp3_file = MP3(filename)
618
619
# Ensure tags exist
620
if mp3_file.tags is None:
621
mp3_file.add_tags()
622
623
# Map common fields to ID3 frames
624
frame_mapping = {
625
'title': 'TIT2',
626
'artist': 'TPE1',
627
'album': 'TALB',
628
'date': 'TDRC',
629
'track': 'TRCK',
630
'genre': 'TCON'
631
}
632
633
for field, frame_id in frame_mapping.items():
634
if field in metadata:
635
mp3_file[frame_id] = getattr(mutagen.id3, frame_id)(
636
encoding=3, text=[metadata[field]]
637
)
638
639
mp3_file.save()
640
```
641
642
## See Also
643
644
- [Mutagen](./index.md) - Main documentation and overview
645
- [Easy Interfaces](./easy-interfaces.md) - Simplified cross-format tag access
646
- [Core Functionality](./core-functionality.md) - Base classes and common patterns
647
- [Container Formats](./container-formats.md) - MP4 and other container formats