tinytag 2.2.1__tar.gz → 2.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tinytag might be problematic. Click here for more details.

@@ -0,0 +1,19 @@
1
+ # SPDX-FileCopyrightText: 2025 tinytag Contributors
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ root = true
5
+
6
+ [*]
7
+ charset = utf-8
8
+ end_of_line = lf
9
+ indent_size = 4
10
+ indent_style = space
11
+ insert_final_newline = true
12
+ max_line_length = 79
13
+ trim_trailing_whitespace = true
14
+
15
+ [*.md]
16
+ trim_trailing_whitespace = false
17
+
18
+ [*.yml]
19
+ indent_size = 2
@@ -0,0 +1,24 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 tinytag Contributors
3
+ SPDX-License-Identifier: MIT
4
+ -->
5
+
6
+ # Contributing
7
+
8
+ Before submitting a PR, please discuss the change you wish to make in an issue
9
+ report or discussion thread, in order to see if it fits the direction of the
10
+ project. If you skip this step, a PR containing anything other than a trivial
11
+ bug fix will likely be rejected.
12
+
13
+ Contributions generated or co-authored by LLMs or AI coding tools are not
14
+ allowed. Your contribution must be licensed as original work that is personally
15
+ authored by you under the terms of the
16
+ [MIT License](https://github.com/tinytag/tinytag/blob/HEAD/LICENSE).
17
+ Every part of your contribution must be written, thoroughly tested and fully
18
+ understood by you so that any queries about the logic of your contribution can
19
+ be answered during the review process.
20
+
21
+ You may only use AI assistants or tooling for learning purposes, including
22
+ guided research of the codebase and exploring concepts. Your contribution must
23
+ not include any content produced by generative AI (code, text snippets, images
24
+ nor other media).
@@ -0,0 +1,121 @@
1
+ Creative Commons Legal Code
2
+
3
+ CC0 1.0 Universal
4
+
5
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
6
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
7
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
8
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
9
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
10
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
11
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
12
+ HEREUNDER.
13
+
14
+ Statement of Purpose
15
+
16
+ The laws of most jurisdictions throughout the world automatically confer
17
+ exclusive Copyright and Related Rights (defined below) upon the creator
18
+ and subsequent owner(s) (each and all, an "owner") of an original work of
19
+ authorship and/or a database (each, a "Work").
20
+
21
+ Certain owners wish to permanently relinquish those rights to a Work for
22
+ the purpose of contributing to a commons of creative, cultural and
23
+ scientific works ("Commons") that the public can reliably and without fear
24
+ of later claims of infringement build upon, modify, incorporate in other
25
+ works, reuse and redistribute as freely as possible in any form whatsoever
26
+ and for any purposes, including without limitation commercial purposes.
27
+ These owners may contribute to the Commons to promote the ideal of a free
28
+ culture and the further production of creative, cultural and scientific
29
+ works, or to gain reputation or greater distribution for their Work in
30
+ part through the use and efforts of others.
31
+
32
+ For these and/or other purposes and motivations, and without any
33
+ expectation of additional consideration or compensation, the person
34
+ associating CC0 with a Work (the "Affirmer"), to the extent that he or she
35
+ is an owner of Copyright and Related Rights in the Work, voluntarily
36
+ elects to apply CC0 to the Work and publicly distribute the Work under its
37
+ terms, with knowledge of his or her Copyright and Related Rights in the
38
+ Work and the meaning and intended legal effect of CC0 on those rights.
39
+
40
+ 1. Copyright and Related Rights. A Work made available under CC0 may be
41
+ protected by copyright and related or neighboring rights ("Copyright and
42
+ Related Rights"). Copyright and Related Rights include, but are not
43
+ limited to, the following:
44
+
45
+ i. the right to reproduce, adapt, distribute, perform, display,
46
+ communicate, and translate a Work;
47
+ ii. moral rights retained by the original author(s) and/or performer(s);
48
+ iii. publicity and privacy rights pertaining to a person's image or
49
+ likeness depicted in a Work;
50
+ iv. rights protecting against unfair competition in regards to a Work,
51
+ subject to the limitations in paragraph 4(a), below;
52
+ v. rights protecting the extraction, dissemination, use and reuse of data
53
+ in a Work;
54
+ vi. database rights (such as those arising under Directive 96/9/EC of the
55
+ European Parliament and of the Council of 11 March 1996 on the legal
56
+ protection of databases, and under any national implementation
57
+ thereof, including any amended or successor version of such
58
+ directive); and
59
+ vii. other similar, equivalent or corresponding rights throughout the
60
+ world based on applicable law or treaty, and any national
61
+ implementations thereof.
62
+
63
+ 2. Waiver. To the greatest extent permitted by, but not in contravention
64
+ of, applicable law, Affirmer hereby overtly, fully, permanently,
65
+ irrevocably and unconditionally waives, abandons, and surrenders all of
66
+ Affirmer's Copyright and Related Rights and associated claims and causes
67
+ of action, whether now known or unknown (including existing as well as
68
+ future claims and causes of action), in the Work (i) in all territories
69
+ worldwide, (ii) for the maximum duration provided by applicable law or
70
+ treaty (including future time extensions), (iii) in any current or future
71
+ medium and for any number of copies, and (iv) for any purpose whatsoever,
72
+ including without limitation commercial, advertising or promotional
73
+ purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
74
+ member of the public at large and to the detriment of Affirmer's heirs and
75
+ successors, fully intending that such Waiver shall not be subject to
76
+ revocation, rescission, cancellation, termination, or any other legal or
77
+ equitable action to disrupt the quiet enjoyment of the Work by the public
78
+ as contemplated by Affirmer's express Statement of Purpose.
79
+
80
+ 3. Public License Fallback. Should any part of the Waiver for any reason
81
+ be judged legally invalid or ineffective under applicable law, then the
82
+ Waiver shall be preserved to the maximum extent permitted taking into
83
+ account Affirmer's express Statement of Purpose. In addition, to the
84
+ extent the Waiver is so judged Affirmer hereby grants to each affected
85
+ person a royalty-free, non transferable, non sublicensable, non exclusive,
86
+ irrevocable and unconditional license to exercise Affirmer's Copyright and
87
+ Related Rights in the Work (i) in all territories worldwide, (ii) for the
88
+ maximum duration provided by applicable law or treaty (including future
89
+ time extensions), (iii) in any current or future medium and for any number
90
+ of copies, and (iv) for any purpose whatsoever, including without
91
+ limitation commercial, advertising or promotional purposes (the
92
+ "License"). The License shall be deemed effective as of the date CC0 was
93
+ applied by Affirmer to the Work. Should any part of the License for any
94
+ reason be judged legally invalid or ineffective under applicable law, such
95
+ partial invalidity or ineffectiveness shall not invalidate the remainder
96
+ of the License, and in such case Affirmer hereby affirms that he or she
97
+ will not (i) exercise any of his or her remaining Copyright and Related
98
+ Rights in the Work or (ii) assert any associated claims and causes of
99
+ action with respect to the Work, in either case contrary to Affirmer's
100
+ express Statement of Purpose.
101
+
102
+ 4. Limitations and Disclaimers.
103
+
104
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
105
+ surrendered, licensed or otherwise affected by this document.
106
+ b. Affirmer offers the Work as-is and makes no representations or
107
+ warranties of any kind concerning the Work, express, implied,
108
+ statutory or otherwise, including without limitation warranties of
109
+ title, merchantability, fitness for a particular purpose, non
110
+ infringement, or the absence of latent or other defects, accuracy, or
111
+ the present or absence of errors, whether or not discoverable, all to
112
+ the greatest extent permissible under applicable law.
113
+ c. Affirmer disclaims responsibility for clearing rights of other persons
114
+ that may apply to the Work or any use thereof, including without
115
+ limitation any person's Copyright and Related Rights in the Work.
116
+ Further, Affirmer disclaims responsibility for obtaining any necessary
117
+ consents, permissions or other rights required for any use of the
118
+ Work.
119
+ d. Affirmer understands and acknowledges that Creative Commons is not a
120
+ party to this document and has no duty or obligation with respect to
121
+ this CC0 or use of the Work.
@@ -0,0 +1 @@
1
+ ../LICENSE
@@ -1,3 +1,45 @@
1
+ Metadata-Version: 2.4
2
+ Name: tinytag
3
+ Version: 2.3.1
4
+ Summary: Read audio file metadata
5
+ Keywords: metadata,audio,music,mp3,m4a,wav,ogg,opus,flac,wma,aiff
6
+ Author: Tom Wallroth, Mat (mathiascode)
7
+ Requires-Python: >=3.7
8
+ Description-Content-Type: text/markdown
9
+ Classifier: Programming Language :: Python
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.7
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Programming Language :: Python :: Free Threading :: 4 - Resilient
20
+ Classifier: License :: OSI Approved :: MIT License
21
+ Classifier: Development Status :: 5 - Production/Stable
22
+ Classifier: Environment :: Web Environment
23
+ Classifier: Intended Audience :: Developers
24
+ Classifier: Operating System :: OS Independent
25
+ Classifier: Topic :: Internet :: WWW/HTTP
26
+ Classifier: Topic :: Multimedia
27
+ Classifier: Topic :: Multimedia :: Sound/Audio
28
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
29
+ Classifier: Typing :: Typed
30
+ License-File: LICENSE
31
+ Requires-Dist: build ; extra == "dev"
32
+ Requires-Dist: coverage ; extra == "dev"
33
+ Requires-Dist: flit_core ; extra == "dev"
34
+ Requires-Dist: mypy ; extra == "dev"
35
+ Requires-Dist: mypy<1.19.0 ; extra == "dev" and ( platform_python_implementation == 'PyPy')
36
+ Requires-Dist: pycodestyle ; extra == "dev"
37
+ Requires-Dist: pylint ; extra == "dev"
38
+ Requires-Dist: pyright ; extra == "dev"
39
+ Requires-Dist: wheel ; extra == "dev"
40
+ Project-URL: Homepage, https://github.com/tinytag/tinytag
41
+ Provides-Extra: dev
42
+
1
43
  <!--
2
44
  SPDX-FileCopyrightText: 2014-2026 tinytag Contributors
3
45
  SPDX-License-Identifier: MIT
@@ -26,12 +68,13 @@ python3 -m pip install tinytag
26
68
 
27
69
  * Read tags, images and properties of audio files
28
70
  * Supported formats:
29
- * MP3 / MP2 / MP1 (ID3 v1, v1.1, v2.2, v2.3+)
30
- * M4A (AAC / ALAC)
71
+ * ID3 v1, v1.1, v2.2, v2.3, v2.4
72
+ * MP3 / MP2 / MP1
73
+ * MP4 (MPEG-4 Audio / AAC / ALAC)
31
74
  * WAVE / WAV
32
75
  * OGG (FLAC / Opus / Speex / Vorbis)
33
76
  * FLAC
34
- * WMA
77
+ * ASF (WMA)
35
78
  * AIFF / AIFF-C
36
79
  * Same API for all formats
37
80
  * Small, portable library
@@ -41,7 +84,8 @@ python3 -m pip install tinytag
41
84
 
42
85
  > [!IMPORTANT]
43
86
  > Support for changing/writing metadata will not be added. Use another library
44
- > such as [Mutagen](https://mutagen.readthedocs.io/) for this.
87
+ > such as [Mutagen](https://mutagen.readthedocs.io/) or [pytaglib](https://github.com/supermihi/pytaglib)
88
+ > for this.
45
89
 
46
90
 
47
91
  ## Usage
@@ -64,34 +108,40 @@ print(f'It is {tag.duration:.2f} seconds long.')
64
108
 
65
109
  Alternatively you can use tinytag directly on the command line:
66
110
 
67
- $ python3 -m tinytag /some/music.mp3
68
- {
69
- "filename": "/some/music.mp3",
70
- "filesize": 3243226,
71
- "duration": 173.52,
72
- "channels": 2,
73
- "bitrate": 128,
74
- "samplerate": 44100,
75
- "artist": [
76
- "artist name"
77
- ],
78
- "album": [
79
- "album name"
80
- ],
81
- "title": [
82
- "track name"
83
- ],
84
- "track": 4,
85
- "genre": [
86
- "Jazz"
87
- ],
88
- "year": [
89
- "2010"
90
- ],
91
- "comment": [
92
- "Some comment here"
93
- ]
94
- }
111
+ ```console
112
+ $ python3 -m tinytag /some/music.mp3
113
+ {
114
+ "filename": "/some/music.mp3",
115
+ "filesize": 3243226,
116
+ "mime_type": "audio/mpeg",
117
+ "is_lossless": false,
118
+ "duration": 173.52,
119
+ "channels": 2,
120
+ "bitrate": 128,
121
+ "samplerate": 44100,
122
+ "artist": [
123
+ "artist name"
124
+ ],
125
+ "album": [
126
+ "album name"
127
+ ],
128
+ "title": [
129
+ "track name"
130
+ ],
131
+ "track": [
132
+ "4"
133
+ ],
134
+ "genre": [
135
+ "Jazz"
136
+ ],
137
+ "year": [
138
+ "2010"
139
+ ],
140
+ "comment": [
141
+ "Some comment here"
142
+ ]
143
+ }
144
+ ```
95
145
 
96
146
  Check `python3 -m tinytag --help` for all CLI options, for example other
97
147
  output formats.
@@ -118,12 +168,17 @@ These are helpful when you need quick access to common metadata.
118
168
 
119
169
  #### File/Audio Properties
120
170
 
121
- tag.bitdepth # bit depth as integer (for lossless audio)
122
- tag.bitrate # bitrate in kBits/s as float
123
- tag.duration # audio duration in seconds as float
124
- tag.filename # filename as string
125
- tag.filesize # file size in bytes as integer
126
- tag.samplerate # samples per second as integer
171
+ ```python
172
+ tag.filename: str | None # file name
173
+ tag.filesize: int # file size in bytes
174
+ tag.bitdepth: int | None # audio bit depth
175
+ tag.bitrate: float | None # audio bitrate in kbps
176
+ tag.channels: int | None # number of audio channels
177
+ tag.duration: float | None # audio duration in seconds
178
+ tag.is_lossless: bool | None # is audio lossless? (added in tinytag 2.3.0)
179
+ tag.mime_type: str | None # audio MIME type (added in tinytag 2.3.0)
180
+ tag.samplerate: int | None # audio samples per second
181
+ ```
127
182
 
128
183
  > [!WARNING]
129
184
  > The `tag.audio_offset` attribute is obsolete as of tinytag 2.0.0, and will
@@ -131,25 +186,75 @@ These are helpful when you need quick access to common metadata.
131
186
 
132
187
  #### Metadata Fields
133
188
 
134
- tag.album # album as string
135
- tag.albumartist # album artist as string
136
- tag.artist # artist name as string
137
- tag.comment # file comment as string
138
- tag.composer # composer as string
139
- tag.disc # disc number as integer
140
- tag.disc_total # total number of discs as integer
141
- tag.genre # genre as string
142
- tag.title # title of the song as string
143
- tag.track # track number as integer
144
- tag.track_total # total number of tracks as integer
145
- tag.year # year or date as string
189
+ ```python
190
+ tag.album: str | None # album name
191
+ tag.albumartist: str | None # album artist name
192
+ tag.artist: str | None # artist name
193
+ tag.comment: str | None # file comment
194
+ tag.composer: str | None # composer name
195
+ tag.disc: int | None # disc number
196
+ tag.disc_total: int | None # total number of discs
197
+ tag.genre: str | None # genre
198
+ tag.title: str | None # title
199
+ tag.track: int | None # track number
200
+ tag.track_total: int | None # total number of tracks
201
+ tag.year: str | None # year/date
202
+ ```
203
+
204
+ #### Audio MIME Types
205
+
206
+ At present, tinytag may return the audio MIME types documented in this section.
207
+ When available, a `codecs` parameter as described in the [RFC 6381](https://www.rfc-editor.org/info/rfc6381)
208
+ standard is included.
209
+
210
+ For standard codec values, see:
211
+ * `audio/mp4`: [RFC 6381](https://www.rfc-editor.org/info/rfc6381)
212
+ * `audio/ogg`: [RFC 5334](https://www.rfc-editor.org/info/rfc5334)
213
+ and [RFC 7845](https://www.rfc-editor.org/info/rfc7845)
214
+ * `audio/wav`: [RFC 2361](https://www.rfc-editor.org/info/rfc2361)
215
+
216
+ No official standards exists for `codecs` values for the
217
+ `application/vnd.ms-asf` and `audio/aiff` MIME types. The most appropriate
218
+ value provided by the format is used.
219
+
220
+ # ASF
221
+ application/vnd.ms-asf
222
+ application/vnd.ms-asf; codecs="<1..>" # WAVE format tag, e.g. "161" (WMA)
223
+
224
+ # AIFF
225
+ audio/aiff
226
+ audio/aiff; codecs="<FourCC>" # AIFF-C compression type, e.g. "alaw"
227
+
228
+ # FLAC
229
+ audio/flac
230
+
231
+ # MP4
232
+ audio/mp4
233
+ audio/mp4; codecs="alac"
234
+ audio/mp4; codecs="mp4a.oo[.A]" # E.g. "mp4a.40.2" for AAC-LC
235
+
236
+ # MP3 / MP2 / MP1
237
+ audio/mpeg
238
+
239
+ # OGG
240
+ audio/ogg
241
+ audio/ogg; codecs="flac"
242
+ audio/ogg; codecs="opus"
243
+ audio/ogg; codecs="speex"
244
+ audio/ogg; codecs="vorbis"
245
+
246
+ # WAV
247
+ audio/wav
248
+ audio/wav; codecs="<1..>" # WAVE format tag, e.g. "1" for PCM
146
249
 
147
250
  ### Additional Metadata
148
251
 
149
252
  For additional values of the same field type, uncommon metadata fields, or
150
253
  metadata specific to certain file formats, use `other`:
151
254
 
152
- tag.other # a dictionary of additional fields
255
+ ```python
256
+ tag.other: OtherFields # a dictionary of additional fields
257
+ ```
153
258
 
154
259
  > [!WARNING]
155
260
  > The `other` dictionary has replaced the `extra` dictionary in tinytag 2.0.0.
@@ -182,6 +287,7 @@ present when files provide such metadata:
182
287
  show_movement
183
288
  url
184
289
  work
290
+ xmp
185
291
 
186
292
  Additional `other` field names not documented above may be present, but are
187
293
  format-specific and may change or disappear in future tinytag releases. If
@@ -214,8 +320,10 @@ print(catalog_numbers)
214
320
 
215
321
  Output:
216
322
 
217
- > 10
218
- > ['10']
323
+ ```console
324
+ > 10
325
+ > ['10']
326
+ ```
219
327
 
220
328
  When a file contains multiple values for a [common metadata field](#common-metadata)
221
329
  (e.g. `artist`), the primary value is accessed through the common attribute
@@ -237,8 +345,10 @@ print(additional_artists)
237
345
 
238
346
  Output:
239
347
 
240
- > main artist
241
- > ['another artist', 'yet another artist']
348
+ ```console
349
+ > main artist
350
+ > ['another artist', 'yet another artist']
351
+ ```
242
352
 
243
353
  ### All Metadata
244
354
 
@@ -246,10 +356,12 @@ If you need to receive all available metadata as key-value pairs in a flat
246
356
  dictionary, use the `as_dict()` method. This combines the common attributes
247
357
  and `other` dictionary, which can be more convenient in some cases.
248
358
 
249
- from tinytag import TinyTag
359
+ ```python
360
+ from tinytag import TinyTag
250
361
 
251
- tag: TinyTag = TinyTag.get('/some/music.mp3')
252
- metadata: dict = tag.as_dict()
362
+ tag: TinyTag = TinyTag.get('/some/music.mp3')
363
+ metadata: dict = tag.as_dict()
364
+ ```
253
365
 
254
366
  ### Images
255
367
 
@@ -259,14 +371,18 @@ keyword argument to `TinyTag.get()`.
259
371
  If you need to receive an image of a specific kind, including its description,
260
372
  use `images`:
261
373
 
262
- tag.images # available embedded images
374
+ ```python
375
+ tag.images: Images # available embedded images
376
+ ```
263
377
 
264
378
  The following common image attributes are available, providing the first
265
- located image of each kind:
379
+ located `Image` object of each kind:
266
380
 
267
- tag.images.front_cover # front cover as 'Image' object
268
- tag.images.back_cover # back cover as 'Image' object
269
- tag.images.media # media (e.g. CD label) as 'Image' object
381
+ ```python
382
+ tag.images.front_cover: Image # front cover
383
+ tag.images.back_cover: Image # back cover
384
+ tag.images.media: Image # media (e.g. CD label)
385
+ ```
270
386
 
271
387
  When present, any additional images are available in an `images.other`
272
388
  dictionary, using the following standardized key names:
@@ -298,10 +414,13 @@ Provided values are always lists containing at least one `Image` object.
298
414
 
299
415
  The `Image` object provides the following attributes:
300
416
 
301
- data # image data as bytes
302
- name # image name/kind as string
303
- mime_type # image MIME type as string
304
- description # image description as string
417
+ ```python
418
+ image.data: bytes # image data
419
+ image.size: int # image size in bytes (added in tinytag 2.3.0)
420
+ image.name: str # image name/kind
421
+ image.mime_type: str | None # image MIME type
422
+ image.description: str | None # image description
423
+ ```
305
424
 
306
425
  To receive any available image, prioritizing the front cover, use `images.any`:
307
426
 
@@ -313,11 +432,13 @@ image: Image | None = tag.images.any
313
432
 
314
433
  if image is not None:
315
434
  data: bytes = image.data
435
+ size: int = image.size
316
436
  name: str = image.name
317
- mime_type: str = image.mime_type
318
- description: str = image.description
437
+ mime_type: str | None = image.mime_type
438
+ description: str | None = image.description
319
439
 
320
440
  print(len(data))
441
+ print(size)
321
442
  print(name)
322
443
  print(mime_type)
323
444
  print(description)
@@ -325,10 +446,13 @@ if image is not None:
325
446
 
326
447
  Output:
327
448
 
328
- > 74452
329
- > front_cover
330
- > image/jpeg
331
- > some image description
449
+ ```console
450
+ > 74452
451
+ > 74452
452
+ > front_cover
453
+ > image/jpeg
454
+ > some image description
455
+ ```
332
456
 
333
457
  > [!WARNING]
334
458
  > `tag.images.any` has replaced `tag.get_image()` in tinytag 2.0.0.
@@ -345,7 +469,7 @@ cover_image: Image = images.front_cover
345
469
 
346
470
  if cover_image is not None:
347
471
  data: bytes = cover_image.data
348
- description: str = cover_image.description
472
+ description: str | None = cover_image.description
349
473
  ```
350
474
 
351
475
  To receive an additional image, e.g. `bright_colored_fish`:
@@ -363,6 +487,19 @@ if fish_images:
363
487
  description = image.description
364
488
  ```
365
489
 
490
+ ### Magic Byte Detection
491
+
492
+ By default, tinytag will determine the file type by 1. checking the file name
493
+ extension, and 2. reading and inspecting magic bytes in the file header.
494
+
495
+ In case you want to disable magic byte detection, e.g. to minimize read
496
+ operations when many non-audio files exist in a folder, pass a
497
+ `check_magic_bytes` argument with a value of `False` (added in tinytag 2.3.0).
498
+
499
+ ```python
500
+ tag: TinyTag = TinyTag.get('invalid_file.jpg', check_magic_bytes=False)
501
+ ```
502
+
366
503
  ### Encoding
367
504
 
368
505
  To open files using a specific encoding, you can use the `encoding` parameter.
@@ -370,7 +507,7 @@ This parameter is however only used for formats where the encoding is not
370
507
  explicitly specified.
371
508
 
372
509
  ```python
373
- TinyTag.get('a_file_with_gbk_encoding.mp3', encoding='gbk')
510
+ tag: TinyTag = TinyTag.get('a_file_with_gbk_encoding.mp3', encoding='gbk')
374
511
  ```
375
512
 
376
513
  ### File-like Objects
@@ -379,18 +516,66 @@ To use a file-like object (e.g. BytesIO) instead of a file path, pass a
379
516
  `file_obj` keyword argument:
380
517
 
381
518
  ```python
382
- TinyTag.get(file_obj=your_file_obj)
519
+ tag: TinyTag = TinyTag.get(file_obj=your_file_obj)
383
520
  ```
384
521
 
385
522
  ### Exceptions
386
523
 
387
- TinyTagException # Base class for exceptions
388
- ParseError # Parsing an audio file failed
389
- UnsupportedFormatError # File format is not supported
524
+ ```python
525
+ TinyTagException # Base class for exceptions
526
+ ParseError # Parsing an audio file failed
527
+ UnsupportedFormatError # File format is not supported
528
+ ```
390
529
 
391
530
 
392
531
  ## Changelog
393
532
 
533
+ ### 2.3.1 (2026-08-30)
534
+
535
+ - Don't open unrecognized files when disabling magic byte detection
536
+ - MPEG: Fix parsing of some files with incorrect headers
537
+ - OGG/WAV: Read sizes as little endian instead of native byte order
538
+
539
+ ### 2.3.0 (2026-07-31)
540
+
541
+ - Add 'mime_type' attribute for audio MIME type/codec
542
+ - Add 'is_lossless' attribute to indicate lossless audio
543
+ - Add 'size' attribute to images for size in bytes
544
+ - Add option to disable magic byte detection
545
+ - Make XMP metadata available under 'other.xmp' field
546
+ - Make bit depth available for lossy files providing it
547
+ - Add .asf, .ogv and .wmv to list of supported file extensions
548
+ - Mark deprecated 'extra' dictionary as obsolete
549
+ - Fix incorrect key when adding common images to 'other' dictionary
550
+ - Fix disc/track numbers not being returned as lists in 'as_dict()'
551
+ - Only set audio properties with a positive value
552
+ - Always read tags and audio properties in a single pass
553
+ - ID3: Parse multi-value text frames correctly
554
+ - ID3: Parse COMM and USLT frames correctly
555
+ - ID3: Fix some errors in parsed size calculations
556
+ - ID3: Exclude a few frames with custom structures
557
+ - MPEG: Read VBRI and Xing Info headers for duration/bitrate
558
+ - MPEG: Fix parsing of layer I and MPEG-2 layer III audio properties
559
+ - MPEG: Fix slightly incorrect duration estimation
560
+ - MPEG/MP4: Raise ParseError if header is invalid
561
+ - MP4: Add 'image/bmp' and 'image/gif' MIME types
562
+ - MP4: Fix infinite loop if size of certain sub-atoms is zero
563
+ - MP4: Fix incorrect parsing of descriptor size
564
+ - MP4: Don't read image data when image reading is disabled
565
+ - OGG: Parse multi-stream files correctly
566
+ - Speex: Don't read vendor string as comment
567
+ - FLAC: Provide actual audio bitrate instead of overall bitrate
568
+ - FLAC: Parse VORBIS_COMMENT and PICTURE blocks with invalid size
569
+ - FLAC: Ignore subsequent STREAMINFO blocks
570
+ - WAV: Include unknown fields in 'other' dictionary
571
+ - WAV: Calculate bitrate/duration correctly
572
+ - AIFF/WAV: Read whole ID3 chunk before parsing
573
+ - ASF: Support parsing additional metadata objects
574
+ - ASF: Stop parsing if object size is smaller than header
575
+ - ASF: Make magic header detection more strict
576
+ - Various performance improvements
577
+ - Various code refactors
578
+
394
579
  ### 2.2.1 (2026-03-15)
395
580
 
396
581
  - ID3: Prevent infinite loop due to malformed SYLT strings
@@ -602,6 +787,7 @@ TinyTag.get(file_obj=your_file_obj)
602
787
 
603
788
  - fixed decoding of UTF-16LE ID3v2 Tags, improved overall stability
604
789
 
605
- ### 0.14.0 (2016-06-05):
790
+ ### 0.14.0 (2016-06-05)
606
791
 
607
792
  - MP4/M4A and Opus support
793
+