volume panel; copilot instructions

This commit is contained in:
2026-04-15 16:10:35 -06:00
parent 0df967507f
commit 4f90750497
11 changed files with 688 additions and 106 deletions

View File

@ -112,6 +112,8 @@ def export_reencode(
resolution: str = "1080p",
format_hint: str = "mp4",
mute_ranges: List[dict] = None,
gain_ranges: List[dict] = None,
global_gain_db: float = 0.0,
) -> str:
"""
Export video with full re-encode. Slower but supports resolution changes,
@ -128,21 +130,29 @@ def export_reencode(
"4k": "scale=-2:2160",
}
# Handle muting case - keep full video but silence audio ranges
if mute_ranges and len(mute_ranges) > 0:
# Build volume filter for muting
volume_filters = []
for i, mute_range in enumerate(mute_ranges):
def build_audio_filter() -> str:
filters = []
if abs(float(global_gain_db)) > 1e-6:
filters.append(f"volume={float(global_gain_db)}dB")
for gain_range in gain_ranges or []:
start = gain_range['start']
end = gain_range['end']
gain_db = gain_range.get('gain_db', 0.0)
filters.append(f"volume={float(gain_db)}dB:enable='between(t,{start},{end})'")
for mute_range in mute_ranges or []:
start = mute_range['start']
end = mute_range['end']
# Use volume=0 to mute, enable to specify time range
volume_filters.append(f"volume=0:enable='between(t,{start},{end})'")
filters.append(f"volume=0:enable='between(t,{start},{end})'")
# Combine all volume filters
if volume_filters:
audio_filter = ",".join(volume_filters)
else:
audio_filter = "anull" # No muting needed
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
# Handle filtered full-timeline audio case (mute/gain/global gain)
if has_audio_filters:
audio_filter = build_audio_filter()
# Video filter - just scaling if needed
scale = scale_map.get(resolution, "")
@ -170,7 +180,14 @@ def export_reencode(
output_path,
]
logger.info(f"Re-encoding with {len(mute_ranges)} mute ranges -> {output_path} ({resolution})")
logger.info(
"Re-encoding with audio filters (mute=%s gain=%s global=%s) -> %s (%s)",
len(mute_ranges or []),
len(gain_ranges or []),
global_gain_db,
output_path,
resolution,
)
else:
# Original cutting logic
if not keep_segments:
@ -228,6 +245,8 @@ def export_reencode_with_subs(
resolution: str = "1080p",
format_hint: str = "mp4",
mute_ranges: List[dict] = None,
gain_ranges: List[dict] = None,
global_gain_db: float = 0.0,
) -> str:
"""
Export video with re-encode and burn-in subtitles (ASS format).
@ -245,19 +264,29 @@ def export_reencode_with_subs(
"4k": "scale=-2:2160",
}
# Handle muting case - keep full video but silence audio ranges
if mute_ranges and len(mute_ranges) > 0:
# Build volume filter for muting
volume_filters = []
for i, mute_range in enumerate(mute_ranges):
def build_audio_filter() -> str:
filters = []
if abs(float(global_gain_db)) > 1e-6:
filters.append(f"volume={float(global_gain_db)}dB")
for gain_range in gain_ranges or []:
start = gain_range['start']
end = gain_range['end']
gain_db = gain_range.get('gain_db', 0.0)
filters.append(f"volume={float(gain_db)}dB:enable='between(t,{start},{end})'")
for mute_range in mute_ranges or []:
start = mute_range['start']
end = mute_range['end']
volume_filters.append(f"volume=0:enable='between(t,{start},{end})'")
filters.append(f"volume=0:enable='between(t,{start},{end})'")
if volume_filters:
audio_filter = ",".join(volume_filters)
else:
audio_filter = "anull"
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
# Handle filtered full-timeline audio case (mute/gain/global gain)
if has_audio_filters:
audio_filter = build_audio_filter()
# Video filter with subtitles
escaped_sub = subtitle_path.replace("\\", "/").replace(":", "\\:")
@ -284,7 +313,14 @@ def export_reencode_with_subs(
output_path,
]
logger.info(f"Re-encoding with subtitles and {len(mute_ranges)} mute ranges -> {output_path} ({resolution})")
logger.info(
"Re-encoding with subtitles and audio filters (mute=%s gain=%s global=%s) -> %s (%s)",
len(mute_ranges or []),
len(gain_ranges or []),
global_gain_db,
output_path,
resolution,
)
else:
# Original cutting logic with subtitles
if not keep_segments: