Initial commit: organize Primary song slides repo

One folder per song under songs/. Tracks PPTX slide files and
Python generation scripts. PDFs and videos excluded (too large
for git; originals are in Google Drive).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-28 21:20:22 -06:00
commit 5a45320057
17 changed files with 788 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
import fitz
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
import io
PDF_PATH = r"C:\Users\jhodgkin\Documents\dev\primary-song-slides\MyFlagMyFlag-Color.pdf"
OUT_PATH = r"C:\Users\jhodgkin\Documents\dev\primary-song-slides\MyFlagMyFlag.pptx"
DPI = 96
SLIDE_W = Inches(13.333)
SLIDE_H = Inches(7.5)
TEXT_BOX_H = Inches(2.1)
FONT_SIZE = Pt(44)
TEXT_COLOR = RGBColor(0x0D, 0x27, 0x6D) # deep navy blue
# PDF pages 1-8 (0-based) map to the 8 lyric lines
# Page 0 is the overview thumbnail sheet — skip it
SLIDES = [
(1, "My flag, my flag, my country's flag,"),
(2, "I love to see you wave;"),
(3, "My flag, my flag, my country's flag,"),
(4, "The banner of the brave."),
(5, "Wave on, wave on forever,"),
(6, "The banner of the free;"),
(7, "Wave on, wave on forever,"),
(8, "The flag of liberty."),
]
def render_page(page):
mat = fitz.Matrix(DPI / 72, DPI / 72)
pix = page.get_pixmap(matrix=mat, alpha=False)
return io.BytesIO(pix.tobytes("jpeg", jpg_quality=85)), pix.width, pix.height
def add_slide(doc, prs, blank_layout, page_idx, lyric):
page = doc[page_idx]
img_bytes, pw, ph = render_page(page)
slide = prs.slides.add_slide(blank_layout)
aspect = pw / ph
h = SLIDE_H
w = int(h * aspect)
if w > SLIDE_W:
w = SLIDE_W
h = int(w / aspect)
left = (SLIDE_W - w) // 2
top = (SLIDE_H - h) // 2
slide.shapes.add_picture(img_bytes, left, top, width=w, height=h)
tb_top = SLIDE_H - TEXT_BOX_H
txBox = slide.shapes.add_textbox(Inches(0.25), tb_top, SLIDE_W - Inches(0.5), TEXT_BOX_H)
tf = txBox.text_frame
tf.word_wrap = True
lines = lyric.split("\n")
for i, line in enumerate(lines):
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
p.alignment = PP_ALIGN.CENTER
run = p.add_run()
run.text = line
run.font.bold = True
run.font.size = FONT_SIZE
run.font.color.rgb = TEXT_COLOR
print(f" Slide {len(prs.slides):2d} (pg {page_idx+1:2d}): {lyric[:60]}")
def main():
doc = fitz.open(PDF_PATH)
prs = Presentation()
prs.slide_width = SLIDE_W
prs.slide_height = SLIDE_H
blank_layout = prs.slide_layouts[6]
for page_idx, lyric in SLIDES:
add_slide(doc, prs, blank_layout, page_idx, lyric)
prs.save(OUT_PATH)
print(f"\nSaved: {OUT_PATH} ({len(SLIDES)} slides)")
if __name__ == "__main__":
main()