From c2883a4d77454f39053629c491331d3872a60be3 Mon Sep 17 00:00:00 2001 From: Robert Goldmann <deadlocker@gmx.de> Date: Sun, 14 Jan 2024 00:06:51 +0100 Subject: [PATCH] added new class to convert wav to mp3, maximize volume and set mp3 tags --- Mp3Converter.py | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ poetry.lock | 13 +++++++++- pyproject.toml | 1 + 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 Mp3Converter.py diff --git a/Mp3Converter.py b/Mp3Converter.py new file mode 100644 index 0000000..a449398 --- /dev/null +++ b/Mp3Converter.py @@ -0,0 +1,68 @@ +import re +import subprocess + +from TheCodeLabs_BaseUtils.DefaultLogger import DefaultLogger +from mutagen.easyid3 import EasyID3 + +LOG_FORMAT = '[%(levelname)-7s] - %(asctime)s - %(message)s' +LOGGER = DefaultLogger().create_logger_if_not_exists('Mp3Converter', logFormat=LOG_FORMAT) + + +class Mp3Converter: + _PATTERN_MAX_VOLUME = re.compile(r'max_volume: ([-.\d+]*)\s') + + @staticmethod + def convert_to_mp3(inputFilePath: str, outputFilePath: str) -> None: + output = subprocess.check_output(['ffmpeg', + '-i', inputFilePath, + '-af', 'volumedetect', + '-vn', # ignore video streams + '-sn', # ignore subtitle streams + '-sn', # ignore data streams + '-hide_banner', # suppress unnecessary log messages + '-f', 'null', + 'NULL'], + stderr=subprocess.STDOUT) + output = output.decode('utf-8') + matches = re.findall(Mp3Converter._PATTERN_MAX_VOLUME, output) + detectedMaxVolume = None + if matches: + detectedMaxVolume = float(matches[0]) + LOGGER.debug(f'\t\tDetected max volume: {detectedMaxVolume}dB') + + arguments = ['ffmpeg', + '-i', inputFilePath, + '-y', # overwrite if already exists + '-hide_banner', # suppress unnecessary log messages + '-loglevel', 'error', + '-vn', # ignore video streams + '-sn', # ignore subtitle streams + '-sn', # ignore data streams + '-ac', '2', # 2 channels + '-b:a', '320k'] # 320k bitrate + + if detectedMaxVolume is not None and detectedMaxVolume < 0: + arguments.extend(['-filter:a', f'volume={abs(detectedMaxVolume)}dB']) # normalizes volume + + arguments.append(outputFilePath) + + LOGGER.info(f'\t\tRunning {" ".join(arguments)}') + subprocess.check_call(arguments) + + @staticmethod + def set_mp3_tags(filePath: str, title: str, artist: str, album: str) -> None: + LOGGER.info(f'\t\tSetting mp3 tags for "{filePath}"') + audio = EasyID3(filePath) + audio['title'] = title + audio['artist'] = artist + audio['album'] = album + audio.save() + + +if __name__ == '__main__': + Mp3Converter.convert_to_mp3('C:/Programmierung/SpotifyBackup/recorder/1 - Bignic - tetrapod.wav', + 'C:/Programmierung/SpotifyBackup/recorder/a.mp3') + Mp3Converter.set_mp3_tags('C:/Programmierung/SpotifyBackup/recorder/a.mp3', + title='Fancy Song', + artist='Various Artists', + album='Album #1') diff --git a/poetry.lock b/poetry.lock index b9c4de7..41b2cc8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -132,6 +132,17 @@ files = [ {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] +[[package]] +name = "mutagen" +version = "1.47.0" +description = "read and write audio tags for many formats" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mutagen-1.47.0-py3-none-any.whl", hash = "sha256:edd96f50c5907a9539d8e5bba7245f62c9f520aef333d13392a79a4f70aca719"}, + {file = "mutagen-1.47.0.tar.gz", hash = "sha256:719fadef0a978c31b4cf3c956261b3c58b6948b32023078a2117b1de09f0fc99"}, +] + [[package]] name = "psutil" version = "5.9.7" @@ -341,4 +352,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "a10c10003642c988271028a8a2a44227cae6123d1e05e4a66f3cb2dbab5a655a" +content-hash = "bb77de02b25207bf10249bf1370a69682b27ad88452311d42abc7d9830eb5494" diff --git a/pyproject.toml b/pyproject.toml index 58bc489..e35ccc9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ python = "^3.11" thecodelabs-baseutils = {version = "*", source = "TheCodeLabs" } spotipy = "2.22.0" PyAudioWPatch = "0.2.12.6" +mutagen = "1.47.0" [tool.poetry.dev-dependencies] -- GitLab