ffmpeg-normalize 1.32.3__py2.py3-none-any.whl → 1.32.4__py2.py3-none-any.whl

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.
@@ -63,7 +63,7 @@ class FFmpegNormalize:
63
63
  lower_only (bool, optional): Whether the audio should not increase in loudness. Defaults to False.
64
64
  auto_lower_loudness_target (bool, optional): Automatically lower EBU Integrated Loudness Target.
65
65
  dual_mono (bool, optional): Dual mono. Defaults to False.
66
- dynamic (bool, optional): Dynamic. Defaults to False.
66
+ dynamic (bool, optional): Use dynamic EBU R128 normalization. This is a one-pass algorithm and skips the initial media scan. Defaults to False.
67
67
  audio_codec (str, optional): Audio codec. Defaults to "pcm_s16le".
68
68
  audio_bitrate (float, optional): Audio bitrate. Defaults to None.
69
69
  sample_rate (int, optional): Sample rate. Defaults to None.
@@ -207,8 +207,16 @@ class MediaFile:
207
207
  """
208
208
  _logger.debug(f"Running normalization for {self.input_file}")
209
209
 
210
- # run the first pass to get loudness stats
211
- self._first_pass()
210
+ # run the first pass to get loudness stats, unless in dynamic EBU mode
211
+ if not (
212
+ self.ffmpeg_normalize.dynamic
213
+ and self.ffmpeg_normalize.normalization_type == "ebu"
214
+ ):
215
+ self._first_pass()
216
+ else:
217
+ _logger.debug(
218
+ "Dynamic EBU mode: First pass will not run, as it is not needed."
219
+ )
212
220
 
213
221
  # for second pass, create a temp file
214
222
  temp_dir = mkdtemp()
@@ -616,7 +624,7 @@ class MediaFile:
616
624
  raise e
617
625
  else:
618
626
  # only move the temp file if it's not a null device and ReplayGain is not enabled!
619
- if self.output_file != os.devnull and not self.ffmpeg_normalize.replaygain:
627
+ if self.output_file != os.devnull and temp_file and not self.ffmpeg_normalize.replaygain:
620
628
  _logger.debug(
621
629
  f"Moving temporary file from {temp_file} to {self.output_file}"
622
630
  )
@@ -428,6 +428,28 @@ class AudioStream(MediaStream):
428
428
  Return second pass loudnorm filter options string for ffmpeg
429
429
  """
430
430
 
431
+ # In dynamic mode, we can do everything in one pass, and we do not have first pass stats
432
+ if self.media_file.ffmpeg_normalize.dynamic:
433
+ if not self.ffmpeg_normalize.sample_rate:
434
+ _logger.warning(
435
+ "In dynamic mode, the sample rate will automatically be set to 192 kHz by the loudnorm filter. "
436
+ "Specify -ar/--sample-rate to override it."
437
+ )
438
+
439
+ opts = {
440
+ "i": self.media_file.ffmpeg_normalize.target_level,
441
+ "lra": self.media_file.ffmpeg_normalize.loudness_range_target,
442
+ "tp": self.media_file.ffmpeg_normalize.true_peak,
443
+ "offset": self.media_file.ffmpeg_normalize.offset,
444
+ "linear": "false",
445
+ "print_format": "json",
446
+ }
447
+
448
+ if self.media_file.ffmpeg_normalize.dual_mono:
449
+ opts["dual_mono"] = "true"
450
+
451
+ return "loudnorm=" + dict_to_filter_opts(opts)
452
+
431
453
  if not self.loudness_statistics["ebu_pass1"]:
