refact (core): split large code blocks, remove useless files/code #12
+116
-85
@@ -269,6 +269,109 @@ def extract_cover_image(input_file: str, output_path: str) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def _build_inputs(cmd: List[str], input_file: str, cover_image_path: Optional[str]) -> None:
|
||||
"""Add input files to the command."""
|
||||
if cover_image_path:
|
||||
cmd.extend(['-i', cover_image_path])
|
||||
cmd.extend(['-i', input_file])
|
||||
|
||||
|
||||
def _build_time_options(cmd: List[str], start_seconds: int, duration_seconds: int) -> None:
|
||||
"""Add time-based options to the command."""
|
||||
cmd.extend(['-ss', format_time(start_seconds), '-t', format_time(duration_seconds)])
|
||||
|
||||
|
||||
def _build_metadata(cmd: List[str], metadata: Optional[Dict]) -> None:
|
||||
"""Add metadata options to the command."""
|
||||
cmd.append('-map_metadata')
|
||||
cmd.append('-1')
|
||||
if metadata:
|
||||
for key, value in metadata.items():
|
||||
if value is not None and value != '':
|
||||
cmd.extend(['-metadata', f"{key}={value}"])
|
||||
|
||||
|
||||
def _build_cover_image_mapping(
|
||||
cmd: List[str],
|
||||
audio_codec: Optional[str],
|
||||
video_codec: Optional[str],
|
||||
video_quality: Optional[int],
|
||||
) -> None:
|
||||
"""Build stream mapping for cover image extraction (audio + cover video)."""
|
||||
cmd.extend(['-map', '1:a:0', '-map', '0:v:0'])
|
||||
|
||||
if video_codec and video_codec != 'copy':
|
||||
cmd.extend(['-c:v', video_codec])
|
||||
else:
|
||||
cmd.extend(['-c:v', 'png'])
|
||||
|
||||
if audio_codec and audio_codec != 'copy':
|
||||
cmd.extend(['-c:a', audio_codec])
|
||||
else:
|
||||
cmd.extend(['-c:a', 'copy'])
|
||||
|
||||
cmd.append('-sn')
|
||||
|
||||
if video_quality is not None:
|
||||
cmd.extend(['-q:v', str(video_quality)])
|
||||
|
||||
|
||||
def _build_standard_mapping(
|
||||
cmd: List[str],
|
||||
stream_info: Dict,
|
||||
audio_codec: Optional[str],
|
||||
video_codec: Optional[str],
|
||||
subtitle_codec: Optional[str],
|
||||
video_quality: Optional[int],
|
||||
drop_video: bool,
|
||||
drop_subs: bool,
|
||||
) -> None:
|
||||
"""Build stream mapping for standard extraction (no cover image)."""
|
||||
if drop_video and drop_subs:
|
||||
cmd.extend(['-map', '0:a:0'])
|
||||
elif drop_video:
|
||||
cmd.extend(['-map', '0:a:0', '-map', '0:s?'])
|
||||
elif drop_subs:
|
||||
cmd.extend(['-map', '0:a:0', '-map', '0:v:0'])
|
||||
else:
|
||||
cmd.extend(['-map', '0'])
|
||||
|
||||
if audio_codec and audio_codec != 'copy':
|
||||
cmd.extend(['-c:a', audio_codec])
|
||||
else:
|
||||
cmd.extend(['-c:a', 'copy'])
|
||||
|
||||
if not drop_video and stream_info.get('has_video'):
|
||||
if video_codec and video_codec != 'copy':
|
||||
cmd.extend(['-c:v', video_codec])
|
||||
if video_quality is not None:
|
||||
cmd.extend(['-q:v', str(video_quality)])
|
||||
else:
|
||||
cmd.extend(['-c:v', 'copy'])
|
||||
else:
|
||||
cmd.append('-vn')
|
||||
|
||||
if not drop_subs and stream_info.get('has_subtitle'):
|
||||
if subtitle_codec and subtitle_codec != 'copy':
|
||||
cmd.extend(['-c:s', subtitle_codec])
|
||||
else:
|
||||
cmd.extend(['-c:s', 'copy'])
|
||||
else:
|
||||
cmd.append('-sn')
|
||||
|
||||
|
||||
def _build_format(cmd: List[str], format_opt: Optional[str]) -> None:
|
||||
"""Add output format option if specified."""
|
||||
if format_opt:
|
||||
ffmpeg_format = FORMAT_INFO.get(format_opt, {}).get('ffmpeg', format_opt)
|
||||
cmd.extend(['-f', ffmpeg_format])
|
||||
|
||||
|
||||
def _build_output(cmd: List[str], output_path: str) -> None:
|
||||
"""Add output file to the command."""
|
||||
cmd.extend(['-y', output_path])
|
||||
|
||||
|
||||
def build_ffmpeg_command(
|
||||
input_file: str,
|
||||
start_seconds: int,
|
||||
@@ -309,93 +412,21 @@ def build_ffmpeg_command(
|
||||
"""
|
||||
cmd = ['ffmpeg']
|
||||
|
||||
# Add cover image as first input if provided
|
||||
_build_inputs(cmd, input_file, cover_image_path)
|
||||
_build_time_options(cmd, start_seconds, duration_seconds)
|
||||
_build_metadata(cmd, metadata)
|
||||
|
||||
if cover_image_path:
|
||||
cmd.extend(['-i', cover_image_path])
|
||||
|
||||
# Add main input file
|
||||
cmd.extend(['-i', input_file])
|
||||
|
||||
# Time options
|
||||
cmd.extend(['-ss', format_time(start_seconds), '-t', format_time(duration_seconds)])
|
||||
|
||||
# Clear all original metadata.
|
||||
cmd.append('-map_metadata')
|
||||
cmd.append('-1')
|
||||
|
||||
# Apply custom metadata.
|
||||
if metadata:
|
||||
for key, value in metadata.items():
|
||||
if value is not None and value != '':
|
||||
cmd.extend(['-metadata', f"{key}={value}"])
|
||||
|
||||
# ---------- Stream mapping and codecs ----------
|
||||
if cover_image_path:
|
||||
# We have two inputs: index 0 = cover image, index 1 = main input
|
||||
# Map audio from main input (index 1) and video from cover image (index 0)
|
||||
cmd.extend(['-map', '1:a:0', '-map', '0:v:0'])
|
||||
|
||||
# Video codec: use user-specified codec if provided, otherwise fallback to png
|
||||
if video_codec and video_codec != 'copy':
|
||||
cmd.extend(['-c:v', video_codec])
|
||||
else:
|
||||
cmd.extend(['-c:v', 'png'])
|
||||
|
||||
# Audio codec
|
||||
if audio_codec and audio_codec != 'copy':
|
||||
cmd.extend(['-c:a', audio_codec])
|
||||
else:
|
||||
cmd.extend(['-c:a', 'copy'])
|
||||
|
||||
# Subtitle: we don't copy subtitles when using cover image (they would be from main input)
|
||||
cmd.append('-sn')
|
||||
|
||||
# Video quality if specified
|
||||
if video_quality is not None:
|
||||
cmd.extend(['-q:v', str(video_quality)])
|
||||
|
||||
_build_cover_image_mapping(cmd, audio_codec, video_codec, video_quality)
|
||||
else:
|
||||
# Standard mapping (no cover image)
|
||||
if drop_video and drop_subs:
|
||||
cmd.extend(['-map', '0:a:0'])
|
||||
elif drop_video:
|
||||
cmd.extend(['-map', '0:a:0', '-map', '0:s?'])
|
||||
elif drop_subs:
|
||||
cmd.extend(['-map', '0:a:0', '-map', '0:v:0'])
|
||||
else:
|
||||
cmd.extend(['-map', '0'])
|
||||
_build_standard_mapping(
|
||||
cmd, stream_info, audio_codec, video_codec, subtitle_codec,
|
||||
video_quality, drop_video, drop_subs
|
||||
)
|
||||
|
||||
# Audio codec
|
||||
if audio_codec and audio_codec != 'copy':
|
||||
cmd.extend(['-c:a', audio_codec])
|
||||
else:
|
||||
cmd.extend(['-c:a', 'copy'])
|
||||
_build_format(cmd, format_opt)
|
||||
_build_output(cmd, output_path)
|
||||
|
||||
# Video codec
|
||||
if not drop_video and stream_info.get('has_video'):
|
||||
if video_codec and video_codec != 'copy':
|
||||
cmd.extend(['-c:v', video_codec])
|
||||
# Add video quality if specified (only when re-encoding)
|
||||
if video_quality is not None:
|
||||
cmd.extend(['-q:v', str(video_quality)])
|
||||
else:
|
||||
cmd.extend(['-c:v', 'copy'])
|
||||
else:
|
||||
cmd.append('-vn')
|
||||
|
||||
# Subtitle codec
|
||||
if not drop_subs and stream_info.get('has_subtitle'):
|
||||
if subtitle_codec and subtitle_codec != 'copy':
|
||||
cmd.extend(['-c:s', subtitle_codec])
|
||||
else:
|
||||
cmd.extend(['-c:s', 'copy'])
|
||||
else:
|
||||
cmd.append('-sn')
|
||||
|
||||
# Output format
|
||||
if format_opt:
|
||||
ffmpeg_format = FORMAT_INFO.get(format_opt, {}).get('ffmpeg', format_opt)
|
||||
cmd.extend(['-f', ffmpeg_format])
|
||||
|
||||
cmd.extend(['-y', output_path])
|
||||
return cmd
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user