Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions submissions/podcast-generation-agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Podcast Generation Agent

Turn a topic or source material such as newsletters, articles, reports, and notes into a two-host podcast episode. The agent produces a readable transcript, multi-voice SSML, and optional narrated audio.

## Agent

The agent uses two recurring hosts with distinct voices and conversational roles. It organizes source material into segments, targets the requested episode length, and produces TTS-ready output without narration-style prose.

## Tools and skills

- The podcast script skill analyzes and ranks source material, writes the dialogue, and generates SSML.
- The Azure Text to Speech connector converts the SSML into a WAV audio file when requested.
- Web search is enabled to support requests that require current source material.

## Import notes

- Import the solution into a Copilot Studio environment.
- Configure the included Azure Text to Speech connection reference during import.
- Ensure the connected Speech resource can use `en-US-AvaMultilingualNeural` and `en-US-AndrewMultilingualNeural`, or update the agent to use available neural voices.
- Review the agent and connection configuration before publishing. The exported solution is configured to publish on import.
17 changes: 17 additions & 0 deletions submissions/podcast-generation-agent/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "Podcast Generation Agent",
"description": "Turns topics, newsletters, articles, and notes into a two-host podcast with a transcript, multi-voice SSML, and optional narrated audio.",
"tags": [
"content",
"podcast",
"audio",
"text-to-speech",
"ssml"
],
"author": "Remi Dyon",
"authorUrl": "https://github.com/raemone",
"authorGithub": "raemone",
"createdAt": "2026-07-28",
"updatedAt": "2026-07-28",
"featured": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<botcomponent_connectionreferenceset>
<botcomponent_connectionreference botcomponentid.schemaname="cr88d_podcastdemo_OMpe9u.tool.ConverttexttospeechwithSSML_VGp" connectionreferenceid.connectionreferencelogicalname="cr88d_podcastdemo_OMpe9u.cr.shared_azuretexttospeech.05570216-c221-4c89-b8db-91dc3749dcde">
<iscustomizable>1</iscustomizable>
</botcomponent_connectionreference>
</botcomponent_connectionreferenceset>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="xml" ContentType="application/octet-stream" /><Default Extension="md" ContentType="application/octet-stream" /><Default Extension="json" ContentType="application/octet-stream" /><Override PartName="/botcomponents/cr88d_podcastdemo_OMpe9u.skill.generating-podcast-script_Jt6/data" ContentType="application/octet-stream" /><Override PartName="/botcomponents/cr88d_podcastdemo_OMpe9u.tool.ConverttexttospeechwithSSML_VGp/data" ContentType="application/octet-stream" /></Types>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<botcomponent schemaname="cr88d_podcastdemo_OMpe9u.file.metadatajson_3bwQq">
<componenttype>14</componenttype>
<filedata mimetype="application/json">metadata.json</filedata>
<iscustomizable>0</iscustomizable>
<name>./metadata.json</name>
<parentbotcomponentid>
<schemaname>cr88d_podcastdemo_OMpe9u.skill.generating-podcast-script_Jt6</schemaname>
</parentbotcomponentid>
<parentbotid>
<schemaname>cr88d_podcastdemo_OMpe9u</schemaname>
</parentbotid>
<statecode>0</statecode>
<statuscode>1</statuscode>
</botcomponent>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "Podcast Script Generator",
"description": "Turn a topic or a pile of source material \u2014 a newsletter, news digest, or set of articles \u2014 into a two-host, NotebookLM-style podcast episode, with multi-voice SSML and optional Azure Text-to-Speech audio.",
"platforms": ["Copilot Studio"],
"tags": ["content", "podcast", "audio", "text-to-speech", "ssml", "news"],
"author": "Remi Dyon",
"authorUrl": "https://github.com/remidyon",
"version": "1.1.0",
"createdAt": "2026-07-28",
"updatedAt": "2026-07-28"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<botcomponent schemaname="cr88d_podcastdemo_OMpe9u.file.readmemd_jxKnE">
<componenttype>14</componenttype>
<filedata mimetype="application/octet-stream">README.md</filedata>
<iscustomizable>0</iscustomizable>
<name>./README.md</name>
<parentbotcomponentid>
<schemaname>cr88d_podcastdemo_OMpe9u.skill.generating-podcast-script_Jt6</schemaname>
</parentbotcomponentid>
<parentbotid>
<schemaname>cr88d_podcastdemo_OMpe9u</schemaname>
</parentbotid>
<statecode>0</statecode>
<statuscode>1</statuscode>
</botcomponent>
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Podcast Script Generator

Turn a topic — or a pile of source material like a newsletter, a news digest, or
a set of articles — into a two-host podcast episode that actually sounds like
two people talking. You get a readable transcript, a multi-voice SSML document,
and optionally a narrated `.wav`.

## What you get

- **Two recurring hosts with distinct personalities.** *Nova* is the warm, quick
lead host who asks the question you're thinking. *Miles* is the dry, precise
analyst who supplies the numbers and the caveats. They talk to each other, not
at the microphone — no narrator voice, no "welcome to the podcast".
- **Real editorial judgement on source material.** Feed it a digest and it
parses out each distinct item, merges duplicates, throws away footers and
unsubscribe boilerplate, ranks what's left by newsworthiness, gives the top
4–6 full segments, and sweeps the rest into a rapid-fire round.
- **Conversational dialogue, not read-aloud prose.** Short lines, contractions,
genuine reactions, one concrete analogy per complex idea, and a naive
clarifying question whenever something needs unpacking.
- **TTS-ready output.** Numbers and acronyms are spelled out the way a
synthesizer needs them, and the SSML uses one `<voice>` per turn with per-line
prosody so the delivery never goes flat.

## Before you start

- **Copilot Studio** — this skill targets the Copilot Studio Python/Linux
container and writes into `/app/created/`.
- **Azure Text-to-Speech connector** — the audio step calls the
`ConverttexttospeechwithSSML` tool. Add it to your agent (Actions → Add an
action → Azure Text to Speech) before asking for audio. Without it you still
get the transcript and the SSML file; only the narration step is skipped.
- **Multi-voice SSML** — the default cast uses `en-US-AvaMultilingualNeural` and
`en-US-AndrewMultilingualNeural`. Your Speech resource needs access to those
neural voices.

## How to use it

Paste or point at your material and ask:

> Here's this week's AI newsletter. Make it a six-minute podcast and give me the
> audio.

> Turn these five articles into a Nova and Miles episode, short version.

Or skip the source material entirely and just give it a topic:

> Do a twelve-minute episode on the history of submarines.

The agent will parse and rank the material, write the transcript to
`/app/created/<slug>_Podcast_Script.txt` and the SSML to
`/app/created/<slug>_Podcast.ssml`, show you a segment-by-segment summary, then
offer to narrate it into `/app/created/<slug>_Podcast.wav`.

## Good to know

- **Length is a real target, not a suggestion.** Everything is budgeted at ~150
spoken words per minute and the agent aims to land within 10 percent. Six
minutes is roughly 900 words of dialogue.
- **It won't invent opinions.** Reactions to facts are fair game ("that number
is wild"); made-up takes on people, companies, or politics are not. Unconfirmed
claims get flagged out loud on air.
- **Two files, two audiences.** The `.txt` transcript carries `NOVA:` / `MILES:`
labels so you can read along. The `.ssml` is the machine artifact — nothing
but the SSML document, ready to hand straight to the TTS connector.
- **Long episodes and the 40k character cap.** The SSML is kept under 40,000
characters. If an episode is too big for one synthesis call, the agent splits
at a segment boundary and stitches the audio back together.
- **Customising the cast.** Ask for different voices, different names, or a
single host and it'll adapt — the Nova/Miles pairing is just the default.
- **Non-English material.** Foreign names and phrases inside an English line get
wrapped in a `<lang>` tag so they're pronounced properly. For a fully
non-English episode, say so and specify matching neural voices.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<botcomponent schemaname="cr88d_podcastdemo_OMpe9u.file.skillmd_A9jgI">
<componenttype>14</componenttype>
<filedata mimetype="application/octet-stream">SKILL.md</filedata>
<iscustomizable>0</iscustomizable>
<name>./SKILL.md</name>
<parentbotcomponentid>
<schemaname>cr88d_podcastdemo_OMpe9u.skill.generating-podcast-script_Jt6</schemaname>
</parentbotcomponentid>
<parentbotid>
<schemaname>cr88d_podcastdemo_OMpe9u</schemaname>
</parentbotid>
<statecode>0</statecode>
<statuscode>1</statuscode>
</botcomponent>
Loading
Loading