Add generate-slides command for Keynote exports

Parses slide directories exported from Keynote and generates
slides.json with proper [S1], [S2], etc. mappings.

- Extracts slide numbers from filenames like Video1.001.png
- Supports png, gif, pdf, jpg formats
- Outputs slides.json in the same directory as images
- --type flag to set slide layout (default: square)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-12 11:31:47 +01:00
parent d5a8d38c9c
commit b347841634
+77
View File
@@ -1,6 +1,8 @@
"""CLI entry point for GnommoEditor.""" """CLI entry point for GnommoEditor."""
import argparse import argparse
import json
import re
import sys import sys
from pathlib import Path from pathlib import Path
@@ -69,6 +71,22 @@ def main() -> int:
help="Print FFmpeg command without executing", help="Print FFmpeg command without executing",
) )
# generate-slides command
gen_slides_parser = subparsers.add_parser(
"generate-slides",
help="Generate slides.json from Keynote export folder",
)
gen_slides_parser.add_argument(
"directory",
type=Path,
help="Path to slides directory (e.g., media/slides/Video1)",
)
gen_slides_parser.add_argument(
"--type",
default="square",
help="Slide type for all slides (default: square)",
)
args = parser.parse_args() args = parser.parse_args()
try: try:
@@ -77,6 +95,8 @@ def main() -> int:
elif args.command == "render": elif args.command == "render":
output = args.output or (args.project / "out" / "final.mp4") output = args.output or (args.project / "out" / "final.mp4")
return cmd_render(args.project, output, args.verbose, args.dry_run) return cmd_render(args.project, output, args.verbose, args.dry_run)
elif args.command == "generate-slides":
return cmd_generate_slides(args.directory, args.type)
except GnommoError as e: except GnommoError as e:
print(f"Error: {e}", file=sys.stderr) print(f"Error: {e}", file=sys.stderr)
return 1 return 1
@@ -154,5 +174,62 @@ def cmd_render(project_path: Path, output_path: Path, verbose: bool, dry_run: bo
return 0 return 0
def cmd_generate_slides(directory: Path, slide_type: str) -> int:
"""Generate slides.json from Keynote export folder."""
directory = directory.resolve()
if not directory.exists():
print(f"Error: Directory not found: {directory}", file=sys.stderr)
return 1
if not directory.is_dir():
print(f"Error: Not a directory: {directory}", file=sys.stderr)
return 1
# Find all image files (png, gif, pdf)
extensions = {".png", ".gif", ".pdf", ".jpg", ".jpeg"}
files = [f for f in directory.iterdir() if f.suffix.lower() in extensions]
if not files:
print(f"Error: No image files found in {directory}", file=sys.stderr)
return 1
# Extract numeric suffix from filenames like "Video1.001.png"
# Pattern: anything followed by .NNN. followed by extension
pattern = re.compile(r"\.(\d+)\.[^.]+$")
slides = {}
for file in files:
match = pattern.search(file.name)
if match:
num = int(match.group(1)) # "001" -> 1
slide_id = f"S{num}"
slides[slide_id] = {
"image": file.name,
"type": slide_type,
}
else:
print(f" Warning: Could not parse slide number from: {file.name}")
if not slides:
print("Error: No valid slide files found", file=sys.stderr)
return 1
# Sort by slide number
sorted_slides = dict(sorted(slides.items(), key=lambda x: int(x[0][1:])))
# Write slides.json in the same directory
output_path = directory / "slides.json"
with open(output_path, "w", encoding="utf-8") as f:
json.dump(sorted_slides, f, indent=2)
print(f"Generated {output_path}")
print(f" - Found {len(sorted_slides)} slides")
for slide_id, slide_def in sorted_slides.items():
print(f" [{slide_id}] {slide_def['image']}")
return 0
if __name__ == "__main__": if __name__ == "__main__":
sys.exit(main()) sys.exit(main())