export works

This commit is contained in:
2026-05-04 17:43:00 -06:00
parent 90b1999a57
commit 5758401dda
4 changed files with 83 additions and 84 deletions

View File

@ -48,6 +48,8 @@ class ExportRequest(BaseModel):
resolution: str = "1080p"
format: str = "mp4"
enhanceAudio: bool = False
normalize_loudness: bool = False
normalize_target_lufs: float = -14.0
captions: str = "none"
words: Optional[List[ExportWordModel]] = None
deleted_indices: Optional[List[int]] = None
@ -166,6 +168,8 @@ async def export_video(req: ExportRequest):
gain_ranges=mapped_gain_segments,
speed_ranges=speed_segments,
global_gain_db=req.global_gain_db,
normalize_loudness=req.normalize_loudness,
normalize_target_lufs=req.normalize_target_lufs,
)
else:
output = export_reencode(
@ -178,6 +182,8 @@ async def export_video(req: ExportRequest):
gain_ranges=mapped_gain_segments,
speed_ranges=speed_segments,
global_gain_db=req.global_gain_db,
normalize_loudness=req.normalize_loudness,
normalize_target_lufs=req.normalize_target_lufs,
)
finally:
if ass_path and os.path.exists(ass_path):

View File

@ -209,6 +209,8 @@ def export_reencode(
gain_ranges: List[dict] = None,
speed_ranges: List[dict] = None,
global_gain_db: float = 0.0,
normalize_loudness: bool = False,
normalize_target_lufs: float = -14.0,
) -> str:
"""
Export video with full re-encode. Slower but supports resolution changes,
@ -241,6 +243,9 @@ def export_reencode(
end = mute_range['end']
filters.append(f"volume=0:enable='between(t,{start},{end})'")
if normalize_loudness:
filters.append(f"loudnorm=I={normalize_target_lufs}:LRA=7:TP=-1.5")
return ",".join(filters) if filters else "anull"
has_audio_filters = bool(mute_ranges) or bool(gain_ranges) or abs(float(global_gain_db)) > 1e-6
@ -367,6 +372,12 @@ def export_reencode(
filter_complex = "".join(filter_parts)
# Add loudnorm to the cutting path audio chain if enabled
audio_map_label = "[outa]"
if normalize_loudness:
filter_complex += f";{audio_map_label}loudnorm=I={normalize_target_lufs}:LRA=7:TP=-1.5[outa_norm]"
audio_map_label = "[outa_norm]"
scale = scale_map.get(resolution, "")
if scale:
filter_complex += f";[outv]{scale}[outv_scaled]"
@ -383,16 +394,17 @@ def export_reencode(
"-i", input_path,
"-filter_complex", filter_complex,
"-map", video_map,
"-map", "[outa]",
"-map", audio_map_label,
*codec_args,
"-movflags", "+faststart",
output_path,
]
logger.info(
"Re-encoding %s segments (speed-adjusted=%s) -> %s (%s)",
"Re-encoding %s segments (speed-adjusted=%s, normalize=%s) -> %s (%s)",
n,
has_speed,
normalize_loudness,
output_path,
resolution,
)
@ -415,6 +427,8 @@ def export_reencode_with_subs(
gain_ranges: List[dict] = None,
speed_ranges: List[dict] = None,
global_gain_db: float = 0.0,
normalize_loudness: bool = False,
normalize_target_lufs: float = -14.0,
) -> str:
"""
Export video with re-encode and burn-in subtitles (ASS format).
@ -451,6 +465,9 @@ def export_reencode_with_subs(
end = mute_range['end']
filters.append(f"volume=0:enable='between(t,{start},{end})'")
if normalize_loudness:
filters.append(f"loudnorm=I={normalize_target_lufs}:LRA=7:TP=-1.5")
return ",".join(filters) if filters else "anull"
has_audio_filters = bool(mute_ranges) or bool(gain_ranges) or abs(float(global_gain_db)) > 1e-6