432
454
  raise FFmpegNormalizeError(
433
455
  "First pass not run, you must call parse_loudnorm_stats first"
@@ -1 +1 @@
1
- __version__ = "1.32.3"
1
+ __version__ = "1.32.4"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ffmpeg_normalize
3
- Version: 1.32.3
3
+ Version: 1.32.4
4
4
  Summary: Normalize audio via ffmpeg
5
5
  Home-page: https://github.com/slhck/ffmpeg-normalize
6
6
  Author: Werner Robitza
@@ -57,7 +57,7 @@ This program normalizes media files to a certain loudness level using the EBU R1
57
57
 
58
58
  ## ✨ Features
59
59
 
60
- - EBU R128 loudness normalization
60
+ - EBU R128 loudness normalization (two-pass by default, with an option for one-pass dynamic normalization)
61
61
  - RMS-based normalization
62
62
  - Peak normalization
63
63
  - Video file support
@@ -131,6 +131,17 @@ The only reason this project exists in its current form is because [@benjaoming]
131
131
  # Changelog
132
132
 
133
133
 
134
+ ## v1.32.4 (2025-06-08)
135
+
136
+ * Update api docs.
137
+
138
+ * Update docs.
139
+
140
+ * Make --dynamic option use one pass only, fixes #263.
141
+
142
+ * Fix type error.
143
+
144
+
134
145
  ## v1.32.3 (2025-05-30)
135
146
 
136
147
  * Fix temp dir cleanup, fixes #284.
@@ -0,0 +1,16 @@
1
+ ffmpeg_normalize/__init__.py,sha256=aAhlk93ZE6SQcWUDzZQcw9vJh0bJcKEUNFGhVc5ZIto,453
2
+ ffmpeg_normalize/__main__.py,sha256=LMj4Xl140ZKe5naY36fAwzz72lK59srzkVlbb0KzkcQ,19955
3
+ ffmpeg_normalize/_cmd_utils.py,sha256=iGzO3iOylDUOnx-FCKd84BMxiIhmIthxU1tg7kvf4Ss,5269
4
+ ffmpeg_normalize/_errors.py,sha256=brTQ4osJ4fTA8wnyMPVVYfGwJ0wqeShRFydTEwi_VEY,48
5
+ ffmpeg_normalize/_ffmpeg_normalize.py,sha256=_ZK2P3kAM0mnxY3iCYH61T6jhMndTdO2Rqh03vJo7rY,11852
6
+ ffmpeg_normalize/_logger.py,sha256=3Ap4Fxg7xGrzz7h4IGuNEf0KKstx0Rq_eLbHPrHzcrI,1841
7
+ ffmpeg_normalize/_media_file.py,sha256=6QYGIlNFpxojYjof_3y1HoU8SgsVnMor2y4hx-22CVY,26323
8
+ ffmpeg_normalize/_streams.py,sha256=tg4D5UMBFpPFxK5x-HG6mwgqkm9Z6H1kH14OlaCXM-A,21590
9
+ ffmpeg_normalize/_version.py,sha256=kVLezpNpKw6uZIvSwisQSFv3H0SHTGxoH32YSRqVSpQ,23
10
+ ffmpeg_normalize/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ ffmpeg_normalize-1.32.4.dist-info/licenses/LICENSE,sha256=mw5RQE6v4UXG_d2gYIQw9rq6jYWQCtzIs3fSm5sBSrs,1076
12
+ ffmpeg_normalize-1.32.4.dist-info/METADATA,sha256=kEvnRedCUL1slT6bbN7m--Hhpgw7yvixyrULe-f2MPQ,33285
13
+ ffmpeg_normalize-1.32.4.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
14
+ ffmpeg_normalize-1.32.4.dist-info/entry_points.txt,sha256=X0EC5ptb0iGOxrk3Aa65dVQtvUixngLd_2-iAtSixdc,68
15
+ ffmpeg_normalize-1.32.4.dist-info/top_level.txt,sha256=wnUkr17ckPrrU1JsxZQiXbEBUnHKsC64yck-MemEBuI,17
16
+ ffmpeg_normalize-1.32.4.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- ffmpeg_normalize/__init__.py,sha256=aAhlk93ZE6SQcWUDzZQcw9vJh0bJcKEUNFGhVc5ZIto,453
2
- ffmpeg_normalize/__main__.py,sha256=LMj4Xl140ZKe5naY36fAwzz72lK59srzkVlbb0KzkcQ,19955
3
- ffmpeg_normalize/_cmd_utils.py,sha256=iGzO3iOylDUOnx-FCKd84BMxiIhmIthxU1tg7kvf4Ss,5269
4
- ffmpeg_normalize/_errors.py,sha256=brTQ4osJ4fTA8wnyMPVVYfGwJ0wqeShRFydTEwi_VEY,48
5
- ffmpeg_normalize/_ffmpeg_normalize.py,sha256=79wzFR4ZOgy-Wn0ywi8PNJzsrxiDSMKtJ6_auHxiQvo,11762
6
- ffmpeg_normalize/_logger.py,sha256=3Ap4Fxg7xGrzz7h4IGuNEf0KKstx0Rq_eLbHPrHzcrI,1841
7
- ffmpeg_normalize/_media_file.py,sha256=Nq99uIWNzYEIJvqtMdLSTheCfPuEz9RUI2TmOj5JTeY,26004
8
- ffmpeg_normalize/_streams.py,sha256=w-gzAFUbnoLiRABckUgYqdhVgidtEATNd3di-jiP9fU,20599
9
- ffmpeg_normalize/_version.py,sha256=sJB5QegETJ0pJBZy1_Y8qTpWDV41DuNG3trAjwSVFas,23
10
- ffmpeg_normalize/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- ffmpeg_normalize-1.32.3.dist-info/licenses/LICENSE,sha256=mw5RQE6v4UXG_d2gYIQw9rq6jYWQCtzIs3fSm5sBSrs,1076
12
- ffmpeg_normalize-1.32.3.dist-info/METADATA,sha256=bWM7-_Ni3SAZ_sw6Yve2EuKSBFsl96eoQPZWtLs8z9A,33075
13
- ffmpeg_normalize-1.32.3.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
14
- ffmpeg_normalize-1.32.3.dist-info/entry_points.txt,sha256=X0EC5ptb0iGOxrk3Aa65dVQtvUixngLd_2-iAtSixdc,68
15
- ffmpeg_normalize-1.32.3.dist-info/top_level.txt,sha256=wnUkr17ckPrrU1JsxZQiXbEBUnHKsC64yck-MemEBuI,17
16
- ffmpeg_normalize-1.32.3.dist-info/RECORD,,