ActivityPub
Each PeerTube instance is able to fetch video from other compatible servers it follows, in a process known as “federation”. Federation is implemented using the ActivityPub protocol, in order to leverage existing tools and be compatible with other services such as Mastodon, Pleroma and many more.
Federation in PeerTube is twofold: videos metadata are shared as activities for inter-server communication in what amounts to sharing parts of one's database, and user interaction via comments which are compatible with the kind of activity textual platforms like Mastodon use.
Supported Activities
Supported Objects
- Video
- CacheFile
- Note
- Playlist
- PlaylistElement
- Actor
- Note (comment)
- WatchAction
Follow
Follow is an activity standardized in the ActivityPub specification (see Follow Activity). The Follow activity is used to subscribe to the activities of another actor (a server subscribing to another server's videos, a user subscribing to another user's videos).
Supported on
- Actor (
peertube
actor, account actor or channel actor)
Accept
Supported on
- Follow
Reject
Reject is an activity standardized in the ActivityPub specification (see Reject Activity).
Supported on
- Follow
Undo
Undo is an activity standardized in the ActivityPub specification (see Undo Activity). The Undo activity is used to undo a previous activity.
Supported on
Like
Like is an activity standardized in the ActivityPub specification (see Like Activity).
Supported on
Dislike
Dislike is an activity standardized in the ActivityStream specification (see Dislike Activity).
Supported on
Update
Update is an activity standardized in the ActivityPub specification (see Update Activity). The Update activity is used when updating an already existing object.
Supported on
Create
Create is an activity standardized in the ActivityPub specification (see Create Activity). The Create activity is used when posting a new object. This has the side effect that the object
embedded within the Activity (in the object property) is created.
Supported on
- Video
- Playlist
- CacheFile
- Note (a comment)
- WatchAction
Example
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{}
],
"to": ["https://peertube2.cpy.re/accounts/root/activity"],
"type": "Create",
"actor": "https://peertube2.cpy.re/accounts/root",
"object": {}
}
Delete
Delete is an activity standardized in the ActivityPub specification (see Delete Activity).
Supported on
Announce
Announce is an activity standardized in the ActivityPub specification (see Announce Activity).
Supported on
Example
{
"type": "Announce",
"id": "https://peertube2.cpy.re/videos/watch/997111d4-e8d8-4f45-99d3-857905785d05/announces/1",
"actor": "https://peertube2.cpy.re/accounts/root",
"object": "https://peertube2.cpy.re/videos/watch/997111d4-e8d8-4f45-99d3-857905785d05",
"to": [
"https://www.w3.org/ns/activitystreams#Public",
"https://peertube2.cpy.re/accounts/root/followers",
"https://peertube2.cpy.re/video-channels/root_channel/followers"
],
"cc": []
}
Flag
Flag is an activity standardized in the ActivityStream specification (see Flag Activity).
Supported on
View
View is an activity standardized in the ActivityStream specification (see View Activity).
A PeerTube instance sends a View
activity every time a user watched a video so the origin server can increment video views counter.
If the View
activity includes an expires
attribute, it means a user is currently watching a video. This kind of event is sent periodically until the user stops watching the video. The same View
action can be sent multiple times using a different expires
attribute, meaning the user is still watching the video.
Supported on
Supported Objects
Video
INFO
This object extends the ActivityPub specification, and therefore some properties are not part of it.
Structure
The model structure definition lies in packages/models/src/activitypub/objects/video-object.ts.
import { LiveVideoLatencyModeType, VideoStateType } from '../../videos/index.js'
import {
ActivityIconObject,
ActivityIdentifierObject,
ActivityPubAttributedTo,
ActivityTagObject,
ActivityUrlObject
} from './common-objects.js'
export interface VideoObject {
type: 'Video'
id: string
name: string
duration: string
uuid: string
tag: ActivityTagObject[]
category: ActivityIdentifierObject
licence: ActivityIdentifierObject
language: ActivityIdentifierObject
subtitleLanguage: ActivityIdentifierObject[]
views: number
sensitive: boolean
isLiveBroadcast: boolean
liveSaveReplay: boolean
permanentLive: boolean
latencyMode: LiveVideoLatencyModeType
commentsEnabled: boolean
downloadEnabled: boolean
waitTranscoding: boolean
state: VideoStateType
published: string
originallyPublishedAt: string
updated: string
uploadDate: string
mediaType: 'text/markdown'
content: string
support: string
icon: ActivityIconObject[]
url: ActivityUrlObject[]
likes: string
dislikes: string
shares: string
comments: string
hasParts: string
attributedTo: ActivityPubAttributedTo[]
preview?: ActivityPubStoryboard[]
to?: string[]
cc?: string[]
}
export interface ActivityPubStoryboard {
type: 'Image'
rel: [ 'storyboard' ]
url: {
href: string
mediaType: string
width: number
height: number
tileWidth: number
tileHeight: number
tileDuration: string
}[]
}
Example
A Video
object could be complex depending on transcoding settings. Here is an example with some comments:
{
"type": "Video",
"id": "https://peertube2.cpy.re/videos/watch/...",
"name": "HLS test 1",
"duration": "PT730S",
"uuid": "969bf103-7818-43b5-94a0-...",
"tag": [
{
"type": "Hashtag",
"name": "tagexample"
}
],
"views": 35,
"sensitive": false,
"waitTranscoding": true,
"isLiveBroadcast": false,
// If this is a live, tell if the user will save a replay or not
"liveSaveReplay": null,
// If this is a live, tell if this is a permanent live or not
"permanentLive": null,
// See the REST API documentation: https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo
"state": 1,
"commentsEnabled": true,
"downloadEnabled": true,
"published": "2019-04-17T08:55:11.871Z",
"originallyPublishedAt": null,
"updated": "2020-12-15T11:01:02.477Z",
"mediaType": "text/markdown",
"content": "The story of programming prodigy and information activist Aaron Swartz, who took his own life at the age of 26.",
// How to support the uploaded/content creator
"support": "Pay me a coffee when you see me",
"subtitleLanguage": [
{
"identifier": "ca",
"name": "Catalan",
"url": "https://peertube2.cpy.re/lazy-static/video-captions/...-ca.vtt"
}
],
"category": {
"identifier": "2", // Internal PeerTube ID
"name": "Films"
},
"licence": {
"identifier": "5", // Internal PeerTube ID
"name": "Attribution - Non Commercial - Share Alike"
},
// Optional
"language": {
"identifier": "en",
"name": "English"
},
"icon": [
{
"type": "Image",
"url": "https://peertube2.cpy.re/static/thumbnails/....jpg",
"mediaType": "image/jpeg",
"width": 200,
"height": 110
},
{
"type": "Image",
"url": "https://peertube2.cpy.re/lazy-static/previews/....jpg",
"mediaType": "image/jpeg",
"width": 560,
"height": 315
}
],
"url": [
// Webpage
{
"type": "Link",
"mediaType": "text/html",
"href": "https://peertube2.cpy.re/videos/watch/969bf103-7818-43b5-94a0-de159e13de50"
},
// Raw URL to web video compatible mp4 file (only if Web Video transcoding is enabled)
{
"type": "Link",
"mediaType": "video/mp4",
"href": "https://peertube2.cpy.re/static/webseed/969bf103-7818-43b5-94a0-de159e13de50-536.mp4",
"height": 536,
"size": 135239407,
"fps": 24
},
// URL to fetch video file metadata (only if Web Video transcoding is enabled)
{
"type": "Link",
"rel": [
"metadata",
"video/mp4"
],
"mediaType": "application/json",
"href": "https://peertube2.cpy.re/api/v1/videos/969bf103-7818-43b5-94a0-de159e13de50/metadata/1642209",
"height": 536,
"fps": 24
},
// Torrent file URL (only if Web Video transcoding is enabled)
{
"type": "Link",
"mediaType": "application/x-bittorrent",
"href": "https://peertube2.cpy.re/static/torrents/969bf103-7818-43b5-94a0-de159e13de50-536.torrent",
"height": 536
},
// Magnet URI (only if Web Video transcoding is enabled)
{
"type": "Link",
"mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
"href": "magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Ftorrents%2F969bf103-7818-43b5-94a0-de159e13de50-536.torrent&xt=urn:btih:673aaa764ad4ba61aa5b50306a5fd77fdbd4e78e&dn=HLS+test+1&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fwebseed%2F969bf103-7818-43b5-94a0-de159e13de50-536.mp4",
"height": 536
},
// HLS playlist URL (only if HLS transcoding is enabled)
{
"type": "Link",
"mediaType": "application/x-mpegURL",
"href": "https://peertube2.cpy.re/static/streaming-playlists/hls/969bf103-7818-43b5-94a0-de159e13de50/master.m3u8",
"tag": [
// Infohashes for p2p-media-loader of every resolution
{
"type": "Infohash",
"name": "d7844378e5a6b9af2d45267c0e413688e7839918"
},
// URL to a JSON that contains the playlist's segments sha sum
{
"type": "Link",
"name": "sha256",
"mediaType": "application/json",
"href": "https://peertube2.cpy.re/static/streaming-playlists/hls/969bf103-7818-43b5-94a0-de159e13de50/segments-sha256.json"
},
// Raw URL to the fragmented mp4 file used by the HLS playlist
{
"type": "Link",
"mediaType": "video/mp4",
"href": "https://peertube2.cpy.re/static/streaming-playlists/hls/969bf103-7818-43b5-94a0-de159e13de50/969bf103-7818-43b5-94a0-de159e13de50-536-fragmented.mp4",
"height": 536,
"size": 135108145,
"fps": 24
},
// URL to fetch video file metadata
{
"type": "Link",
"rel": [
"metadata",
"video/mp4"
],
"mediaType": "application/json",
"href": "https://peertube2.cpy.re/api/v1/videos/969bf103-7818-43b5-94a0-de159e13de50/metadata/3649370",
"height": 536,
"fps": 24
},
// Fragmented mp4 file torrent URL
{
"type": "Link",
"mediaType": "application/x-bittorrent",
"href": "https://peertube2.cpy.re/static/torrents/969bf103-7818-43b5-94a0-de159e13de50-536-hls.torrent",
"height": 536
},
// Fragmented mp4 file magnet URI
{
"type": "Link",
"mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
"href": "magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Ftorrents%2F969bf103-7818-43b5-94a0-de159e13de50-536-hls.torrent&xt=urn:btih:e629524f99aa27bc2b42d05b22ac318cc22cfcf7&dn=HLS+test+1&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fstreaming-playlists%2Fhls%2F969bf103-7818-43b5-94a0-de159e13de50%2F969bf103-7818-43b5-94a0-de159e13de50-536-fragmented.mp4",
"height": 536
}
]
}
],
"likes": "https://peertube2.cpy.re/videos/watch/969bf103-7818-43b5-94a0-de159e13de50/likes",
"dislikes": "https://peertube2.cpy.re/videos/watch/969bf103-7818-43b5-94a0-de159e13de50/dislikes",
"shares": "https://peertube2.cpy.re/videos/watch/969bf103-7818-43b5-94a0-de159e13de50/announces",
"comments": "https://peertube2.cpy.re/videos/watch/969bf103-7818-43b5-94a0-de159e13de50/comments",
"attributedTo": [
// The account
{
"type": "Person",
"id": "https://peertube2.cpy.re/accounts/root"
},
// The channel
{
"type": "Group",
"id": "https://peertube2.cpy.re/video-channels/a75cbdf4-acf2-45c0-a491-e9b28939f8db"
}
],
"to": [],
"cc": [],
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
...
]
Playlist
INFO
This object is not standard to the ActivityPub specification.
The model structure definition lies in packages/models/src/activitypub/objects/playlist-object.ts.
import { ActivityIconObject, ActivityPubAttributedTo } from './common-objects.js'
export interface PlaylistObject {
id: string
type: 'Playlist'
name: string
content: string
mediaType: 'text/markdown'
uuid: string
totalItems: number
attributedTo: ActivityPubAttributedTo[]
icon?: ActivityIconObject
published: string
updated: string
orderedItems?: string[]
partOf?: string
next?: string
first?: string
to?: string[]
}
CacheFile
INFO
This object is not standard to the ActivityPub specification.
The object is used to represent a cached file. It is usually sent by third-party servers to the origin server hosting a video file (a resolution from a Video
), to notify it that they have put up a copy of that file. The origin server should then add the server emitting the CacheFile
to the list of WebSeeds for that file.
Structure
The model structure definition lies in packages/models/src/activitypub/objects/cache-file-object.ts.
import { ActivityVideoUrlObject, ActivityPlaylistUrlObject } from './common-objects.js'
export interface CacheFileObject {
id: string
type: 'CacheFile'
object: string
expires: string
url: ActivityVideoUrlObject | ActivityPlaylistUrlObject
}
Note
A Note
is usually a comment made to a video. Since most ActivityPub textual platforms use the Note
object for their messages, most of them can interact in the same way with PeerTube videos, making them able to comment PeerTube videos directly! A Note
is emitted along the Video publication object: the former is used to notify textual platforms of the Fediverse, the latter to notify the Vidiverse.
Structure
The model structure definition lies in packages/models/src/activitypub/objects/video-comment-object.ts.
import { ActivityPubAttributedTo, ActivityTagObject } from './common-objects.js'
export interface VideoCommentObject {
type: 'Note'
id: string
content: string
mediaType: 'text/markdown'
inReplyTo: string
published: string
updated: string
url: string
attributedTo: ActivityPubAttributedTo
tag: ActivityTagObject[]
}
Playlist
INFO
This object is not standard to the ActivityPub specification.
The object is used to represent a video playlist. It extends OrderedCollectionPage and items are PlaylistElement.
Structure
The model structure definition lies in packages/models/src/activitypub/objects/playlist-object.ts.
import { ActivityIconObject, ActivityPubAttributedTo } from './common-objects.js'
export interface PlaylistObject {
id: string
type: 'Playlist'
name: string
content: string
mediaType: 'text/markdown'
uuid: string
totalItems: number
attributedTo: ActivityPubAttributedTo[]
icon?: ActivityIconObject
published: string
updated: string
orderedItems?: string[]
partOf?: string
next?: string
first?: string
to?: string[]
}
Playlist Element
INFO
This object is not standard to the ActivityPub specification.
The object is used to represent a video playlist element inside the Playlist
object.
Structure
The model structure definition lies in packages/models/src/activitypub/objects/playlist-element-object.ts.
export interface PlaylistElementObject {
id: string
type: 'PlaylistElement'
url: string
position: number
startTimestamp?: number
stopTimestamp?: number
}
Watch Action PeerTube >= 4.2
INFO
This object is not standard to the ActivityPub specification. It comes from Schema.org
The object is used to represent a viewer that watched a video. Allows origin server to aggregate viewer statistics.
Structure
The model structure definition lies in packages/models/src/activitypub/objects/watch-action-object.ts.
export interface WatchActionObject {
id: string
type: 'WatchAction'
startTime: string
endTime: string
location?: {
addressCountry: string
}
uuid: string
object: string
actionStatus: 'CompletedActionStatus'
duration: string
watchSections: {
startTimestamp: number
endTimestamp: number
}[]
}