add trimation
This commit is contained in:
parent
d1126b7cf6
commit
5f36e9a22a
|
|
@ -149,11 +149,17 @@ class VideoHighStrategy(ConversionStrategy):
|
||||||
"""High quality video conversion: Lossless H.264 (video) + PCM (audio)."""
|
"""High quality video conversion: Lossless H.264 (video) + PCM (audio)."""
|
||||||
def convert(self, input_file, output_file):
|
def convert(self, input_file, output_file):
|
||||||
cmd = [
|
cmd = [
|
||||||
"ffmpeg", "-y", "-i", input_file,
|
"ffmpeg", "-y", "-i", input_file
|
||||||
|
]
|
||||||
|
# Add trim parameters if specified
|
||||||
|
if hasattr(self, "trim"):
|
||||||
|
start, end = self.trim
|
||||||
|
cmd += ["-ss", str(start), "-to", str(end)]
|
||||||
|
cmd += [
|
||||||
"-c:v", "libx264", "-preset", "veryslow", "-crf", "18",
|
"-c:v", "libx264", "-preset", "veryslow", "-crf", "18",
|
||||||
"-pix_fmt", "yuv420p",
|
"-pix_fmt", "yuv420p",
|
||||||
"-movflags", "+faststart",
|
"-movflags", "+faststart",
|
||||||
"-c:a", "pcm_s16le" # Lossless audio using PCM
|
"-c:a", "pcm_s16le" # Lossless audio using PCM
|
||||||
]
|
]
|
||||||
if hasattr(self, "custom_params"):
|
if hasattr(self, "custom_params"):
|
||||||
cmd.extend(self.custom_params)
|
cmd.extend(self.custom_params)
|
||||||
|
|
@ -164,7 +170,13 @@ class VideoLowStrategy(ConversionStrategy):
|
||||||
"""Low quality video conversion: H.264 (video) + AAC (audio)."""
|
"""Low quality video conversion: H.264 (video) + AAC (audio)."""
|
||||||
def convert(self, input_file, output_file):
|
def convert(self, input_file, output_file):
|
||||||
cmd = [
|
cmd = [
|
||||||
"ffmpeg", "-y", "-i", input_file,
|
"ffmpeg", "-y", "-i", input_file
|
||||||
|
]
|
||||||
|
# Add trim parameters if specified
|
||||||
|
if hasattr(self, "trim"):
|
||||||
|
start, end = self.trim
|
||||||
|
cmd += ["-ss", str(start), "-to", str(end)]
|
||||||
|
cmd += [
|
||||||
"-c:v", "libx264", "-preset", "fast", "-crf", "23",
|
"-c:v", "libx264", "-preset", "fast", "-crf", "23",
|
||||||
"-c:a", "aac", "-b:a", "192k"
|
"-c:a", "aac", "-b:a", "192k"
|
||||||
]
|
]
|
||||||
|
|
@ -176,9 +188,14 @@ class VideoLowStrategy(ConversionStrategy):
|
||||||
class AudioHighStrategy(ConversionStrategy):
|
class AudioHighStrategy(ConversionStrategy):
|
||||||
"""High quality audio conversion using FLAC."""
|
"""High quality audio conversion using FLAC."""
|
||||||
def convert(self, input_file, output_file):
|
def convert(self, input_file, output_file):
|
||||||
# Using -vn and -map to select only audio stream(s)
|
|
||||||
cmd = [
|
cmd = [
|
||||||
"ffmpeg", "-y", "-i", input_file,
|
"ffmpeg", "-y", "-i", input_file
|
||||||
|
]
|
||||||
|
# Add trim parameters if specified
|
||||||
|
if hasattr(self, "trim"):
|
||||||
|
start, end = self.trim
|
||||||
|
cmd += ["-ss", str(start), "-to", str(end)]
|
||||||
|
cmd += [
|
||||||
"-vn",
|
"-vn",
|
||||||
"-map", "0:a",
|
"-map", "0:a",
|
||||||
"-c:a", "flac"
|
"-c:a", "flac"
|
||||||
|
|
@ -191,9 +208,14 @@ class AudioHighStrategy(ConversionStrategy):
|
||||||
class AudioLowStrategy(ConversionStrategy):
|
class AudioLowStrategy(ConversionStrategy):
|
||||||
"""Low quality audio conversion using MP3 (libmp3lame)."""
|
"""Low quality audio conversion using MP3 (libmp3lame)."""
|
||||||
def convert(self, input_file, output_file):
|
def convert(self, input_file, output_file):
|
||||||
# Using -vn and -map to select only audio stream(s)
|
|
||||||
cmd = [
|
cmd = [
|
||||||
"ffmpeg", "-y", "-i", input_file,
|
"ffmpeg", "-y", "-i", input_file
|
||||||
|
]
|
||||||
|
# Add trim parameters if specified
|
||||||
|
if hasattr(self, "trim"):
|
||||||
|
start, end = self.trim
|
||||||
|
cmd += ["-ss", str(start), "-to", str(end)]
|
||||||
|
cmd += [
|
||||||
"-vn",
|
"-vn",
|
||||||
"-map", "0:a",
|
"-map", "0:a",
|
||||||
"-c:a", "libmp3lame", "-b:a", "192k"
|
"-c:a", "libmp3lame", "-b:a", "192k"
|
||||||
|
|
@ -211,14 +233,17 @@ class MediaConverter:
|
||||||
Main class that selects the appropriate conversion strategy based on media type
|
Main class that selects the appropriate conversion strategy based on media type
|
||||||
and quality, then performs the conversion.
|
and quality, then performs the conversion.
|
||||||
"""
|
"""
|
||||||
def __init__(self, input_file, output_file, quality, custom_params=None):
|
def __init__(self, input_file, output_file, quality, custom_params=None, trim=None):
|
||||||
self.input_file = input_file
|
self.input_file = input_file
|
||||||
self.output_file = output_file
|
self.output_file = output_file
|
||||||
self.quality = quality
|
self.quality = quality
|
||||||
self.custom_params = custom_params or []
|
self.custom_params = custom_params or []
|
||||||
|
self.trim = trim # Tuple of (start, end) times in seconds
|
||||||
self.media_type = MediaDetector.detect_media_type(self.input_file)
|
self.media_type = MediaDetector.detect_media_type(self.input_file)
|
||||||
logging.info("Detected media type: %s", self.media_type)
|
logging.info("Detected media type: %s", self.media_type)
|
||||||
self.strategy = self.get_strategy()
|
self.strategy = self.get_strategy()
|
||||||
|
if self.trim:
|
||||||
|
self.strategy.trim = self.trim
|
||||||
|
|
||||||
def get_strategy(self):
|
def get_strategy(self):
|
||||||
"""Selects and returns the proper conversion strategy."""
|
"""Selects and returns the proper conversion strategy."""
|
||||||
|
|
@ -254,6 +279,7 @@ def main():
|
||||||
help="Quality mode: high or low")
|
help="Quality mode: high or low")
|
||||||
parser.add_argument("--custom", nargs='*',
|
parser.add_argument("--custom", nargs='*',
|
||||||
help="Additional custom ffmpeg parameters", default=[])
|
help="Additional custom ffmpeg parameters", default=[])
|
||||||
|
parser.add_argument("--trim", help="Trim the media between start-end seconds (e.g., 0.5-35)", default=None)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Fixed paths
|
# Fixed paths
|
||||||
|
|
@ -265,6 +291,19 @@ def main():
|
||||||
logging.error("Input file not found at %s", input_path)
|
logging.error("Input file not found at %s", input_path)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Parse trim argument if provided
|
||||||
|
trim_tuple = None
|
||||||
|
if args.trim:
|
||||||
|
try:
|
||||||
|
start_str, end_str = args.trim.split('-')
|
||||||
|
trim_tuple = (float(start_str), float(end_str))
|
||||||
|
if trim_tuple[0] >= trim_tuple[1]:
|
||||||
|
logging.error("Invalid trim range: start time must be less than end time.")
|
||||||
|
sys.exit(1)
|
||||||
|
except ValueError:
|
||||||
|
logging.error("Invalid trim format. Use format: start-end (e.g., 0.5-35)")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# Determine media type
|
# Determine media type
|
||||||
media_type = MediaDetector.detect_media_type(input_path)
|
media_type = MediaDetector.detect_media_type(input_path)
|
||||||
|
|
||||||
|
|
@ -288,11 +327,13 @@ def main():
|
||||||
logging.info("Output file will be: %s", output_path)
|
logging.info("Output file will be: %s", output_path)
|
||||||
if args.custom:
|
if args.custom:
|
||||||
logging.info("Custom ffmpeg parameters: %s", args.custom)
|
logging.info("Custom ffmpeg parameters: %s", args.custom)
|
||||||
|
if trim_tuple:
|
||||||
|
logging.info("Trimming media from %s to %s seconds", trim_tuple[0], trim_tuple[1])
|
||||||
|
|
||||||
# Parse all metadata and save it as output.json in the output directory
|
# Parse all metadata and save it as output.json in the output directory
|
||||||
parse_metadata(input_path, os.path.dirname(output_path))
|
parse_metadata(input_path, os.path.dirname(output_path))
|
||||||
|
|
||||||
converter = MediaConverter(input_path, output_path, args.quality, args.custom)
|
converter = MediaConverter(input_path, output_path, args.quality, args.custom, trim=trim_tuple)
|
||||||
converter.convert()
|
converter.convert()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue