ffmpeg-normalize 1.37.8__tar.gz → 1.38.0__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.
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/PKG-INFO +3 -1
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/README.md +2 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/pyproject.toml +1 -1
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/__main__.py +4 -3
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/_media_file.py +31 -26
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/LICENSE.md +0 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/__init__.py +0 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/_cmd_utils.py +0 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/_errors.py +0 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/_ffmpeg_normalize.py +0 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/_logger.py +0 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/_presets.py +0 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/_streams.py +0 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/data/presets/music.json +0 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/data/presets/podcast.json +0 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/data/presets/streaming-video.json +0 -0
- {ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ffmpeg-normalize
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.38.0
|
|
4
4
|
Summary: Normalize audio via ffmpeg
|
|
5
5
|
Keywords: ffmpeg,normalize,audio
|
|
6
6
|
Author: Werner Robitza
|
|
@@ -64,6 +64,8 @@ This program normalizes media files to a certain loudness level using the EBU R1
|
|
|
64
64
|
|
|
65
65
|
## 🆕 What's New
|
|
66
66
|
|
|
67
|
+
- Version 1.38.0 writes the normalized output directly to the destination without using temporary files
|
|
68
|
+
|
|
67
69
|
- Version 1.36.0 introduces **presets** with `--preset`! Save and reuse your favorite normalization configurations for different use cases. Comes with three built-in presets: `podcast` (AES standard), `music` (RMS-based batch normalization), and `streaming-video` (video content). Create custom presets too!
|
|
68
70
|
|
|
69
71
|
Example:
|
|
@@ -33,6 +33,8 @@ This program normalizes media files to a certain loudness level using the EBU R1
|
|
|
33
33
|
|
|
34
34
|
## 🆕 What's New
|
|
35
35
|
|
|
36
|
+
- Version 1.38.0 writes the normalized output directly to the destination without using temporary files
|
|
37
|
+
|
|
36
38
|
- Version 1.36.0 introduces **presets** with `--preset`! Save and reuse your favorite normalization configurations for different use cases. Comes with three built-in presets: `podcast` (AES standard), `music` (RMS-based batch normalization), and `streaming-video` (video content). Create custom presets too!
|
|
37
39
|
|
|
38
40
|
Example:
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import argparse
|
|
4
|
+
|
|
5
|
+
# Import version from package
|
|
6
|
+
import importlib.metadata
|
|
4
7
|
import json
|
|
5
8
|
import logging
|
|
6
9
|
import os
|
|
@@ -15,9 +18,6 @@ from ._ffmpeg_normalize import NORMALIZATION_TYPES, FFmpegNormalize
|
|
|
15
18
|
from ._logger import setup_cli_logger
|
|
16
19
|
from ._presets import PresetManager
|
|
17
20
|
|
|
18
|
-
# Import version from package
|
|
19
|
-
import importlib.metadata
|
|
20
|
-
|
|
21
21
|
__version__ = importlib.metadata.version("ffmpeg-normalize")
|
|
22
22
|
|
|
23
23
|
_logger = logging.getLogger(__name__)
|
|
@@ -42,6 +42,7 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
42
42
|
- `TMP` / `TEMP` / `TMPDIR`
|
|
43
43
|
Sets the path to the temporary directory in which files are
|
|
44
44
|
stored before being moved to the final output directory.
|
|
45
|
+
Only valid for ReplayGain and when the input file == output file.
|
|
45
46
|
Note: You need to use full paths.
|
|
46
47
|
|
|
47
48
|
- `FFMPEG_PATH`
|
|
@@ -4,8 +4,8 @@ import logging
|
|
|
4
4
|
import os
|
|
5
5
|
import re
|
|
6
6
|
import shlex
|
|
7
|
-
from shutil import
|
|
8
|
-
from tempfile import mkdtemp
|
|
7
|
+
from shutil import rmtree
|
|
8
|
+
from tempfile import mkdtemp, mkstemp
|
|
9
9
|
from typing import TYPE_CHECKING, Iterable, Iterator, Literal, TypedDict, Union
|
|
10
10
|
|
|
11
11
|
from mutagen.id3 import ID3, TXXX
|
|
@@ -297,14 +297,14 @@ class MediaFile:
|
|
|
297
297
|
f"Batch mode: Skipping first pass (already completed), using batch reference = {batch_reference:.2f}"
|
|
298
298
|
)
|
|
299
299
|
|
|
300
|
-
|
|
301
|
-
temp_dir = mkdtemp()
|
|
302
|
-
self.temp_file = os.path.join(temp_dir, f"out.{self.output_ext}")
|
|
300
|
+
temp_dir = None
|
|
303
301
|
|
|
304
302
|
if self.ffmpeg_normalize.replaygain:
|
|
305
303
|
_logger.debug(
|
|
306
304
|
"ReplayGain mode: Second pass will run with temporary file to get stats."
|
|
307
305
|
)
|
|
306
|
+
temp_dir = mkdtemp()
|
|
307
|
+
self.temp_file = os.path.join(temp_dir, f"out.{self.output_ext}")
|
|
308
308
|
self.output_file = self.temp_file
|
|
309
309
|
|
|
310
310
|
# run the second pass as a whole.
|
|
@@ -322,7 +322,7 @@ class MediaFile:
|
|
|
322
322
|
pass
|
|
323
323
|
|
|
324
324
|
# remove temp dir; this will remove the temp file as well if it has not been renamed (e.g. for replaygain)
|
|
325
|
-
if os.path.exists(temp_dir):
|
|
325
|
+
if temp_dir and os.path.exists(temp_dir):
|
|
326
326
|
rmtree(temp_dir, ignore_errors=True)
|
|
327
327
|
|
|
328
328
|
# This will use stats from ebu_pass2 if available (from the main second pass),
|
|
@@ -836,39 +836,44 @@ class MediaFile:
|
|
|
836
836
|
yield 100
|
|
837
837
|
return
|
|
838
838
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
839
|
+
is_in_place_overwrite = os.path.realpath(self.input_file) == os.path.realpath(
|
|
840
|
+
self.output_file
|
|
841
|
+
)
|
|
842
842
|
|
|
843
|
-
|
|
844
|
-
if
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
temp_file =
|
|
843
|
+
temp_file: Union[str, None] = None
|
|
844
|
+
if is_in_place_overwrite:
|
|
845
|
+
# need to create a temporary file because we cannot override
|
|
846
|
+
# the same input file
|
|
847
|
+
output_dir = os.path.dirname(self.output_file) or "."
|
|
848
|
+
fd, temp_file = mkstemp(
|
|
849
|
+
suffix=f".{self.output_ext}",
|
|
850
|
+
prefix=f".{os.path.splitext(os.path.basename(self.output_file))[0]}.",
|
|
851
|
+
dir=output_dir,
|
|
852
|
+
)
|
|
853
|
+
os.close(fd)
|
|
854
|
+
_logger.debug(
|
|
855
|
+
f"Output file is the same as the input file, "
|
|
856
|
+
f"encoding to temporary file {temp_file} first"
|
|
857
|
+
)
|
|
849
858
|
cmd.append(temp_file)
|
|
859
|
+
else:
|
|
860
|
+
cmd.append(self.output_file)
|
|
850
861
|
|
|
851
862
|
cmd_runner = CommandRunner()
|
|
852
863
|
try:
|
|
853
864
|
yield from cmd_runner.run_ffmpeg_command(cmd)
|
|
854
865
|
except Exception as e:
|
|
855
866
|
_logger.error(f"Error while running command {shlex.join(cmd)}! Error: {e}")
|
|
867
|
+
if temp_file and os.path.exists(temp_file):
|
|
868
|
+
os.remove(temp_file)
|
|
856
869
|
raise e
|
|
857
870
|
else:
|
|
858
|
-
#
|
|
859
|
-
if
|
|
860
|
-
self.output_file != os.devnull
|
|
861
|
-
and temp_file
|
|
862
|
-
and not self.ffmpeg_normalize.replaygain
|
|
863
|
-
):
|
|
871
|
+
# for in-place normalization, move the finished temp file over the input
|
|
872
|
+
if temp_file:
|
|
864
873
|
_logger.debug(
|
|
865
874
|
f"Moving temporary file from {temp_file} to {self.output_file}"
|
|
866
875
|
)
|
|
867
|
-
|
|
868
|
-
finally:
|
|
869
|
-
# clean up temp directory if it was created
|
|
870
|
-
if temp_dir and os.path.exists(temp_dir):
|
|
871
|
-
rmtree(temp_dir, ignore_errors=True)
|
|
876
|
+
os.replace(temp_file, self.output_file)
|
|
872
877
|
|
|
873
878
|
output = cmd_runner.get_output()
|
|
874
879
|
# in the second pass, we do not normalize stream-by-stream, so we set the stats based on the
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/_ffmpeg_normalize.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/data/presets/music.json
RENAMED
|
File without changes
|
{ffmpeg_normalize-1.37.8 → ffmpeg_normalize-1.38.0}/src/ffmpeg_normalize/data/presets/podcast.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|