ffmpeg-normalize 1.33.4__py3-none-any.whl → 1.34.0__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.
- ffmpeg_normalize/__main__.py +53 -0
- ffmpeg_normalize/_ffmpeg_normalize.py +24 -0
- ffmpeg_normalize/_media_file.py +127 -20
- ffmpeg_normalize/_streams.py +3 -0
- {ffmpeg_normalize-1.33.4.dist-info → ffmpeg_normalize-1.34.0.dist-info}/METADATA +2 -2
- ffmpeg_normalize-1.34.0.dist-info/RECORD +14 -0
- {ffmpeg_normalize-1.33.4.dist-info → ffmpeg_normalize-1.34.0.dist-info}/WHEEL +1 -1
- ffmpeg_normalize-1.33.4.dist-info/RECORD +0 -14
- {ffmpeg_normalize-1.33.4.dist-info → ffmpeg_normalize-1.34.0.dist-info}/entry_points.txt +0 -0
- {ffmpeg_normalize-1.33.4.dist-info → ffmpeg_normalize-1.34.0.dist-info}/licenses/LICENSE.md +0 -0
ffmpeg_normalize/__main__.py
CHANGED
|
@@ -315,6 +315,44 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
315
315
|
),
|
|
316
316
|
)
|
|
317
317
|
|
|
318
|
+
group_stream_selection = parser.add_argument_group("Audio Stream Selection")
|
|
319
|
+
group_stream_selection.add_argument(
|
|
320
|
+
"-as",
|
|
321
|
+
"--audio-streams",
|
|
322
|
+
type=str,
|
|
323
|
+
help=textwrap.dedent(
|
|
324
|
+
"""\
|
|
325
|
+
Select specific audio streams to normalize by stream index (comma-separated).
|
|
326
|
+
Example: --audio-streams 0,2 will normalize only streams 0 and 2.
|
|
327
|
+
|
|
328
|
+
By default, all audio streams are normalized.
|
|
329
|
+
"""
|
|
330
|
+
),
|
|
331
|
+
)
|
|
332
|
+
group_stream_selection.add_argument(
|
|
333
|
+
"--audio-default-only",
|
|
334
|
+
action="store_true",
|
|
335
|
+
help=textwrap.dedent(
|
|
336
|
+
"""\
|
|
337
|
+
Only normalize audio streams with the 'default' disposition flag.
|
|
338
|
+
This is useful for files with multiple audio tracks where only the main track
|
|
339
|
+
should be normalized (e.g., keeping commentary tracks unchanged).
|
|
340
|
+
"""
|
|
341
|
+
),
|
|
342
|
+
)
|
|
343
|
+
group_stream_selection.add_argument(
|
|
344
|
+
"--keep-other-audio",
|
|
345
|
+
action="store_true",
|
|
346
|
+
help=textwrap.dedent(
|
|
347
|
+
"""\
|
|
348
|
+
Keep non-selected audio streams in the output file (copy without normalization).
|
|
349
|
+
Only applies when --audio-streams or --audio-default-only is used.
|
|
350
|
+
|
|
351
|
+
By default, only selected streams are included in the output.
|
|
352
|
+
"""
|
|
353
|
+
),
|
|
354
|
+
)
|
|
355
|
+
|
|
318
356
|
group_acodec = parser.add_argument_group("Audio Encoding")
|
|
319
357
|
group_acodec.add_argument(
|
|
320
358
|
"-c:a",
|
|
@@ -553,6 +591,18 @@ def main() -> None:
|
|
|
553
591
|
extra_input_options = _split_options(cli_args.extra_input_options)
|
|
554
592
|
extra_output_options = _split_options(cli_args.extra_output_options)
|
|
555
593
|
|
|
594
|
+
# parse audio streams selection
|
|
595
|
+
audio_streams = None
|
|
596
|
+
if cli_args.audio_streams:
|
|
597
|
+
try:
|
|
598
|
+
audio_streams = [int(s.strip()) for s in cli_args.audio_streams.split(",")]
|
|
599
|
+
except ValueError:
|
|
600
|
+
error("Invalid audio stream indices. Must be comma-separated integers.")
|
|
601
|
+
|
|
602
|
+
# validate stream selection options
|
|
603
|
+
if cli_args.audio_default_only and cli_args.audio_streams:
|
|
604
|
+
error("Cannot use both --audio-default-only and --audio-streams together.")
|
|
605
|
+
|
|
556
606
|
ffmpeg_normalize = FFmpegNormalize(
|
|
557
607
|
normalization_type=cli_args.normalization_type,
|
|
558
608
|
target_level=cli_args.target_level,
|
|
@@ -586,6 +636,9 @@ def main() -> None:
|
|
|
586
636
|
dry_run=cli_args.dry_run,
|
|
587
637
|
progress=cli_args.progress,
|
|
588
638
|
replaygain=cli_args.replaygain,
|
|
639
|
+
audio_streams=audio_streams,
|
|
640
|
+
audio_default_only=cli_args.audio_default_only,
|
|
641
|
+
keep_other_audio=cli_args.keep_other_audio,
|
|
589
642
|
)
|
|
590
643
|
|
|
591
644
|
if cli_args.output and len(cli_args.input) > len(cli_args.output):
|
|
@@ -84,6 +84,9 @@ class FFmpegNormalize:
|
|
|
84
84
|
debug (bool, optional): Debug. Defaults to False.
|
|
85
85
|
progress (bool, optional): Progress. Defaults to False.
|
|
86
86
|
replaygain (bool, optional): Write ReplayGain tags without normalizing. Defaults to False.
|
|
87
|
+
audio_streams (list[int] | None, optional): List of audio stream indices to normalize. Defaults to None (all streams).
|
|
88
|
+
audio_default_only (bool, optional): Only normalize audio streams with default disposition. Defaults to False.
|
|
89
|
+
keep_other_audio (bool, optional): Keep non-selected audio streams in output (copy without normalization). Defaults to False.
|
|
87
90
|
|
|
88
91
|
Raises:
|
|
89
92
|
FFmpegNormalizeError: If the ffmpeg executable is not found or does not support the loudnorm filter.
|
|
@@ -124,6 +127,9 @@ class FFmpegNormalize:
|
|
|
124
127
|
debug: bool = False,
|
|
125
128
|
progress: bool = False,
|
|
126
129
|
replaygain: bool = False,
|
|
130
|
+
audio_streams: list[int] | None = None,
|
|
131
|
+
audio_default_only: bool = False,
|
|
132
|
+
keep_other_audio: bool = False,
|
|
127
133
|
):
|
|
128
134
|
self.ffmpeg_exe = get_ffmpeg_exe()
|
|
129
135
|
self.has_loudnorm_capabilities = ffmpeg_has_loudnorm()
|
|
@@ -207,6 +213,11 @@ class FFmpegNormalize:
|
|
|
207
213
|
self.progress = progress
|
|
208
214
|
self.replaygain = replaygain
|
|
209
215
|
|
|
216
|
+
# Stream selection options
|
|
217
|
+
self.audio_streams = audio_streams
|
|
218
|
+
self.audio_default_only = audio_default_only
|
|
219
|
+
self.keep_other_audio = keep_other_audio
|
|
220
|
+
|
|
210
221
|
if (
|
|
211
222
|
self.audio_codec is None or "pcm" in self.audio_codec
|
|
212
223
|
) and self.output_format in PCM_INCOMPATIBLE_FORMATS:
|
|
@@ -221,6 +232,19 @@ class FFmpegNormalize:
|
|
|
221
232
|
"ReplayGain only works for EBU normalization type for now."
|
|
222
233
|
)
|
|
223
234
|
|
|
235
|
+
# Validate stream selection options
|
|
236
|
+
if self.audio_streams is not None and self.audio_default_only:
|
|
237
|
+
raise FFmpegNormalizeError(
|
|
238
|
+
"Cannot use both audio_streams and audio_default_only together."
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
if self.keep_other_audio and self.keep_original_audio:
|
|
242
|
+
raise FFmpegNormalizeError(
|
|
243
|
+
"Cannot use both --keep-other-audio and --keep-original-audio together. "
|
|
244
|
+
"Use --keep-original-audio to keep all original streams alongside normalized ones, "
|
|
245
|
+
"or --keep-other-audio to keep only non-selected streams as passthrough."
|
|
246
|
+
)
|
|
247
|
+
|
|
224
248
|
self.stats: list[LoudnessStatisticsWithMetadata] = []
|
|
225
249
|
self.media_files: list[MediaFile] = []
|
|
226
250
|
self.file_count = 0
|
ffmpeg_normalize/_media_file.py
CHANGED
|
@@ -136,6 +136,18 @@ class MediaFile:
|
|
|
136
136
|
|
|
137
137
|
output_lines = [line.strip() for line in output.split("\n")]
|
|
138
138
|
|
|
139
|
+
# First pass: parse disposition flags for each stream
|
|
140
|
+
stream_dispositions: dict[int, bool] = {}
|
|
141
|
+
|
|
142
|
+
for line in output_lines:
|
|
143
|
+
if line.startswith("Stream"):
|
|
144
|
+
if stream_id_match := re.search(r"#0:([\d]+)", line):
|
|
145
|
+
stream_id = int(stream_id_match.group(1))
|
|
146
|
+
# Check if (default) appears on the Stream line
|
|
147
|
+
is_default = "(default)" in line
|
|
148
|
+
stream_dispositions[stream_id] = is_default
|
|
149
|
+
|
|
150
|
+
# Second pass: parse stream information
|
|
139
151
|
duration = None
|
|
140
152
|
for line in output_lines:
|
|
141
153
|
if "Duration" in line:
|
|
@@ -155,8 +167,12 @@ class MediaFile:
|
|
|
155
167
|
else:
|
|
156
168
|
continue
|
|
157
169
|
|
|
170
|
+
is_default = stream_dispositions.get(stream_id, False)
|
|
171
|
+
|
|
158
172
|
if "Audio" in line:
|
|
159
|
-
_logger.debug(
|
|
173
|
+
_logger.debug(
|
|
174
|
+
f"Found audio stream at index {stream_id} (default: {is_default})"
|
|
175
|
+
)
|
|
160
176
|
sample_rate_match = re.search(r"(\d+) Hz", line)
|
|
161
177
|
sample_rate = (
|
|
162
178
|
int(sample_rate_match.group(1)) if sample_rate_match else None
|
|
@@ -170,6 +186,7 @@ class MediaFile:
|
|
|
170
186
|
sample_rate,
|
|
171
187
|
bit_depth,
|
|
172
188
|
duration,
|
|
189
|
+
is_default,
|
|
173
190
|
)
|
|
174
191
|
|
|
175
192
|
elif "Video" in line:
|
|
@@ -201,6 +218,53 @@ class MediaFile:
|
|
|
201
218
|
self.streams["video"] = {}
|
|
202
219
|
self.streams["subtitle"] = {}
|
|
203
220
|
|
|
221
|
+
def _get_streams_to_normalize(self) -> list[AudioStream]:
|
|
222
|
+
"""
|
|
223
|
+
Determine which audio streams to normalize based on configuration.
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
list[AudioStream]: List of audio streams to normalize
|
|
227
|
+
"""
|
|
228
|
+
all_audio_streams = list(self.streams["audio"].values())
|
|
229
|
+
|
|
230
|
+
if self.ffmpeg_normalize.audio_streams is not None:
|
|
231
|
+
# User specified specific stream indices
|
|
232
|
+
selected_streams = [
|
|
233
|
+
stream
|
|
234
|
+
for stream in all_audio_streams
|
|
235
|
+
if stream.stream_id in self.ffmpeg_normalize.audio_streams
|
|
236
|
+
]
|
|
237
|
+
if not selected_streams:
|
|
238
|
+
_logger.warning(
|
|
239
|
+
f"No audio streams found matching indices {self.ffmpeg_normalize.audio_streams}. "
|
|
240
|
+
f"Available streams: {[s.stream_id for s in all_audio_streams]}"
|
|
241
|
+
)
|
|
242
|
+
else:
|
|
243
|
+
_logger.info(
|
|
244
|
+
f"Normalizing selected audio streams: {[s.stream_id for s in selected_streams]}"
|
|
245
|
+
)
|
|
246
|
+
return selected_streams
|
|
247
|
+
|
|
248
|
+
elif self.ffmpeg_normalize.audio_default_only:
|
|
249
|
+
# Only normalize streams with default disposition
|
|
250
|
+
default_streams = [
|
|
251
|
+
stream for stream in all_audio_streams if stream.is_default
|
|
252
|
+
]
|
|
253
|
+
if not default_streams:
|
|
254
|
+
_logger.warning(
|
|
255
|
+
"No audio streams with 'default' disposition found. "
|
|
256
|
+
f"Available streams: {[s.stream_id for s in all_audio_streams]}"
|
|
257
|
+
)
|
|
258
|
+
else:
|
|
259
|
+
_logger.info(
|
|
260
|
+
f"Normalizing default audio streams: {[s.stream_id for s in default_streams]}"
|
|
261
|
+
)
|
|
262
|
+
return default_streams
|
|
263
|
+
|
|
264
|
+
else:
|
|
265
|
+
# Normalize all streams (default behavior)
|
|
266
|
+
return all_audio_streams
|
|
267
|
+
|
|
204
268
|
def run_normalization(self) -> None:
|
|
205
269
|
"""
|
|
206
270
|
Run the normalization process for this file.
|
|
@@ -400,7 +464,9 @@ class MediaFile:
|
|
|
400
464
|
"""
|
|
401
465
|
_logger.debug(f"Parsing normalization info for {self.input_file}")
|
|
402
466
|
|
|
403
|
-
|
|
467
|
+
streams_to_normalize = self._get_streams_to_normalize()
|
|
468
|
+
|
|
469
|
+
for index, audio_stream in enumerate(streams_to_normalize):
|
|
404
470
|
if self.ffmpeg_normalize.normalization_type == "ebu":
|
|
405
471
|
fun = getattr(audio_stream, "parse_loudnorm_stats")
|
|
406
472
|
else:
|
|
@@ -410,7 +476,7 @@ class MediaFile:
|
|
|
410
476
|
with tqdm(
|
|
411
477
|
total=100,
|
|
412
478
|
position=1,
|
|
413
|
-
desc=f"Stream {index + 1}/{len(
|
|
479
|
+
desc=f"Stream {index + 1}/{len(streams_to_normalize)}",
|
|
414
480
|
bar_format=TQDM_BAR_FORMAT,
|
|
415
481
|
) as pbar:
|
|
416
482
|
for progress in fun():
|
|
@@ -429,7 +495,9 @@ class MediaFile:
|
|
|
429
495
|
filter_chains = []
|
|
430
496
|
output_labels = []
|
|
431
497
|
|
|
432
|
-
|
|
498
|
+
streams_to_normalize = self._get_streams_to_normalize()
|
|
499
|
+
|
|
500
|
+
for audio_stream in streams_to_normalize:
|
|
433
501
|
skip_normalization = False
|
|
434
502
|
if self.ffmpeg_normalize.lower_only:
|
|
435
503
|
if self.ffmpeg_normalize.normalization_type == "ebu":
|
|
@@ -551,29 +619,66 @@ class MediaFile:
|
|
|
551
619
|
f"The chosen output extension {self.output_ext} does not support video/cover art. It will be disabled."
|
|
552
620
|
)
|
|
553
621
|
|
|
622
|
+
# Determine streams to normalize and passthrough
|
|
623
|
+
streams_to_normalize = self._get_streams_to_normalize()
|
|
624
|
+
all_audio_streams = list(self.streams["audio"].values())
|
|
625
|
+
|
|
626
|
+
# Determine which streams to passthrough
|
|
627
|
+
if self.ffmpeg_normalize.keep_other_audio and (
|
|
628
|
+
self.ffmpeg_normalize.audio_streams is not None
|
|
629
|
+
or self.ffmpeg_normalize.audio_default_only
|
|
630
|
+
):
|
|
631
|
+
streams_to_passthrough = [
|
|
632
|
+
s for s in all_audio_streams if s not in streams_to_normalize
|
|
633
|
+
]
|
|
634
|
+
else:
|
|
635
|
+
streams_to_passthrough = []
|
|
636
|
+
|
|
554
637
|
# ... and map the output of the normalization filters
|
|
555
638
|
for ol in output_labels:
|
|
556
639
|
cmd.extend(["-map", ol])
|
|
557
640
|
|
|
558
|
-
#
|
|
559
|
-
|
|
560
|
-
cmd.extend(["-
|
|
561
|
-
else:
|
|
562
|
-
for index, (_, audio_stream) in enumerate(self.streams["audio"].items()):
|
|
563
|
-
cmd.extend([f"-c:a:{index}", audio_stream.get_pcm_codec()])
|
|
641
|
+
# ... and map passthrough audio streams (copy without normalization)
|
|
642
|
+
for stream in streams_to_passthrough:
|
|
643
|
+
cmd.extend(["-map", f"0:{stream.stream_id}"])
|
|
564
644
|
|
|
565
|
-
#
|
|
645
|
+
# Track output audio stream index for codec assignment
|
|
646
|
+
output_audio_idx = 0
|
|
647
|
+
|
|
648
|
+
# set audio codec for normalized streams
|
|
649
|
+
for audio_stream in streams_to_normalize:
|
|
650
|
+
if self.ffmpeg_normalize.audio_codec:
|
|
651
|
+
codec = self.ffmpeg_normalize.audio_codec
|
|
652
|
+
else:
|
|
653
|
+
codec = audio_stream.get_pcm_codec()
|
|
654
|
+
cmd.extend([f"-c:a:{output_audio_idx}", codec])
|
|
655
|
+
output_audio_idx += 1
|
|
656
|
+
|
|
657
|
+
# set audio codec for passthrough streams (always copy)
|
|
658
|
+
for _ in streams_to_passthrough:
|
|
659
|
+
cmd.extend([f"-c:a:{output_audio_idx}", "copy"])
|
|
660
|
+
output_audio_idx += 1
|
|
661
|
+
|
|
662
|
+
# other audio options (if any) - only apply to normalized streams
|
|
566
663
|
if self.ffmpeg_normalize.audio_bitrate:
|
|
567
664
|
if self.ffmpeg_normalize.audio_codec == "libvorbis":
|
|
568
665
|
# libvorbis takes just a "-b" option, for some reason
|
|
569
666
|
# https://github.com/slhck/ffmpeg-normalize/issues/277
|
|
570
667
|
cmd.extend(["-b", str(self.ffmpeg_normalize.audio_bitrate)])
|
|
571
668
|
else:
|
|
572
|
-
|
|
669
|
+
# Only apply to normalized streams
|
|
670
|
+
for idx in range(len(streams_to_normalize)):
|
|
671
|
+
cmd.extend(
|
|
672
|
+
[f"-b:a:{idx}", str(self.ffmpeg_normalize.audio_bitrate)]
|
|
673
|
+
)
|
|
573
674
|
if self.ffmpeg_normalize.sample_rate:
|
|
574
|
-
|
|
675
|
+
# Only apply to normalized streams
|
|
676
|
+
for idx in range(len(streams_to_normalize)):
|
|
677
|
+
cmd.extend([f"-ar:a:{idx}", str(self.ffmpeg_normalize.sample_rate)])
|
|
575
678
|
if self.ffmpeg_normalize.audio_channels:
|
|
576
|
-
|
|
679
|
+
# Only apply to normalized streams
|
|
680
|
+
for idx in range(len(streams_to_normalize)):
|
|
681
|
+
cmd.extend([f"-ac:a:{idx}", str(self.ffmpeg_normalize.audio_channels)])
|
|
577
682
|
|
|
578
683
|
# ... and subtitles
|
|
579
684
|
if not self.ffmpeg_normalize.subtitle_disable:
|
|
@@ -583,10 +688,11 @@ class MediaFile:
|
|
|
583
688
|
cmd.extend(["-c:s", "copy"])
|
|
584
689
|
|
|
585
690
|
if self.ffmpeg_normalize.keep_original_audio:
|
|
586
|
-
|
|
691
|
+
# Map all original audio streams after normalized and passthrough streams
|
|
587
692
|
for index, _ in enumerate(self.streams["audio"].items()):
|
|
588
693
|
cmd.extend(["-map", f"0:a:{index}"])
|
|
589
|
-
cmd.extend([f"-c:a:{
|
|
694
|
+
cmd.extend([f"-c:a:{output_audio_idx}", "copy"])
|
|
695
|
+
output_audio_idx += 1
|
|
590
696
|
|
|
591
697
|
# extra options (if any)
|
|
592
698
|
if self.ffmpeg_normalize.extra_output_options:
|
|
@@ -645,13 +751,14 @@ class MediaFile:
|
|
|
645
751
|
ebu_pass_2_stats = list(
|
|
646
752
|
AudioStream.prune_and_parse_loudnorm_output(output).values()
|
|
647
753
|
)
|
|
648
|
-
# Only set second pass stats
|
|
649
|
-
|
|
650
|
-
|
|
754
|
+
# Only set second pass stats for streams that were actually normalized
|
|
755
|
+
streams_to_normalize = self._get_streams_to_normalize()
|
|
756
|
+
if len(ebu_pass_2_stats) == len(streams_to_normalize):
|
|
757
|
+
for idx, audio_stream in enumerate(streams_to_normalize):
|
|
651
758
|
audio_stream.set_second_pass_stats(ebu_pass_2_stats[idx])
|
|
652
759
|
else:
|
|
653
760
|
_logger.debug(
|
|
654
|
-
f"Expected {len(
|
|
761
|
+
f"Expected {len(streams_to_normalize)} EBU pass 2 statistics but got {len(ebu_pass_2_stats)}. "
|
|
655
762
|
"This can happen when normalization is skipped (e.g., with --lower-only)."
|
|
656
763
|
)
|
|
657
764
|
|
ffmpeg_normalize/_streams.py
CHANGED
|
@@ -99,6 +99,7 @@ class AudioStream(MediaStream):
|
|
|
99
99
|
sample_rate: int | None,
|
|
100
100
|
bit_depth: int | None,
|
|
101
101
|
duration: float | None,
|
|
102
|
+
is_default: bool = False,
|
|
102
103
|
):
|
|
103
104
|
"""
|
|
104
105
|
Create an AudioStream object.
|
|
@@ -110,6 +111,7 @@ class AudioStream(MediaStream):
|
|
|
110
111
|
sample_rate (int): sample rate in Hz
|
|
111
112
|
bit_depth (int): bit depth in bits
|
|
112
113
|
duration (float): duration in seconds
|
|
114
|
+
is_default (bool): Whether this stream has the default disposition flag
|
|
113
115
|
"""
|
|
114
116
|
super().__init__(ffmpeg_normalize, media_file, "audio", stream_id)
|
|
115
117
|
|
|
@@ -124,6 +126,7 @@ class AudioStream(MediaStream):
|
|
|
124
126
|
self.bit_depth = bit_depth
|
|
125
127
|
|
|
126
128
|
self.duration = duration
|
|
129
|
+
self.is_default = is_default
|
|
127
130
|
|
|
128
131
|
@staticmethod
|
|
129
132
|
def _constrain(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ffmpeg-normalize
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.34.0
|
|
4
4
|
Summary: Normalize audio via ffmpeg
|
|
5
5
|
Keywords: ffmpeg,normalize,audio
|
|
6
6
|
Author: Werner Robitza
|
|
@@ -33,7 +33,7 @@ Description-Content-Type: text/markdown
|
|
|
33
33
|
# ffmpeg-normalize
|
|
34
34
|
|
|
35
35
|
[](https://pypi.org/project/ffmpeg-normalize)
|
|
36
|
-

|
|
36
|
+
[](https://hub.docker.com/r/slhck/ffmpeg-normalize)
|
|
37
37
|

|
|
38
38
|
|
|
39
39
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ffmpeg_normalize/__init__.py,sha256=l0arjiMMBNbiH3IH67gT6SdZjPGAVLAdorUx38dNtvE,508
|
|
2
|
+
ffmpeg_normalize/__main__.py,sha256=pn5OePgr7-P5ajO3HxTMe4yQ1NR7wru5mGMHDklkbQI,22901
|
|
3
|
+
ffmpeg_normalize/_cmd_utils.py,sha256=1JspVpguAPsq7DqvyvjUNzHhVv8J3X93xNOMwito_jY,5284
|
|
4
|
+
ffmpeg_normalize/_errors.py,sha256=brTQ4osJ4fTA8wnyMPVVYfGwJ0wqeShRFydTEwi_VEY,48
|
|
5
|
+
ffmpeg_normalize/_ffmpeg_normalize.py,sha256=ThIglofVOXxPMZcIrrYQ03HchlIOKmVSn41qILQNgg4,13193
|
|
6
|
+
ffmpeg_normalize/_logger.py,sha256=3Ap4Fxg7xGrzz7h4IGuNEf0KKstx0Rq_eLbHPrHzcrI,1841
|
|
7
|
+
ffmpeg_normalize/_media_file.py,sha256=Dz5vBDOelD1-GnlKX6830UbnlwvARFo3O_O-8Zyqlmw,31214
|
|
8
|
+
ffmpeg_normalize/_streams.py,sha256=V5MnTjSnvQa6BNPSoFrUu0zg6mM-b9qaZE0ltGS2FV0,22329
|
|
9
|
+
ffmpeg_normalize/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
ffmpeg_normalize-1.34.0.dist-info/licenses/LICENSE.md,sha256=ig-_YggmJGbPQC_gUgBNFa0_XMsuHTpocivFnlOF4tE,1082
|
|
11
|
+
ffmpeg_normalize-1.34.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
|
|
12
|
+
ffmpeg_normalize-1.34.0.dist-info/entry_points.txt,sha256=1bdrW7-kJRc8tctjnGcfe_Fwx39z5JOm0yZnJHnmwl8,69
|
|
13
|
+
ffmpeg_normalize-1.34.0.dist-info/METADATA,sha256=yoBY7Ig4p2ijd91p1NcT96URVZKZPaDWb0A0XyysIQY,11425
|
|
14
|
+
ffmpeg_normalize-1.34.0.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
ffmpeg_normalize/__init__.py,sha256=l0arjiMMBNbiH3IH67gT6SdZjPGAVLAdorUx38dNtvE,508
|
|
2
|
-
ffmpeg_normalize/__main__.py,sha256=UJIaAel7DSWd0eJr0FlZupsaHvj4wwrQsWd7fmBWB8s,20965
|
|
3
|
-
ffmpeg_normalize/_cmd_utils.py,sha256=1JspVpguAPsq7DqvyvjUNzHhVv8J3X93xNOMwito_jY,5284
|
|
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=eJt9uNXmJheSH4B0ZZARFPMOwN0BGGXOELhcDpWmeew,26860
|
|
8
|
-
ffmpeg_normalize/_streams.py,sha256=XPM539yS220cOrCz0aAiKgoIcStbBUvR4-E0J-7uyOg,22174
|
|
9
|
-
ffmpeg_normalize/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
ffmpeg_normalize-1.33.4.dist-info/licenses/LICENSE.md,sha256=ig-_YggmJGbPQC_gUgBNFa0_XMsuHTpocivFnlOF4tE,1082
|
|
11
|
-
ffmpeg_normalize-1.33.4.dist-info/WHEEL,sha256=F3mArEuDT3LDFEqo9fCiUx6ISLN64aIhcGSiIwtu4r8,79
|
|
12
|
-
ffmpeg_normalize-1.33.4.dist-info/entry_points.txt,sha256=1bdrW7-kJRc8tctjnGcfe_Fwx39z5JOm0yZnJHnmwl8,69
|
|
13
|
-
ffmpeg_normalize-1.33.4.dist-info/METADATA,sha256=01HzoufSfqquEDkixSDTGiOWZq0FsU0ZmGZhM-kG_Mg,11374
|
|
14
|
-
ffmpeg_normalize-1.33.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|