volume panel; copilot instructions
This commit is contained in:
@ -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:
|
||||
|
||||
Reference in New Issue
Block a user