How PPT Master Generates and Embeds Speaker Notes into PPTX Files
PPT Master automatically discovers Markdown files in the notes/ folder, converts them to plain text, and injects them as XML notes-slides into the final PPTX package during the SVG-to-PPTX conversion process.
PPT Master (hugohe3/ppt-master) is an open-source automation framework for building presentation decks from SVG assets. When generating output files, the tool handles speaker notes by reading optional Markdown documentation and embedding it directly into the Open XML structure, ensuring presenters have contextual annotations available in PowerPoint.
Discovering Markdown Notes Files
The discovery phase is orchestrated by pptx_discovery.find_notes_files in skills/ppt-master/scripts/svg_to_pptx/pptx_discovery.py. This function scans the project/notes/*.md path and constructs a dictionary mapping SVG file stems to their corresponding notes content.
Filename-Based and Index-Based Matching
The system supports two strategies to pair notes with slides:
- Filename-based matching (preferred): A notes file named
01_cover.mdautomatically pairs with01_cover.svgbased on identical stem names. - Index-based matching (legacy fallback): Files named
slide01.mdorslide_1.mdmap to the first SVG in the sequence.
The implementation uses regex to detect index patterns while prioritizing exact stem matches:
# skills/ppt-master/scripts/svg_to_pptx/pptx_discovery.py
def find_notes_files(project_path: Path, svg_files: list[Path] | None = None) -> dict[str, str]:
...
for notes_file in notes_dir.glob('*.md'):
stem = notes_file.stem
# Index-based match
match = re.search(r'slide[_]?(\d+)', stem)
...
# Filename-based match (overrides index-based)
if stem in svg_stems_mapping:
notes[stem] = content
The CLI entry point in pptx_cli.py controls this behavior via the --no-notes flag:
enable_notes = not args.no_notes
notes: dict[str, str] = {}
if enable_notes:
notes = find_notes_files(project_path, svg_files)
Converting Markdown Syntax to Plain Text
Once discovered, raw Markdown content must be sanitized for the PPTX format. The pptx_notes.markdown_to_plain_text function in skills/ppt-master/scripts/svg_to_pptx/pptx_notes.py strips formatting syntax—converting headings, bold markers, and list bullets into clean plain text while collapsing empty lines.
# skills/ppt-master/scripts/svg_to_pptx/pptx_notes.py
def markdown_to_plain_text(md_content: str) -> str:
...
for line in md_content.split('\n'):
if line.startswith('#'):
text = re.sub(r'^#+\s*', '', line).strip()
...
elif line.strip().startswith('- '):
...
else:
...
Constructing the Notes-Slide XML
PPTX files store speaker notes as separate XML documents linked to their parent slides. PPT Master generates these via two dedicated helpers in pptx_notes.py:
create_notes_slide_xml(slide_num, notes_text): Builds the<p:notes>root element containing<a:p>paragraphs for each line of text.create_notes_slide_rels_xml(slide_num): Generates the relationship file defining connections to the slide master and the corresponding slide.
These functions produce the exact Open XML markup required by the Office Open XML specification.
Injecting Notes into the PPTX Package
The final assembly occurs inside pptx_builder.create_pptx_with_native_svg within skills/ppt-master/scripts/svg_to_pptx/pptx_builder.py. During the per-slide iteration, the system conditionally writes notes files when enable_notes is true and content exists for the current SVG stem.
The process creates the necessary directory structure, writes the XML documents, and registers relationships:
# skills/ppt-master/scripts/svg_to_pptx/pptx_builder.py (excerpt)
if enable_notes:
svg_stem = svg_path.stem
notes_content = notes.get(svg_stem, '') if notes else ''
notes_text = markdown_to_plain_text(notes_content) if notes_content else ''
if notes_text:
notes_slides_dir = extract_dir / 'ppt' / 'notesSlides'
notes_slides_dir.mkdir(exist_ok=True)
notes_xml_path = notes_slides_dir / f'notesSlide{slide_num}.xml'
notes_xml = create_notes_slide_xml(slide_num, notes_text)
with open(notes_xml_path, 'w', encoding='utf-8') as f:
f.write(notes_xml)
notes_rels_dir = notes_slides_dir / '_rels'
notes_rels_dir.mkdir(exist_ok=True)
notes_rels_path = notes_rels_dir / f'notesSlide{slide_num}.xml.rels'
notes_rels_xml = create_notes_slide_rels_xml(slide_num)
with open(notes_rels_path, 'w', encoding='utf-8') as f:
f.write(notes_rels_xml)
_append_relationship(
rels_path,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide',
f'../notesSlides/notesSlide{slide_num}.xml',
)
The _append_relationship helper inserts the requisite <Relationship> entry into the slide's .rels file, establishing the link between the slide and its notes.
Command-Line Controls
By default, notes processing is enabled. Users can explicitly disable it using the --no-notes flag:
python -m skills.ppt-master.scripts.svg_to_pptx.pptx_cli \
examples/ppt169_demo \
-s final \
--no-notes # Skip notes discovery and embedding
When notes are present and processed, the CLI displays a “+notes” indicator alongside the slide progress output.
Summary
- PPT Master treats speaker notes as optional Markdown files located in the
notes/directory. - The
find_notes_filesfunction maps note files to SVG slides using filename or index matching. markdown_to_plain_textsanitizes content by removing Markdown syntax before XML generation.- Two XML components are created: the notes slide (
<p:notes>) and its relationship file. pptx_builder.pyembeds these into the PPTX package underppt/notesSlides/and updates slide relationships.- Use
--no-notesto disable the entire pipeline.
Frequently Asked Questions
What file format does PPT Master use for speaker notes?
PPT Master expects speaker notes as Markdown files (.md) stored in the project's notes/ folder. The content is automatically converted to plain text during the PPTX generation process to ensure compatibility with PowerPoint's native notes format.
How does PPT Master match notes to specific slides?
The system attempts filename-based matching first, pairing slide_name.md with slide_name.svg. If no exact match exists, it falls back to index-based matching, interpreting filenames like slide01.md or slide_1.md as corresponding to the first SVG in the sequence. This logic is implemented in pptx_discovery.py.
Can I disable speaker notes generation?
Yes. Pass the --no-notes flag to the CLI command, or set enable_notes=False when calling create_pptx_with_native_svg programmatically. When disabled, the system skips discovery, parsing, and XML generation entirely, producing a PPTX file without speaker notes.
Where are speaker notes stored inside the generated PPTX?
Speaker notes reside in the ppt/notesSlides/ directory within the PPTX archive (which is a ZIP file). Each slide with notes has a corresponding notesSlide{number}.xml file and a notesSlide{number}.xml.rels file in the _rels subdirectory. You can inspect these by unzipping the .pptx file or using command-line tools like unzip -p output.pptx ppt/notesSlides/notesSlide1.xml.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →