or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

container-formats.mdcore-functionality.mdeasy-interfaces.mdindex.mdlossless-formats.mdmp3-id3.mdogg-formats.md

mp3-id3.mddocs/

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