Standards-based cross-app podcast comments (2024) #623
Replies: 4 comments 13 replies
-
The No Agenda podcast has an approximate audience of 900k (as per op3.dev). We have been publishing a root post in our social intera t tag since inception of the tag. Thousands of our listeners also have mastodon server accounts. If devs want to experiment it is a good test bed. I am happy to promote any work that includes comments on the show. You can see comments on all episodes here: |
Beta Was this translation helpful? Give feedback.
-
Thanks for restarting this conversation!
I urge us to make the source of truth be what the podcaster owns/controls, not merely by where the feed links to, but where the data exists. So apps pull from the podcast's centralized activity stream, not from all federated responses. This centralized authority would also be far more performant that following a tree of reply URIs and all the HTTP requests that would require.
I think this, like all other features, should be opt-in. If a podcast doesn't declare the feature, then it doesn't get the feature. Some podcasts are under legal constraints to moderate the conversation that is displayed with their content. Some podcasters don't want comments on their episodes. I don't think we should be auto-enabling cross-app comments for podcasts that don't want them, just like we don't make Satoshi wallets for all podcasts. |
Beta Was this translation helpful? Give feedback.
-
My top five concerns for any solution here:
|
Beta Was this translation helpful? Give feedback.
-
A minor correction here, Pleroma, as far as I have tested, actually supports C2S for read and write. There might be some other implementations out there. If Mastodon supported it for write as well, this would be a big win. Lack of an auth standard is a big deal. Another issue with C2S for webapps that do not have their own server is CORS. That is an issue even for fetching the comments, I had that issue when implementing support for it on podcastindex.org. P.S.: I have some words to write about content forgery, but I will leave it for when I have more time. |
Beta Was this translation helpful? Give feedback.
-
Given the renewed interest in this topic, I thought it might be worthwhile to publish a quick public perspective on the current state of things, building on a few conversations I've had recently. This will not be new to folks that have been following this topic for a while (e.g. back when I made the podcastsocial.org site), but we now have a few more apps wanting to get started, and more fediverse folks in general.
Most of the hard work has already been done (by folks like Benjamin Bellamy/Yassine Doghri at Castopod, Alecks Gates, & Dave Jones), but some amount of the easy/fun work remains. There is no free lunch in an open system, particularly one that deals in user-generated content.
My bias is for pragmatism, so I'm going to focus on the opportunity as it exists today (and short-term) in the world as it is, there are enough gold nuggets just sitting on the ground waiting to be picked up by podcast apps/services that are willing to roll up their sleeves, without boiling the ocean or waiting for a far-off future system or an off-the-shelf solution.
Indeed, one of the reasons to be bullish about ActivityPub is that it is less about client→server conformance to a single platform, but more about independent, standalone systems with different goals & release schedules publishing a subset of their functionality for server→server interactions without losing a sense of what differentiates their own app/community in the first place.
The immediate goal
At a high level, the initial idea is that although existing podcast apps may have a robust commenting system within their own app, it would be better if:
While this overview talks about ActivityPub as the protocol, one can map the same concepts to other systems providing similar identity systems and similar extensible payloads. Also other public systems can be bridged.
The Note-iverse and ActivityPub
With the formalization of the
podcast:socialInteract
tag in the podcast namespace we now have a way for podcasters (or their proxies, the podcast hosting companies) to clearly express the venue for federated commenting around a single episode, an item-level tag in the RSS feed that specifies the protocol + uri.One might think we are done here, we can throw a Mastodon link in there, and that's it, right? The magic of ActivityPub!
I'm finding that although folks have some idea about what Mastodon is, terms like ActivityPub & ActivityStreams [1] [2] are thrown around loosely without knowing exactly where they fit in. Perhaps Evan's book later this year will bring a more detailed look at the system that for now you kind of need to piece together from various places and a bunch of trial and error.
Also, there are podcast apps that seem to want a free lunch, the ability to ride on top of an existing API to other servers, and delegate all social interactions to other systems.
There are two major issues with this approach, one is that although the Mastodon world is larger than it was the first time we looked into this, not all podcast commenters are existing Mastodon users, nor will this ever likely be the case. We are looking to build a podcasting-wide system here, not a Mastodon-constrained one.
The second issue is that when you delegate all interaction via someone's existing Mastodon account, you are not using ActivityPub at all for posting! You are just using the Mastodon API. The ActivityPub "client-to-server" (C2S) api is underspecified (e.g. it says nothing about auth) and no existing servers support it.
What this means is that you lose any ability to provide custom podcast-specific properties or podcast-specific object types, and you lose the ability to use any other system in the fediverse that does not also happen to mimic the subset of the Mastodon API that you call. You are trapped in the Note-iverse (the basic object type used for microblogging posts), and whatever basic fields the Mastodon posting API supports. You also lose out on server push of federated replies, since you are not a peer in the system, just a client of whatever server the user happens to use. If you want to support other non-Mastodon servers, you have to implement this code multiple times!
While not ideal, apps that want to do the minimum amount of work can go this route (prompt for the user's account, oauth via Mastodon, post via the Mastodon API, and enumerate the replies collection e.g. with threadcap) and participate in cross-app comments in a limited way. It's possible we could come up with a simple tunnelling standard for appending podcast-specific properties (like payment claims) to the bottom of the message text.
However, most podcast apps should seamlessly host their own users' identities (Actors) by default and become true peers in the system.
If you think about new podcast apps like Fountain or TrueFans, this is what they already do. They manage user identities, activity, and content to some extent, and are perfectly positioned to start federating basic comments to the podcaster-specified endpoint: the ActivityPub url specified in the
podcast:socialInteract
tag.In order to do this, podcast apps need to provide Actor endpoints with stable uris for each user, and stable uris for each comment. Since they own the implementation in this scenario, they'll have full control on attaching podcast-specific properties like payment claims. They'll also be responsible for taking down content if necessary since they are hosting it. They'll be notifying the url specified in the
podcast:socialInteract
tag on any interactions, and the destination is free to block/ignore it. They can also pull in comments from other systems by enumerating the replies collection.The other side of the implementation
Now the question: who or what hosts the
podcast:socialInteract
ActivityPub url for any given podcast episode?As long as the url supports ActivityPub requests, and supports the replies collection, it really depends on the podcaster or hosting company.
Worst case, the podcaster should have the ability to paste in an external link to an existing Mastodon or other fediverse account they control.
However, podcast hosting companies should provide these endpoint urls by default for each new episode.
Ideally, there should be no need for the podcaster to do anything when publishing a new episode, other than potentially modifying default moderation policy for that episode.
Under the hood, the hosting company could host a Mastodon server, but now there are lighter-weight alternatives that support the limited ActivityPub subset needed for the podcast comments scenarios. Basically you need a server that has the ability to manage the
replies
collection, since this is the canonical endpoint apps will use to pull in comments from other apps. It's likely the best approach will be to develop this themselves for seamless integration with their existing CMS and UI or partner with a hosted service.It's worth talking a bit about how replies to an object are expressed in the Activity Streams vocabulary, and how it would look for a podcast episode.
When an episode is published and the
podcast:socialInteract
url defined, any AP requests to that url should return a top-level object representing that episode. It should roughly follow the fields specified in theNote
object (so that it can be rendered in existing microblogging UIs) but it doesn't need to be of typeNote
. It could bePodcastEpisode
, for example (I believe Castopod already does this). It must have areplies
property, but the spec is flexible (and indeed existing servers are varied) about how these replies are implementated.Replies can be as simple as a JSON array of string uris, each uri pointing to an object on a remote server hosting that reply. Or they can be expressed as a collection or page of inline objects. This might seem like a trivial detail, but this is the lever for the podcaster to moderate replies in this cross-app comments system. Not every incoming notification needs to be copied over into this collection. And comments can effectively be disabled by returning an empty array.
The implementation can be as hands-on or hands-off regarding moderation as the podcaster needs, even providing a workflow for privately reviewing every incoming comment for review before returning it in the
replies
collection.Services
If a hosting company does not want to implement this system themselves, there exists an opportunity for them to partner with a generic service that provides these endpoints for any podcast episode or set of podcasts, given a podcast guid and item guid. e.g.
Perhaps Dave could even extend his current service to provide a default implementation? Would need to support the episode level, and ideally allow a podcaster login to moderate.
Crucially these services would need to serve AP objects for the episode, serve Actor AP for each podcast, and respond to ActivityPub Server-to-Server follow/reply actions and handle them accordingly.
The rest
Now to the question of what to do about podcasters that don't care or can't declare
podcast:socialInteract
tags for episodes in their feed. Otherwise known as 99% of podcasts today. Are we back to square one for these shows? i.e. comments relegated to within a single app onlyIdeally, every app could derive the same stable ActivityPub url to use in the meantime for any episode. Again, perhaps Dave's service could handle this? I'm also thinking about standing up something here. Perhaps we could add a new PI api call to get the socialInteract uri for a given episode that would return the one declared in the feed, if present, or the stable fallback. Very similar to the
podcast:guid
fallback allocation process.The longer-term goal
Once we have podcast apps as first-class ActivityPub publishers, and podcast hosting companies/services as first-class ActivityPub receivers, we can send other activities down this channel! The tag is called
socialInteract
after all, notcomments
.We could:
It's just a matter of coming up with a shared podcast vocabulary for our noun/verb types, starting with interactions we already know about. We have a truly open and federated model for podcast/episode-level activity while maintaining the RSS feed (ie the podcaster) as the locus of control.
TODO list
podcast
JSON-LD context - this is the way to include custom namespaced properties in ActivityPub payloads, basically the ActivityPub equivalent of thepodcast
xml namespace. The one that immediately comes to mind is a string property that contains a payment claim. I love the idea of using a JWT for this, maybe Alecks could walk through an example manually? I'm not sure how this would work with services like Alby, do they have APIs to sign arbitrary data using the user's private key?Beta Was this translation helpful? Give feedback.
All reactions