In my previous post, I showed how to create a RSS feed using WCF Syndication. Next, I'll show how to add the additional tags needed to turn a RSS feed into an iTunes podcast.
A podcast is merely a RSS feed with some special characteristics:
iTunes RSS tags. These are additional tags beyond the standard RSS spec. Apple has a good page on the requirements.
Audio file enclosure. This is a link to the audio file (such as mp3) hosted by your site. Apple doesn't host the audio, they just read the meta-data from the RSS feed into their system.
The SyndicationFeed class supports both AttributeExtensions & ElementExtensions to add custom tags to the RSS feeds.
A couple of points of interest in the code below:
The imageUrl below provides the album cover for iTunes (170px × 170px)
Each SyndicationItem corresponds to an audio episode in your podcast
So, here's the code:
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
1: XNamespace itunesNS = "http://www.itunes.com/dtds/podcast-1.0.dtd";
2: string prefix = "itunes";
3:
4: var feed = new SyndicationFeed(title, description, new Uri(link));
5: feed.Categories.Add(new SyndicationCategory(category));
6: feed.AttributeExtensions.Add(new XmlQualifiedName(prefix,
7: "http://www.w3.org/2000/xmlns/"), itunesNS.NamespaceName);
8: feed.Copyright = new TextSyndicationContent(copyright);
9: feed.Language = "en-us";
10: feed.Copyright = new TextSyndicationContent(DateTime.Now.Year + " " + ownerName);
11: feed.ImageUrl = new Uri(imageUrl);
12: feed.LastUpdatedTime = DateTime.Now;
13: feed.Authors.Add(new SyndicationPerson() {Name=ownerName, Email=ownerEmail });
14: var extensions = feed.ElementExtensions;
15: extensions.Add(new XElement(itunesNS + "subtitle", subTitle).CreateReader());
16: extensions.Add(new XElement(itunesNS + "image",
17: new XAttribute("href", imageUrl)).CreateReader());
18: extensions.Add(new XElement(itunesNS + "author", ownerName).CreateReader());
19: extensions.Add(new XElement(itunesNS + "summary", description).CreateReader());
20: extensions.Add(new XElement(itunesNS + "category",
21: new XAttribute("text", category),
22: new XElement(itunesNS + "category",
23: new XAttribute("text", subCategory))).CreateReader());
24: extensions.Add(new XElement(itunesNS + "explicit", "no").CreateReader());
25: extensions.Add(new XDocument(
26: new XElement(itunesNS + "owner",
27: new XElement(itunesNS + "name", ownerName),
28: new XElement(itunesNS + "email", ownerEmail))).CreateReader());
29:
30: var feedItems = new List<SyndicationItem>();
31: foreach (var i in Items)
32: {
33: var item = new SyndicationItem(i.title, null, new Uri(link));
34: item.Summary = new TextSyndicationContent(i.summary);
35: item.Id = i.id;
36: if (i.publishedDate != null)
37: item.PublishDate = (DateTimeOffset)i.publishedDate;
38: item.Links.Add(new SyndicationLink() {
39: Title = i.title, Uri = new Uri(link),
40: Length = i.size, MediaType = i.mediaType });
41: var itemExt = item.ElementExtensions;
42: itemExt.Add(new XElement(itunesNS + "subtitle", i.subTitle).CreateReader());
43: itemExt.Add(new XElement(itunesNS + "summary", i.summary).CreateReader());
44: itemExt.Add(new XElement(itunesNS + "duration",
45: string.Format("{0}:{1:00}:{2:00}",
46: i.duration.Hours, i.duration.Minutes, i.duration.Seconds)
47: ).CreateReader());
48: itemExt.Add(new XElement(itunesNS + "keywords", i.keywords).CreateReader());
49: itemExt.Add(new XElement(itunesNS + "explicit", "no").CreateReader());
50: itemExt.Add(new XElement("enclosure", new XAttribute("url", i.url),
51: new XAttribute("length", i.size), new XAttribute("type", i.mediaType)));
52: feedItems.Add(item);
53: }
54:
55: feed.Items = feedItems;
If you're hosting your podcast feed within a MVC project, you can use the code from my previous post to stream it.
Once you have created your feed, you can use the Feed Validator tool to make sure it is up to spec. Or you can use iTunes:
Launch iTunes.
In the Advanced menu, select Subscribe to Podcast.
Enter your feed URL in the text box and click OK.
After you've verified your feed is solid & good to go, you can submit it to iTunes.
Launch iTunes.
In the left navigation column, click on iTunes Store to open the store.
Once the store loads, click on Podcasts along the top navigation bar to go to the Podcasts page.
In the right column of the Podcasts page, click on the Submit a Podcast link.
Follow the instructions on the Submit a Podcast page.
Here are the full instructions. Once they have approved your podcast, it will be available within iTunes.
RIM has also gotten into the podcasting business...which is great for BlackBerry users. They accept the same enhanced-RSS feed that iTunes uses, so just create an account with them & submit the feed's URL. It goes through a similar approval process to iTunes. BlackBerry users must be on BlackBerry 6 OS or download the Podcast App from App World.
In my next post, I'll show how to build the podcast feed dynamically from the ID3 tags within the MP3 files.