ffmpeg-normalize 1.37.2__tar.gz → 1.37.3__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.2 → ffmpeg_normalize-1.37.3}/PKG-INFO +1 -1
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/pyproject.toml +1 -1
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/__main__.py +1 -1
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/_media_file.py +101 -2
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/LICENSE.md +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/README.md +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/__init__.py +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/_cmd_utils.py +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/_errors.py +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/_ffmpeg_normalize.py +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/_logger.py +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/_presets.py +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/_streams.py +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/data/presets/music.json +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/data/presets/podcast.json +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/data/presets/streaming-video.json +0 -0
- {ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/py.typed +0 -0
|
@@ -197,7 +197,7 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
197
197
|
help=textwrap.dedent(
|
|
198
198
|
"""\
|
|
199
199
|
Write ReplayGain tags to the original file without normalizing.
|
|
200
|
-
This mode will overwrite the input file and ignore other options.
|
|
200
|
+
This mode will overwrite the input file and ignore other options. It will strip all ReplayGain tags.
|
|
201
201
|
Only works with EBU normalization, and only with .mp3, .mp4/.m4a, .ogg, .opus for now.
|
|
202
202
|
"""
|
|
203
203
|
),
|
|
@@ -332,8 +332,10 @@ class MediaFile:
|
|
|
332
332
|
"ReplayGain tagging is enabled. Proceeding with tag calculation/application."
|
|
333
333
|
)
|
|
334
334
|
self._run_replaygain()
|
|
335
|
-
|
|
336
|
-
|
|
335
|
+
else:
|
|
336
|
+
# Strip any existing ReplayGain tags from the output file
|
|
337
|
+
# since they are no longer accurate after normalization
|
|
338
|
+
self._strip_replaygain_tags(self.output_file)
|
|
337
339
|
_logger.info(f"Normalized file written to {self.output_file}")
|
|
338
340
|
|
|
339
341
|
def _run_replaygain(self) -> None:
|
|
@@ -461,6 +463,103 @@ class MediaFile:
|
|
|
461
463
|
f"Successfully wrote replaygain tags to input file {self.input_file}"
|
|
462
464
|
)
|
|
463
465
|
|
|
466
|
+
def _strip_replaygain_tags(self, output_file: str) -> None:
|
|
467
|
+
"""
|
|
468
|
+
Strip ReplayGain tags from the output file after normalization.
|
|
469
|
+
|
|
470
|
+
This ensures that old ReplayGain tags from the input are removed,
|
|
471
|
+
since they are no longer accurate after normalization.
|
|
472
|
+
|
|
473
|
+
Args:
|
|
474
|
+
output_file (str): Path to the output file to strip tags from
|
|
475
|
+
"""
|
|
476
|
+
_logger.debug(f"Stripping ReplayGain tags from {output_file}")
|
|
477
|
+
|
|
478
|
+
output_file_ext = os.path.splitext(output_file)[1]
|
|
479
|
+
if output_file_ext == ".mp3":
|
|
480
|
+
try:
|
|
481
|
+
mp3 = MP3(output_file, ID3=ID3)
|
|
482
|
+
if not mp3.tags:
|
|
483
|
+
return
|
|
484
|
+
# Remove REPLAYGAIN_* tags
|
|
485
|
+
tags_to_remove = [
|
|
486
|
+
key for key in mp3.tags if key.startswith("TXXX:REPLAYGAIN_")
|
|
487
|
+
]
|
|
488
|
+
for tag in tags_to_remove:
|
|
489
|
+
del mp3.tags[tag]
|
|
490
|
+
if tags_to_remove:
|
|
491
|
+
mp3.save()
|
|
492
|
+
_logger.debug(
|
|
493
|
+
f"Stripped {len(tags_to_remove)} ReplayGain tag(s) from {output_file}"
|
|
494
|
+
)
|
|
495
|
+
except Exception as e:
|
|
496
|
+
_logger.warning(
|
|
497
|
+
f"Could not strip ReplayGain tags from {output_file}: {e}"
|
|
498
|
+
)
|
|
499
|
+
elif output_file_ext in [".mp4", ".m4a", ".m4v", ".mov"]:
|
|
500
|
+
try:
|
|
501
|
+
mp4 = MP4(output_file)
|
|
502
|
+
if not mp4.tags:
|
|
503
|
+
return
|
|
504
|
+
# Remove REPLAYGAIN_* tags
|
|
505
|
+
tags_to_remove = [
|
|
506
|
+
key
|
|
507
|
+
for key in mp4.tags
|
|
508
|
+
if "REPLAYGAIN_" in key.upper() or "REPLAYGAIN" in key.upper()
|
|
509
|
+
]
|
|
510
|
+
for tag in tags_to_remove:
|
|
511
|
+
del mp4.tags[tag]
|
|
512
|
+
if tags_to_remove:
|
|
513
|
+
mp4.save()
|
|
514
|
+
_logger.debug(
|
|
515
|
+
f"Stripped {len(tags_to_remove)} ReplayGain tag(s) from {output_file}"
|
|
516
|
+
)
|
|
517
|
+
except Exception as e:
|
|
518
|
+
_logger.warning(
|
|
519
|
+
f"Could not strip ReplayGain tags from {output_file}: {e}"
|
|
520
|
+
)
|
|
521
|
+
elif output_file_ext == ".ogg":
|
|
522
|
+
try:
|
|
523
|
+
ogg = OggVorbis(output_file)
|
|
524
|
+
# Remove REPLAYGAIN_* tags (case-insensitive)
|
|
525
|
+
tags_to_remove = [
|
|
526
|
+
key for key in ogg.keys() if key.upper().startswith("REPLAYGAIN_")
|
|
527
|
+
]
|
|
528
|
+
for tag in tags_to_remove:
|
|
529
|
+
del ogg[tag]
|
|
530
|
+
if tags_to_remove:
|
|
531
|
+
ogg.save()
|
|
532
|
+
_logger.debug(
|
|
533
|
+
f"Stripped {len(tags_to_remove)} ReplayGain tag(s) from {output_file}"
|
|
534
|
+
)
|
|
535
|
+
except Exception as e:
|
|
536
|
+
_logger.warning(
|
|
537
|
+
f"Could not strip ReplayGain tags from {output_file}: {e}"
|
|
538
|
+
)
|
|
539
|
+
elif output_file_ext == ".opus":
|
|
540
|
+
try:
|
|
541
|
+
opus = OggOpus(output_file)
|
|
542
|
+
# Remove R128_* tags (Opus uses R128 instead of REPLAYGAIN, case-insensitive)
|
|
543
|
+
tags_to_remove = [
|
|
544
|
+
key for key in opus.keys() if key.upper().startswith("R128_")
|
|
545
|
+
]
|
|
546
|
+
for tag in tags_to_remove:
|
|
547
|
+
del opus[tag]
|
|
548
|
+
if tags_to_remove:
|
|
549
|
+
opus.save()
|
|
550
|
+
_logger.debug(
|
|
551
|
+
f"Stripped {len(tags_to_remove)} R128 tag(s) from {output_file}"
|
|
552
|
+
)
|
|
553
|
+
except Exception as e:
|
|
554
|
+
_logger.warning(
|
|
555
|
+
f"Could not strip ReplayGain tags from {output_file}: {e}"
|
|
556
|
+
)
|
|
557
|
+
else:
|
|
558
|
+
# For other formats, we don't need to strip tags
|
|
559
|
+
_logger.debug(
|
|
560
|
+
f"Skipping ReplayGain tag stripping for {output_file_ext} (not supported/needed)"
|
|
561
|
+
)
|
|
562
|
+
|
|
464
563
|
def _can_write_output_video(self) -> bool:
|
|
465
564
|
"""
|
|
466
565
|
Determine whether the output file can contain video at all.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/_ffmpeg_normalize.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/data/presets/music.json
RENAMED
|
File without changes
|
{ffmpeg_normalize-1.37.2 → ffmpeg_normalize-1.37.3}/src/ffmpeg_normalize/data/presets/podcast.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|