Skip to content

Commit badcd22

Browse files
authored
Merge pull request #58 from jcassette/bitratemode
Add the properties bitrate_mode, encoder_info and encoder_settings
2 parents 055c490 + 989a548 commit badcd22

File tree

5 files changed

+100
-5
lines changed

5 files changed

+100
-5
lines changed

docs/conf.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
copyright = '2016, the beets project'
1818
author = 'the beets project'
1919

20-
version = '0.5'
21-
release = '0.5.0'
20+
version = '0.9'
21+
release = '0.9.0'
2222

2323
pygments_style = 'sphinx'
2424
htmlhelp_basename = 'mediafiledoc'

docs/index.rst

+7-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ The metadata schema is generally based on MusicBrainz' schema with similar namin
3030
* ``lyrics``, ``copyright``, ``url``
3131
* calculated metadata like ``bpm`` (beats per minute) and ``r128_track_gain`` (ReplayGain),
3232
* embedded images (e.g. album art),
33-
* file metadata like ``bitrate`` and ``length``.
33+
* file metadata like ``samplerate``, ``bitdepth``, ``channels``, ``bitrate``, ``bitrate_mode``, ``encoder_info``, ``encoder_settings`` and ``length``.
3434

3535
Compatibility
3636
-------------
@@ -135,6 +135,12 @@ To copy tags from one MediaFile to another:
135135
Changelog
136136
---------
137137
138+
v0.9.0
139+
''''''
140+
141+
- Add the properties ``bitrate_mode``, ``encoder_info`` and
142+
``encoder_settings``.
143+
138144
v0.8.1
139145
''''''
140146

mediafile.py

+40-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
import mutagen
3939
import mutagen.id3
40+
import mutagen.mp3
4041
import mutagen.mp4
4142
import mutagen.flac
4243
import mutagen.asf
@@ -58,7 +59,7 @@
5859
import traceback
5960

6061

61-
__version__ = '0.8.1'
62+
__version__ = '0.9.0'
6263
__all__ = ['UnreadableFileError', 'FileTypeError', 'MediaFile']
6364

6465
log = logging.getLogger(__name__)
@@ -1721,7 +1722,8 @@ def readable_fields(cls):
17211722
for property in cls.fields():
17221723
yield property
17231724
for property in ('length', 'samplerate', 'bitdepth', 'bitrate',
1724-
'channels', 'format'):
1725+
'bitrate_mode', 'channels', 'encoder_info',
1726+
'encoder_settings', 'format'):
17251727
yield property
17261728

17271729
@classmethod
@@ -2326,6 +2328,42 @@ def bitrate(self):
23262328
return 0
23272329
return int(self.filesize * 8 / self.length)
23282330

2331+
@property
2332+
def bitrate_mode(self):
2333+
"""The mode of the bitrate used in the audio coding
2334+
(a string, eg. "CBR", "VBR" or "ABR").
2335+
Only available for the MP3 file format (empty where unavailable).
2336+
"""
2337+
if hasattr(self.mgfile.info, 'bitrate_mode'):
2338+
return {
2339+
mutagen.mp3.BitrateMode.CBR: 'CBR',
2340+
mutagen.mp3.BitrateMode.VBR: 'VBR',
2341+
mutagen.mp3.BitrateMode.ABR: 'ABR',
2342+
}.get(self.mgfile.info.bitrate_mode, '')
2343+
else:
2344+
return ''
2345+
2346+
@property
2347+
def encoder_info(self):
2348+
"""The name and/or version of the encoder used
2349+
(a string, eg. "LAME 3.97.0").
2350+
Only available for some formats (empty where unavailable).
2351+
"""
2352+
if hasattr(self.mgfile.info, 'encoder_info'):
2353+
return self.mgfile.info.encoder_info
2354+
else:
2355+
return ''
2356+
2357+
@property
2358+
def encoder_settings(self):
2359+
"""A guess of the settings used for the encoder (a string, eg. "-V2").
2360+
Only available for the MP3 file format (empty where unavailable).
2361+
"""
2362+
if hasattr(self.mgfile.info, 'encoder_settings'):
2363+
return self.mgfile.info.encoder_settings
2364+
else:
2365+
return ''
2366+
23292367
@property
23302368
def format(self):
23312369
"""A string describing the file format/codec."""

test/rsrc/cbr.mp3

13 KB
Binary file not shown.

test/test_mediafile.py

