
Using Claude to Generate Song Service PowerPoint Files
Introduction
Since I’ve started using Claude Code as my primary software development tool, I’ve come to the conclusion that I’d much prefer to tell an AI agent what to do than to do the work myself. However, I’ve had significant trouble in the past getting an AI agent to generate PowerPoint files containing song lyrics, suitable for congregational singing. Yesterday, I finally found success and discovered a few things along the way. I wonder how long it’ll be before this becomes outdated?
My Method
Although I used Claude for everything, I used a mix of Claude products. I started out in Claude Desktop on Windows because Claude Code isn’t as good at generating PowerPoint—or so I’d heard. I created a project for my work so I could more easily keep track of assets.
Step 1
In this case, someone had emailed me a Word document containing the full program—songs and other items. I got Claude to extract the song list. So far, so good.
Step 2
Next, I asked Claude to obtain the lyrics for all of the songs. Most of them came from the Seventh-day Adventist Hymnal, and I was able to find a GitHub repository containing all the lyrics. However, online lyrics for the hymnal are often full of typos and sometimes diverge, possibly because they used some other source. For the other non-hymnal songs, I asked Claude to search the web for the lyrics and compare multiple sources to try to find a canonical version.
I gave it an output format and set it to work. Claude Desktop churned happily away, but eventually just stopped with a message that an error occurred and gave a retry button. There was no information as to the nature of the error. I retried multiple times, until Claude cleared my entire context and lost all of the work it had done. Thus, I no longer have my initial prompt.
Next, I tried asking Claude to process each song one at a time and ask for my approval between songs, in order to create a breakpoint and not lose everything in case of an error. But I hit the same error issue after a while.
Thinking there might be a problem with the desktop version, I moved to Claude Web. This time, I had learned to save the work I had done so far so that if I hit the error I wouldn’t have to redo everything. I was wondering if I was running into issues with context size, but that wasn’t the problem. Claude Web had the same issue.
Frustrated, I moved to my usual weapon of choice, Claude Code. I exported all of the files from the Claude Desktop/Web project into a directory on my local machine and set Claude to work. From this point, I have the prompts I used:
`song_list.md` contains a list of songs for which we need the lyrics. We need to obtain the lyrics for all of these songs and add them sequentially to a file. The file `lyrics.md` has many of the songs already done. You will be adding songs to that same file. Follow this procedure for each song:
1. Download the lyrics. For hymns, the text is in files in the directory `adventist_hymnal\raw_text`. For other songs, search the web for the lyrics. Compare multiple versions to establish the best possible version.
2. Review the lyrics. Change straight quotes to curly quotes, fix typos, fix incorrect line lengths, etc. For the song that was already done, you can observe how lines were corrected from the repo version.
3. Write the cleaned up version to the file.
4. Tell me about any fixes you made, then stop and wait for my approval.
5. Once I approve, continue to the next song.
You'll probably need to clean up mojibake in the file before you begin.
Mojibake? That’s a preview of a surprising issue explained below.
Claude Code set to work, and pretty soon hit the same error. This time, though, it told me what the error was, which I’ve prettified for readability.
// API Error: 400
{
"type":"error",
"error": {
"type":"invalid_request_error",
"message":"Output blocked by content filtering policy"
},
"request_id":"req_011CYGTWtyrBTW8k8QrN5dDx"
}
Why couldn’t the other Claude products tell me something useful? Why did I have to resort to Claude Code to find out the problem?
Once I knew that the problem was a particular song (I’ll explain more below), I was able to tell Claude to skip the problematic song and move on. Finally, I had all the lyrics—almost!
Step 3
Now that I had a lyrics file, I re-added it to the Claude Web project, and once again had Claude fix the mojibake. I then asked Claude to generate a PowerPoint file for me. At this point, it was simply a matter of refining the design. There was no drama, but it took a number of iterations to get something I loved.
This was awesome, because I was able to get a PowerPoint document from AI that I could actually use without modification. Except that it had a placeholder for the lyrics for that one problematic song, and I didn’t relish manually adding it. I also wanted a simpler process for the future. So, on to step 4.
But first, here’s the generated file.
Step 4
I noticed that Claude Web wrote a set of scripts to create the PowerPoint file.
- A Python script to manipulate the chosen images
- A JavaScript script to generate the PowerPoint file
- A Python script to post-process the PowerPoint file to make edits that the JS library didn’t support
So, I asked Claude Web to write those scripts to a Zip file and give me the file. Then, I unzipped the file to a directory on my machine and had Claude Code make the fixes needed for me to be able to run the scripts. These fixes were things like file paths, dependencies, documentation, and a package.json file to manage it all. I initialized a git repository and made a few other changes.
With all that in place, I was able to add just the lyrics of the problematic song and regenerate the PowerPoint, and all was great!
And now, if I want to regenerate this presentation, or another similar one, I have an easy tool. It has a lot of stuff hard-coded, but that’s easy enough to change with AI when the time comes.
You can check out the repository on GitHub if you like.
Issues
Copyright Issues
Copyright was interesting for this project. In my initial prompt, which was lost, I told Claude that most of the songs were in the public domain and that we had licenses for the others. Claude was perfectly fine with that.
When I had to rewrite the prompt, I forgot to say anything about copyright. Claude (Opus 4.6) examined the list of songs and told me that most of them were public domain and posed no problem, but that one of them was copyrighted. Claude then refused to download that song. When I told Claude that I had a license, it responded that this didn’t matter because it couldn’t verify the license, and at any rate its instructions wouldn’t allow it to reproduce copyrighted content regardless of whether I had a license. Fair enough.
Interestingly, though, Claude offered me a workaround: If I were to paste the lyrics into the chat instead of asking Claude to get them itself, then the copyright issue would be resolved as Claude would be merely transforming them. That seems a bit dubious from a legal standpoint, but nevertheless I used Claude’s workaround.
Problematic Song
The song that Claude had an issue with was “Were You There?” The error was “Output blocked by content filtering policy.” I chatted about this error with another Claude instance, which theorized that the lyrics might have triggered Claude’s rules against violence. It suggested that I use /bug in Claude Code to report this as a bug. Well, it turns out that /bug isn’t available in my version of Claude Code, and I couldn’t be bothered to investigate further.
My main issue is that I wish that Claude Desktop and Claude Web gave more useful error messages. At least Claude Code told me something I could use to work around the problem.
Character Set Issues
When moving files in and out of a project in Claude Desktop or Claude Web, Claude breaks the file encoding. For example, a dash (—) gets corrupted to — and an apostrophe (’) becomes ’. These corrupted characters are known as mojibake.
I thought this problem was solved many years ago, as systems agreed on character sets (mostly standardizing on Unicode). It’s probably been at least 15 years since I’ve encountered this issue in anything new. Yet Claude Desktop and Web keep creating it.
So, any time a file is moved in or out of those tools, I ended up having to ask Claude to fix the mojibake. In 2026.
Curly Quotes
I wanted my PowerPoint files to use curly quotes instead of straight quotes, so I wanted curly quotes to be in my input Markdown file. It turns out that when Claude Code uses its edit tool, it changes curly quotes into straight quotes. I had to point out the issue to Claude and watch as it tried to edit multiple times without success. It eventually ended up writing a Python script to edit the input Markdown file so that it could preserve the curly quotes.