From 240bc7dc6d0df31852f3c457c59e204e1bd8c242 Mon Sep 17 00:00:00 2001 From: lucemia Date: Tue, 21 May 2024 04:35:30 +0000 Subject: [PATCH] init parser --- src/app/__init__.py | 0 src/app/parser.py | 67 ++++++++++++++++++++++++++++++++++++++++++++ src/ffmpeg/parser.py | 9 ------ 3 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 src/app/__init__.py create mode 100644 src/app/parser.py delete mode 100644 src/ffmpeg/parser.py diff --git a/src/app/__init__.py b/src/app/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/app/parser.py b/src/app/parser.py new file mode 100644 index 00000000..8b54fa5f --- /dev/null +++ b/src/app/parser.py @@ -0,0 +1,67 @@ +import shlex +from scripts.cache import load +from ffmpeg.common.schema import FFMpegOptionList, FFMpegOptionType, FFMpegOption +from ffmpeg.base import input, output +from typing import Any + +option_list = load(FFMpegOptionList, "list") + + + +def parse(cmd: str) -> Any: + """ + Parse the command line arguments and return the options. + Options has Input Option, Output Option, Global Option, and Filter Option. + """ + + option_dict = { + k.name: k for k in option_list.options + } + + arguments = shlex.split(cmd) + + assert arguments.pop(0) == "ffmpeg" + + parsed_options: dict[str, tuple[FFMpegOption, str | bool]] = {} + + nodes = [] + while arguments: + arg = arguments.pop(0) + if arg == "-i": + filename = arguments.pop(0) + + nodes.append(input(filename=filename, **{k: parsed_options[k] for k in parsed_options if parsed_options[k][0].is_input_option})) + parsed_options = {k: parsed_options[k] for k in parsed_options if not parsed_options[k][0].is_input_option} + + assert not {k: parsed_options[k] for k in parsed_options if parsed_options[k][0].is_output_option}, f"Output options must not be specified before input files, {parsed_options}" + + elif arg.startswith("-"): + arg = arg.lstrip("-") + arg_name = arg.split(":")[0] + assert arg_name in option_dict, f"Unknown option {arg_name}" + + option = option_dict[arg_name] + + arg_value: str | bool + if option.type == FFMpegOptionType.OPT_TYPE_BOOL: + arg_value = True + else: + arg_value = arguments.pop(0) + + # option is not exclusive, for example -c are both input and output options + parsed_options[arg] = (option, arg_value) + else: + # should be output file + nodes.append(output(filename=arg, **{k: parsed_options[k][1] for k in parsed_options if parsed_options[k][0].is_output_option})) + parsed_options = {k: parsed_options[k] for k in parsed_options if not parsed_options[k][0].is_output_option} + + assert not {k: parsed_options[k] for k in parsed_options if parsed_options[k][0].is_input_option}, f"Input options must not be specified after output files, {parsed_options}" + + if parsed_options: + # handle globla nodes + ... + + print(nodes) + +parse("ffmpeg -i input.mp4 -c:v libx264 -c:a aac output.mp4") +parse("ffmpeg -i input.mp4 -c:a aac output.mp4 -c:v libx264 -c:a aac output.mp4") \ No newline at end of file diff --git a/src/ffmpeg/parser.py b/src/ffmpeg/parser.py deleted file mode 100644 index 3f0ad000..00000000 --- a/src/ffmpeg/parser.py +++ /dev/null @@ -1,9 +0,0 @@ -import shlex - - -def parse(cmd: str): - arguments = shlex.split(cmd) - - assert arguments[0] == "ffmpeg" - - \ No newline at end of file