]> sipb.mit.edu Git - ikiwiki.git/blob - doc/todo/fancypodcast.mdwn
merge schmonz/fancypodcast
[ikiwiki.git] / doc / todo / fancypodcast.mdwn
1 ikiwiki's simple podcasting, while elegant and minimal, doesn't (as
2 mentioned in [[todo/blogging]]) produce full-featured feeds. In
3 fancy podcasts, episodes are accompanied by text content. The feeds
4 also have lots more metadata.
5
6 [[!toc]]
7
8 ## Status
9
10 [[!template id=gitbranch branch=schmonz/fancypodcast author="[[schmonz]]"]]
11 [[!tag patch]]
12
13 In summary, the branch preserves ikiwiki's existing podcast behavior,
14 adds more featureful behavior, and has been tested to work well in
15 some common podcatchers. I believe it is ready for integration.
16 --[[schmonz]]
17
18 ## Features
19
20 [[!table data="""
21 Feature            |iTunes RSS|iTunes Atom|Downcast RSS|Downcast Atom
22 Feed image         |          |           |            |
23 Feed title         |(./)      |(./)       |(./)        |(./)
24 Feed publisher     |          |           |            |
25 Feed "category"    |          |           |            |
26 Feed date          |(./)      |(./)       |(./)        |(./)
27 Feed description   |(./)      |(./)       |(./)        |
28 Episode image      |          |           |            |
29 Episode title      |(./)      |(./)       |(./)        |(./)
30 Episode date       |(./)      |(./)       |(./)        |(./)
31 Episode duration   |          |           |            |
32 Episode author     |          |           |            |
33 Episode description|(./)      |(./)       |(./)        |
34 Episode enclosure  |(./)      |(./)       |(./)        |(./)
35 """]]
36
37 ## Design
38
39 7. For each fancy podcast episode, write a blog post containing
40    `\[[!meta enclosure="WikiLink/to/media.mp3"]]`. (Don't specify
41    more than one enclosure -- but if you do, last one wins.)
42 7. When rendering to HTML (single-page or inlined), append a link
43    to the media file.
44 7. When rendering to RSS/Atom, the text is the entry's content and
45    the media file is its enclosure.
46 7. Don't break simple podcasts in pursuit of fancy podcasts.
47
48 ## Implementation
49
50 ### Completed
51
52 * Cover the existing simple podcast behavior with tests.
53 * Add an `enclosure` field to [[plugins/meta]] that expands the
54   given [[ikiwiki/WikiLink]] to an absolute URL (feed enclosures
55   pretty much need to be, and the reference feeds I've looked at
56   all do this).
57 * Write failing tests for the desired single-page and inlined
58   HTML behavior, then make them pass by adding enclosure stanzas
59   to `{,inline}page.tmpl`.
60 * Write failing tests for the desired RSS/Atom behavior, then make
61   them pass via changes to `{atom,rss}item.tmpl` and [[plugins/inline]].
62 * Match feature-for-feature with
63   [tru_podcast](http://www.rainskit.com/blog/542/tru_podcast-a-podcasting-plugin-for-textpattern)
64   (what [[schmonz]] will be migrating from).
65 * Enrich [feed metadata](http://cyber.law.harvard.edu/rss/rss.html)
66   by catching up `rsspage.tmpl` to `atompage.tmpl`.
67 * Verify that [[plugins/more]] plays well with fancy podcasts.
68 * Verify that the feeds validate.
69 * Subscribe to a fancy feed in some common podcatchers and verify
70   display details against a reference podcast.
71 * Verify smooth transitions for two common use cases (see testing
72   details below).
73 * Code review: don't add enclosure divs unless we have enclosures.
74 * Code review: genericize download link for more use cases.
75 * Code review: don't confuse old readers with Atom names in RSS.
76 * Code review: instead of hacking back to `$link`, just provide it.
77 * Code review: show author in addition to feedname, if different.
78
79 ### Must-have (for [[schmonz]], anyway)
80
81 * Think carefully about UTF-8.
82 * Verify that _all_ the tests pass (not just my new ones).
83
84 ## Migration
85
86 ### Upgrading within ikiwiki: from simple to fancy
87
88 #### My test podcast
89
90 For this test, I chose a podcast that tries to work around ikiwiki's
91 current limitations by issuing two separate `inline`s:
92
93 * One with `feedonly=yes` that includes `.mdwn`, `.pdf`, and `.mp3`
94 * One with `feeds=no` that includes only `.mdwn` (and makes a trail)
95
96 This has the following effects:
97
98 * Browser: sees just the articles (each of which has a manually
99   created link to its corresponding media file)
100 * Feedreader: sees all the articles and media in one flat stream
101 * Podcatcher: sees just the media (sans articles)
102
103 I want instead to write one `inline` with these effects:
104
105 * Browser: sees just the articles (each of which automatically links
106   to its enclosure)
107 * Feedreader: sees just the articles (each of which specifies its
108   enclosure)
109 * Podcatcher: sees just the enclosures (each of which has an enclosing
110   article, rendered as the media's "description")
111
112 #### Upgrade steps
113
114 7. Set up a non-production copy of the podcast.
115     7. Visually diff RSS and Atom feeds against production.
116     7. Subscribe to the copy (both feeds) in `r2e`, iTunes, Downcast.
117 7. Apply fancypodcast patch to the installed ikiwiki:
118     7. `cd ~/Documents/trees/ikiwiki && git checkout fancypodcast`
119     7. `git diff --no-prefix master > ~/Documents/trees/localpatches/www/ikiwiki/fancypodcast.diff`
120     7. `cd ~/Documents/trees/pkgsrc-current/www/ikiwiki && make deinstall && make install clean`
121 7. Verify that simple podcasts are unaffected:
122     7. Rerun `ikiwiki --setup`.
123     7. `diff -uB simple-before.rss simple-after.rss`
124         * A few new elements and attributes, as expected.
125     7. `diff -uB simple-before.atom simple-after.atom`
126         * No change.
127 7. Remove the feed-only `inline` and enable feeds on the remaining one.
128 7. Convert articles' manual download links to `\[[!meta enclosure=""]]`.
129 7. I want existing and future podcatchers to get my new fancy
130    episodes, and I know my podcast isn't in any planets, so I'm
131    going to skip [[tips/howto avoid flooding aggregators]].
132 7. Rerun `ikiwiki --setup`.
133 7. Verify browser shows the same stuff.
134 7. `diff -uB simple-after.rss fancy-after.rss   # and atom`
135     * MP3s and PDFs are no longer naked enclosures, but belong to
136       articles as they should.
137     * Articles have updated modification times, as they should.
138 7. `r2e run` (both RSS and Atom)
139     * Nothing new with the default `trust-guid = True` (otherwise
140       would expect updated articles).
141 7. iTunes "Update Podcast" (both RSS and Atom)
142     * Added one episode per article, with article text as the episode
143       description.
144     * Kept old naked-enclosure episodes around.
145 7. Downcast refresh (RSS):
146     * Added one episode per article, with article text as the episode
147       description.
148     * Kept old naked-enclosure episodes around.
149 7. Downcast refresh (Atom):
150     * Added one episode per article, with no episode description
151       (expected, see feature table).
152     * Kept old naked-enclosure episodes around.
153
154 Different tradeoffs are possible. These seem okay to me.
155
156 ### Importing into ikiwiki: fancy (from another CMS)
157
158 #### My test podcast
159
160 For this test, I chose a podcast currently being published with
161 Textpattern and tru_podcast, because I'd strongly prefer to publish
162 it with ikiwiki instead.
163
164 #### Upgrade steps
165
166 7. Set up a non-production copy of the podcast.
167     7. Visually diff RSS and Atom feeds against production.
168     7. Subscribe to the copy (both feeds) in `r2e`, iTunes, Downcast.
169 7. With a fancypodcast-enabled ikiwiki installed:
170     7. Copy content from Textpattern to ikiwiki:
171         7. Match article paths to preserve `/YYYY/MM/DD/post-title` permalinks.
172         7. Match enclosure paths (or redirect) to preserve Textpattern's URLs.
173         7. Match titles, post dates, and guids with `\[[!meta]]`.
174             7. Match feed paths with permanent redirects from `/atom/` to
175            `/index.atom` (and same for RSS).
176         7. `\[[!inline]]` the articles.
177     7. Rerun `ikiwiki --setup`.
178 7. Stop Textpattern, start ikiwiki.
179 7. Verify that podcatchers see the feeds and don't redownload anything.
180 7. Naively add two new blog posts, one with an enclosure.
181 7. Verify that podcatchers download the new enclosures.
182
183 -----
184
185 ## Future improvements
186
187 ### iTunes fancy podcasting
188
189 * [iTunes-specific tags](https://www.apple.com/itunes/podcasts/specs.html)
190   appear to be RSS-only
191     * If they work in Atom, teach `inline` to optionally iTunesify RSS/Atom.
192     * Else, add `itunes` as a third kind of feed (RSS plus more stuff).
193 * Notable tags for feeds:
194     * `itunes:subtitle`
195     * `itunes:author`
196     * `itunes:summary` (same as `description`)
197     * `itunes:owner` (includes `itunes:name` and `itunes:email`)
198     * `itunes:image href=''`
199     * `itunes:publisher`
200     * `itunes:category text=''` (can contain subcategories)
201     * `itunes:keywords`
202 * Notable tags for entries:
203     * `itunes:duration`
204         * [[!cpan Audio::TagLib]] might be fastest, if present and applicable
205         * [ffprobe](http://ffmpeg.org/ffprobe.html) is reasonably fast
206         * [mediainfo](http://mediainfo.sourceforge.net/) is way slower
207         * Cache computed durations as pagestate
208
209 ### Fancy podcast aggregating
210
211 * Write tests comparing a fancy podcast (HTML and feeds) against
212   the same podcast aggregated and republished, then make them pass
213   via changes to `aggregatepost.impl` and [[plugins/aggregate]].
214
215 ### Other ideas
216
217 * Don't render template text (e.g., "Use this template to insert a
218   note into a page") in feeds.
219 * Optionally specify the enclosure's:
220     * MIME type, in case `File::MimeInfo` guesses wrong.
221     * Duration, in case `ffprobe` guesses wrong.
222 * Optionally specify enclosures outside the wiki:
223     * Some people don't want to store big unchanging files in the VCS.
224     * Other people like [podcasting found media](http://huffduffer.com/about).
225     * We'd have to download the file just to compute some metadata
226       about it, and then somehow not frequently re-download it.
227 * Configurably generate additional subscription links (such as
228   iTunes) alongside the RSS/Atom ones in [[plugins/inline]].
229 * Support Apple's "enhanced podcasts" (if they're still relevant).
230
231 ### code review
232
233         +                               # XXX better way to compute relative to srcdir?
234         +                               my $file = $absurl;
235         +                               $file =~ s|^$config{url}/||;
236
237 I don't think ikiwiki offers a better way to do that, because there is
238 normally no reason to do that. Why does it need an url of this form here?
239 --[[Joey]] 
240
241 > In all the popular, production-quality podcast feeds I've looked
242 > at, enclosure URLs are always absolute (even when they could be
243 > expressed concisely as relative). [Apple's
244 > example](http://www.apple.com/itunes/podcasts/specs.html#example)
245 > does too. So I told \[[!meta]] to call `urlto()` with the third
246 > parameter true, which means the \[[!inline]] code here gets an
247 > absolute URL in `$pagestate{$p}{meta}{enclosure}`. To compute the
248 > enclosure's metadata, though, we of course need it as a local path.
249 > I didn't see a less
250 > [ongepotchket](http://www.jewish-languages.org/jewish-english-lexicon/words/1402)
251 > way at the time. If you have a better idea, I'm happy to hear it;
252 > if not, I'll add an explanatory comment. --[[schmonz]]
253
254 >> I would be more comfortable with this if two two different forms of url
255 >> you need were both generated by calling urlto. It'd be fine to call
256 >> it more than once. --[[Joey]]
257
258 >>> Heh, it was even easier than that! (Hooray for tests.) Done.
259 >>> --[[schmonz]]
260
261         +<TMPL_IF HTML5><section id="inlineenclosure"><TMPL_ELSE><div id="inlineenclosure"></TMPL_IF>
262         +<TMPL_IF ENCLOSURE>
263
264 Can't we avoid adding this div when there's no enclosure? --[[Joey]]
265
266 > Sure, I've moved the `<TMPL_IF ENCLOSURE>` check to outside the
267 > section-and-div block for `{,inline}page.tmpl`. --[[schmonz]]
268
269         +<a href="<TMPL_VAR ENCLOSURE>">Download this episode</a>
270
271 "Download this episode" is pretty specific to particular use cases.
272 Can this be made more generic, perhaps just "Download"? --[[Joey]] 
273
274 > Yep, I got a little carried away. Done. --[[schmonz]]
275
276         -<TMPL_IF AUTHOR>
277         -       <title><TMPL_VAR AUTHOR ESCAPE=HTML>: <TMPL_VAR TITLE></title>
278         -       <dcterms:creator><TMPL_VAR AUTHOR ESCAPE=HTML></dcterms:creator>
279
280 This change removes the author name from the title of the rss feed, which
281 does not seem necessary for fancy podcasts. And it is a change that
282 could negatively impact eg, Planet style aggregators using ikiwiki. --[[Joey]]
283
284 > While comparing how feeds render in podcatchers, I noticed that
285 > RSS and Atom were inconsistent in a couple ways, of which this was
286 > one. The way I noticed it: with RSS, valuable title space was being
287 > spent to display the author. I figured Atom's display was the one
288 > worth matching. You're right, of course, that planets using the
289 > default template and somehow relying on the current author-in-the-title
290 > rendering for RSS feeds (but not Atom feeds!) would be broken by
291 > this change. I'm having trouble imagining exactly what would break,
292 > though, since guids and timestamps are unaffected. Would it suffice
293 > to provide a note in the changelog warning people to be careful
294 > upgrading their planets, and to customize `rssitem.tmpl` if they
295 > really prefer the old behavior (or don't want to take any chances)?
296 > --[[schmonz]]
297
298 >> A specific example I know of is updo.debian.net, when used with
299 >> rss2email. Without the author name there, one cannot see who posted
300 >> an item. It's worth noting that planet.debian.org does the same thing
301 >> with its rss feed. (That's probably what I copied.) Atom feeds may
302 >> not have this problem, don't know. --[[Joey]]
303
304 >>> Okay, that's easy to reproduce. It looks like this _might_ be
305 >>> a simple matter of getting \[[!aggregate]] to populate author in
306 >>> `add_page()`. I'll see what I can figure out. --[[schmonz]]
307
308 >>>> Yep, that was mostly it. If the feed entry defines an author,
309 >>>> and the author is distinct from the feed name, we now show `NAME:
310 >>>> AUTHOR`, else just show `NAME` (same as always). In addition,
311 >>>> the W3 feed validator says `<dcterms:creator>` is invalid, so
312 >>>> I replaced it with `<dc:creator>`, and all of a sudden `r2e`
313 >>>> gives me better `From:` headers. With the latest on my branch,
314 >>>> when I generate the same planet as updo and run `r2e` over it,
315 >>>> the names I get in `From:` look like so:
316
317 *  `"updo: Junio C Hamano"`
318 *  `"updo: Greg Kroah-Hartman"`
319 *  `"updo: Eric Raymond: esr"` (article author != feed name, so we get both)
320 *  `"updo: Jannis Pohlman: Jannis Pohlmann"` (oops! I tweaked the real updo)
321
322 >>>> --[[schmonz]]
323
324         +++ b/templates/rsspage.tmpl
325         +       xmlns:atom="http://www.w3.org/2005/Atom"
326         +<atom:link href="<TMPL_VAR FEEDURL>" rel="self" type="application/rss+xml" />
327
328 Why is it using atom namespace inside an rss feed? What are the chances
329 every crummy rss reader on earth is going to understand this? I'd put it at
330 about 0%; I doubt ikiwiki's own rss reader understands such a mashup.
331 --[[Joey]]
332
333 > The validator I used (<http://validator.w3.org/feed/>) told me to.
334 > Pretty sure it doesn't make anything work better in the podcatchers
335 > I tried. Hadn't considered that it might break some readers.
336 > Removed. --[[schmonz]]
337
338         +<generator>ikiwiki</generator>
339
340 Does this added tag provide any benefits? --[[Joey]]
341
342 > Consistency with the Atom feed, and of course it trumpets ikiwiki
343 > to software and/or curious humans who inspect their feeds. The tag
344 > arrived only in RSS 2.0, but that's already the version we're
345 > claiming to be, and it's over a decade old. Seems much less risky
346 > than the atom namespace bits. --[[schmonz]]
347
348 >> Sounds ok then. --[[Joey]]
349
350 ----
351
352 [[merged|done]] --[[Joey]]