From 8c05a4a989b0aa4a933d7436e9c189f446f47cbe Mon Sep 17 00:00:00 2001 From: Roberto Mello Date: Sat, 22 Nov 2025 23:15:24 -0700 Subject: [PATCH 1/2] Accept command-line arguments and YAML file for idea and script - Replace hardcoded parameters with argparse command-line arguments - Support both direct CLI arguments (-i, -u, -s) and YAML file input (-f) - Add example YAML files (idea-example.yaml, script-example.yaml) - Update .gitignore to exclude .DS_Store and .tool-versions --- .gitignore | 4 ++ idea-example.yaml | 7 ++++ main_idea2video.py | 89 +++++++++++++++++++++++++++++++++++----- main_script2video.py | 98 ++++++++++++++++++++++++++++++++++---------- script-example.yaml | 17 ++++++++ 5 files changed, 183 insertions(+), 32 deletions(-) create mode 100644 idea-example.yaml create mode 100644 script-example.yaml diff --git a/.gitignore b/.gitignore index 54cf5da9..48064e20 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,7 @@ wheels/ # working directory .working_dir/ .test/ + +# other +.DS_Store +.tool-versions diff --git a/idea-example.yaml b/idea-example.yaml new file mode 100644 index 00000000..10f245b6 --- /dev/null +++ b/idea-example.yaml @@ -0,0 +1,7 @@ +idea: | + If a cat and a dog are best friends, what would happen when they meet a new cat? + +user_requirement: | + For children, do not exceed 3 scenes. Each scene should be no more than 5 shots. + +style: Cartoon diff --git a/main_idea2video.py b/main_idea2video.py index 09fe7a55..adf650e5 100644 --- a/main_idea2video.py +++ b/main_idea2video.py @@ -1,22 +1,89 @@ import asyncio +import argparse +import yaml +from pathlib import Path from pipelines.idea2video_pipeline import Idea2VideoPipeline -# SET YOUR OWN IDEA, USER REQUIREMENT, AND STYLE HERE -idea = \ -""" -If a cat and a dog are best friends, what would happen when they meet a new cat? -""" -user_requirement = \ -""" -For children, do not exceed 3 scenes. Each scene should be no more than 5 shots. -""" -style = "Cartoon" +def load_from_file(file_path: str) -> dict: + """Load idea, user_requirement, and style from a YAML file.""" + with open(file_path, 'r') as f: + data = yaml.safe_load(f) + + required_fields = ['idea', 'user_requirement', 'style'] + for field in required_fields: + if field not in data: + raise ValueError( + f"Missing required field '{field}' in {file_path}") + + return data + + +def parse_args(): + parser = argparse.ArgumentParser( + description='Generate video from an idea using AI', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + # Using command-line arguments: + python main_idea2video.py -i "A woman exercising" -u "3 scenes max" -s "Realistic" + + # Using a YAML file: + python main_idea2video.py -f idea-example.yaml -c configs/myidea2video.yaml + + # YAML file format: + idea: | + Your idea here + Can span multiple lines + user_requirement: | + Your requirements here + style: Realistic, warm feel + """ + ) + + parser.add_argument('-f', '--file', type=str, + help='Path to YAML file containing idea, user_requirement, and style') + parser.add_argument('-i', '--idea', type=str, + help='The main idea for the video') + parser.add_argument('-u', '--user-requirement', type=str, + help='User requirements (e.g., number of scenes, shots)') + parser.add_argument('-s', '--style', type=str, + help='Video style (e.g., "Realistic, warm feel")') + parser.add_argument('-c', '--config', type=str, default='configs/idea2video.yaml', + help='Path to pipeline configuration file (default: configs/idea2video.yaml)') + + args = parser.parse_args() + + # Validate arguments + if args.file: + if any([args.idea, args.user_requirement, args.style]): + parser.error( + "Cannot use --file with --idea, --user-requirement, or --style") + return args + else: + if not all([args.idea, args.user_requirement, args.style]): + parser.error( + "Must provide either --file or all of: --idea, --user-requirement, --style") + return args async def main(): - pipeline = Idea2VideoPipeline.init_from_config(config_path="configs/idea2video.yaml") + args = parse_args() + + # Load parameters from file or command-line arguments + if args.file: + data = load_from_file(args.file) + idea = data['idea'] + user_requirement = data['user_requirement'] + style = data['style'] + else: + idea = args.idea + user_requirement = args.user_requirement + style = args.style + + pipeline = Idea2VideoPipeline.init_from_config(config_path=args.config) await pipeline(idea=idea, user_requirement=user_requirement, style=style) + if __name__ == "__main__": asyncio.run(main()) diff --git a/main_script2video.py b/main_script2video.py index cd6cf7bc..761a6ef4 100644 --- a/main_script2video.py +++ b/main_script2video.py @@ -1,32 +1,88 @@ import asyncio +import argparse +import yaml +from pathlib import Path from pipelines.script2video_pipeline import Script2VideoPipeline -# SET YOUR OWN SCRIPT, USER REQUIREMENT, AND STYLE HERE -script = \ -""" -EXT. SCHOOL GYM - DAY -A group of students are practicing basketball in the gym. The gym is large and open, with a basketball hoop at one end and a large crowd of spectators at the other end. John (18, male, tall, athletic) is the star player, and he is practicing his dribble and shot. Jane (17, female, short, athletic) is the assistant coach, and she is helping John with his practice. The other students are watching the practice and cheering for John. -John: (dribbling the ball) I'm going to score a basket! -Jane: (smiling) Good job, John! -John: (shooting the ball) Yes! -John:(The shot misses. He seems frustrated.) Argh! My follow-through feels off today. -Jane:(Walks over, analytical.) Your elbow is drifting out. Remember, straight as an arrow. -John:(Nods, taking the ball again.) Straight as an arrow... Let me try again. -(John takes another shot. This time, the ball swishes through the net perfectly.) -Jane:(Clapping.) There it is! Perfect form! That's the shot we need for the championship. -John:(Retrieving the ball, smiling with renewed confidence.) Thanks, Coach Jane. I just needed you to point it out. One more time? -""" -user_requirement = \ -""" -Fast-paced with no more than 15 shots. -""" -style = "Anime Style" +def load_from_file(file_path: str) -> dict: + """Load script, user_requirement, and style from a YAML file.""" + with open(file_path, 'r') as f: + data = yaml.safe_load(f) + required_fields = ['script', 'user_requirement', 'style'] + for field in required_fields: + if field not in data: + raise ValueError( + f"Missing required field '{field}' in {file_path}") + + return data + + +def parse_args(): + parser = argparse.ArgumentParser( + description='Generate video from a script using AI', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + # Using command-line arguments: + python main_script2video.py -S "EXT. GYM - DAY..." -u "15 shots max" -s "Anime Style" + + # Using a YAML file: + python main_script2video.py -f script-example.yaml + + # YAML file format: + script: | + EXT. GYM - DAY + Your script here + Can span multiple lines + user_requirement: | + Your requirements here + style: Anime Style + """ + ) + + parser.add_argument('-f', '--file', type=str, + help='Path to YAML file containing script, user_requirement, and style') + parser.add_argument('-S', '--script', type=str, + help='The script for the video') + parser.add_argument('-u', '--user-requirement', type=str, + help='User requirements (e.g., number of shots, pacing)') + parser.add_argument('-s', '--style', type=str, + help='Video style (e.g., "Anime Style")') + parser.add_argument('-c', '--config', type=str, default='configs/script2video.yaml', + help='Path to pipeline configuration file (default: configs/script2video.yaml)') + + args = parser.parse_args() + + # Validate arguments + if args.file: + if any([args.script, args.user_requirement, args.style]): + parser.error( + "Cannot use --file with --script, --user-requirement, or --style") + return args + else: + if not all([args.script, args.user_requirement, args.style]): + parser.error( + "Must provide either --file or all of: --script, --user-requirement, --style") + return args async def main(): - pipeline = Script2VideoPipeline.init_from_config(config_path="configs/script2video.yaml") + args = parse_args() + + # Load parameters from file or command-line arguments + if args.file: + data = load_from_file(args.file) + script = data['script'] + user_requirement = data['user_requirement'] + style = data['style'] + else: + script = args.script + user_requirement = args.user_requirement + style = args.style + + pipeline = Script2VideoPipeline.init_from_config(config_path=args.config) await pipeline(script=script, user_requirement=user_requirement, style=style) diff --git a/script-example.yaml b/script-example.yaml new file mode 100644 index 00000000..9d45fbca --- /dev/null +++ b/script-example.yaml @@ -0,0 +1,17 @@ +script: | + EXT. SCHOOL GYM - DAY + A group of students are practicing basketball in the gym. The gym is large and open, with a basketball hoop at one end and a large crowd of spectators at the other end. John (18, male, tall, athletic) is the star player, and he is practicing his dribble and shot. Jane (17, female, short, athletic) is the assistant coach, and she is helping John with his practice. The other students are watching the practice and cheering for John. + John: (dribbling the ball) I'm going to score a basket! + Jane: (smiling) Good job, John! + John: (shooting the ball) Yes! + John:(The shot misses. He seems frustrated.) Argh! My follow-through feels off today. + Jane:(Walks over, analytical.) Your elbow is drifting out. Remember, straight as an arrow. + John:(Nods, taking the ball again.) Straight as an arrow... Let me try again. + (John takes another shot. This time, the ball swishes through the net perfectly.) + Jane:(Clapping.) There it is! Perfect form! That's the shot we need for the championship. + John:(Retrieving the ball, smiling with renewed confidence.) Thanks, Coach Jane. I just needed you to point it out. One more time? + +user_requirement: | + Fast-paced with no more than 15 shots. + +style: Anime Style From 3a282558b039520c0031b7a0f5ef6573b1fb337d Mon Sep 17 00:00:00 2001 From: Roberto Mello Date: Sat, 22 Nov 2025 23:19:10 -0700 Subject: [PATCH 2/2] Move example idea and script to configs to keep main tree clean. Update docstrings --- idea-example.yaml => configs/idea-example.yaml | 0 script-example.yaml => configs/script-example.yaml | 0 main_idea2video.py | 2 +- main_script2video.py | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename idea-example.yaml => configs/idea-example.yaml (100%) rename script-example.yaml => configs/script-example.yaml (100%) diff --git a/idea-example.yaml b/configs/idea-example.yaml similarity index 100% rename from idea-example.yaml rename to configs/idea-example.yaml diff --git a/script-example.yaml b/configs/script-example.yaml similarity index 100% rename from script-example.yaml rename to configs/script-example.yaml diff --git a/main_idea2video.py b/main_idea2video.py index adf650e5..72513300 100644 --- a/main_idea2video.py +++ b/main_idea2video.py @@ -29,7 +29,7 @@ def parse_args(): python main_idea2video.py -i "A woman exercising" -u "3 scenes max" -s "Realistic" # Using a YAML file: - python main_idea2video.py -f idea-example.yaml -c configs/myidea2video.yaml + python main_idea2video.py -f configs/idea-example.yaml -c configs/myidea2video.yaml # YAML file format: idea: | diff --git a/main_script2video.py b/main_script2video.py index 761a6ef4..f2d88218 100644 --- a/main_script2video.py +++ b/main_script2video.py @@ -29,7 +29,7 @@ def parse_args(): python main_script2video.py -S "EXT. GYM - DAY..." -u "15 shots max" -s "Anime Style" # Using a YAML file: - python main_script2video.py -f script-example.yaml + python main_script2video.py -f configs/script-example.yaml # YAML file format: script: |