+51
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,9 @@ class MP3Test(ReadWriteTestBase, PartialTestMixin,
761761
audio_properties = {
762762
'length': 1.0,
763763
'bitrate': 80000,
764+
'bitrate_mode': '',
765+
'encoder_info': '',
766+
'encoder_settings': '',
764767
'format': 'MP3',
765768
'samplerate': 44100,
766769
'bitdepth': 0,
@@ -771,13 +774,28 @@ def test_unknown_apic_type(self):
771774
mediafile = self._mediafile_fixture('image_unknown_type')
772775
self.assertEqual(mediafile.images[0].type, ImageType.other)
773776

777+
def test_bitrate_mode(self):
778+
mediafile = self._mediafile_fixture('cbr')
779+
self.assertEqual(mediafile.bitrate_mode, 'CBR')
780+
781+
def test_encoder_info(self):
782+
mediafile = self._mediafile_fixture('cbr')
783+
self.assertEqual(mediafile.encoder_info, 'LAME 3.100.0+')
784+
785+
def test_encoder_settings(self):
786+
mediafile = self._mediafile_fixture('cbr')
787+
self.assertEqual(mediafile.encoder_settings, '-b 80')
788+
774789

775790
class MP4Test(ReadWriteTestBase, PartialTestMixin,
776791
ImageStructureTestMixin, unittest.TestCase):
777792
extension = 'm4a'
778793
audio_properties = {
779794
'length': 1.0,
780795
'bitrate': 64000,
796+
'bitrate_mode': '',
797+
'encoder_info': '',
798+
'encoder_settings': '',
781799
'format': 'AAC',
782800
'samplerate': 44100,
783801
'bitdepth': 16,
@@ -799,6 +817,9 @@ class AlacTest(ReadWriteTestBase, unittest.TestCase):
799817
audio_properties = {
800818
'length': 1.0,
801819
'bitrate': 21830,
820+
'bitrate_mode': '',
821+
'encoder_info': '',
822+
'encoder_settings': '',
802823
# 'format': 'ALAC',
803824
'samplerate': 44100,
804825
'bitdepth': 16,
@@ -811,6 +832,9 @@ class MusepackTest(ReadWriteTestBase, unittest.TestCase):
811832
audio_properties = {
812833
'length': 1.0,
813834
'bitrate': 24023,
835+
'bitrate_mode': '',
836+
'encoder_info': '',
837+
'encoder_settings': '',
814838
'format': u'Musepack',
815839
'samplerate': 44100,
816840
'bitdepth': 0,
@@ -824,6 +848,9 @@ class WMATest(ReadWriteTestBase, ExtendedImageStructureTestMixin,
824848
audio_properties = {
825849
'length': 1.0,
826850
'bitrate': 128000,
851+
'bitrate_mode': '',
852+
'encoder_info': '',
853+
'encoder_settings': '',
827854
'format': u'Windows Media',
828855
'samplerate': 44100,
829856
'bitdepth': 0,
@@ -852,6 +879,9 @@ class OggTest(ReadWriteTestBase, ExtendedImageStructureTestMixin,
852879
audio_properties = {
853880
'length': 1.0,
854881
'bitrate': 48000,
882+
'bitrate_mode': '',
883+
'encoder_info': '',
884+
'encoder_settings': '',
855885
'format': u'OGG',
856886
'samplerate': 44100,
857887
'bitdepth': 0,
@@ -896,6 +926,9 @@ class FlacTest(ReadWriteTestBase, PartialTestMixin,
896926
audio_properties = {
897927
'length': 1.0,
898928
'bitrate': 108688,
929+
'bitrate_mode': '',
930+
'encoder_info': '',
931+
'encoder_settings': '',
899932
'format': u'FLAC',
900933
'samplerate': 44100,
901934
'bitdepth': 16,
@@ -909,6 +942,9 @@ class ApeTest(ReadWriteTestBase, ExtendedImageStructureTestMixin,
909942
audio_properties = {
910943
'length': 1.0,
911944
'bitrate': 112608,
945+
'bitrate_mode': '',
946+
'encoder_info': '',
947+
'encoder_settings': '',
912948
'format': u'APE',
913949
'samplerate': 44100,
914950
'bitdepth': 16,
@@ -921,6 +957,9 @@ class WavpackTest(ReadWriteTestBase, unittest.TestCase):
921957
audio_properties = {
922958
'length': 1.0,
923959
'bitrate': 109312,
960+
'bitrate_mode': '',
961+
'encoder_info': '',
962+
'encoder_settings': '',
924963
'format': u'WavPack',
925964
'samplerate': 44100,
926965
'bitdepth': 16 if mutagen.version >= (1, 45, 0) else 0,
@@ -933,6 +972,9 @@ class OpusTest(ReadWriteTestBase, unittest.TestCase):
933972
audio_properties = {
934973
'length': 1.0,
935974
'bitrate': 66792,
975+
'bitrate_mode': '',
976+
'encoder_info': '',
977+
'encoder_settings': '',
936978
'format': u'Opus',
937979
'samplerate': 48000,
938980
'bitdepth': 0,
@@ -945,6 +987,9 @@ class AIFFTest(ReadWriteTestBase, unittest.TestCase):
945987
audio_properties = {
946988
'length': 1.0,
947989
'bitrate': 705600,
990+
'bitrate_mode': '',
991+
'encoder_info': '',
992+
'encoder_settings': '',
948993
'format': u'AIFF',
949994
'samplerate': 44100,
950995
'bitdepth': 16,
@@ -957,6 +1002,9 @@ class WAVETest(ReadWriteTestBase, unittest.TestCase):
9571002
audio_properties = {
9581003
'length': 1.0,
9591004
'bitrate': 88200,
1005+
'bitrate_mode': '',
1006+
'encoder_info': '',
1007+
'encoder_settings': '',
9601008
'format': u'WAVE',
9611009
'samplerate': 44100,
9621010
'bitdepth': 16,
@@ -1033,6 +1081,9 @@ class DSFTest(ReadWriteTestBase, unittest.TestCase):
10331081
audio_properties = {
10341082
'length': 0.01,
10351083
'bitrate': 11289600,
1084+
'bitrate_mode': '',
1085+
'encoder_info': '',
1086+
'encoder_settings': '',
10361087
'format': u'DSD Stream File',
10371088
'samplerate': 5644800,
10381089
'bitdepth': 1,

0 commit comments

Comments
 (0)