Skip to content

ActivityPub

Each PeerTube instance is able to fetch videos 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.

Federate with PeerTube

TIP

If you have any problem or question about PeerTube federation, don't hesitate to discuss about them on our forum

PeerTube has the concept of video channels (Group actor) that are owned by accounts (Person actor). In ActivityPub, a PeerTube video is created by the account and Announced by the video channel.

To federate videos, PeerTube requires the video to have an attributedTo field that contains a Group actor. The Group actor also contains an attributedTo field pointing to the owner Person actor (see the documentation for more information and examples).

If your video platform doesn't have the concept of channels, we recommend you either:

  • simulate a Group actor representing your account (automatically adding _channel to your account username example)
  • put your Person actor as a Group actor in attributedTo that is owned by a global Person actor that would own all your fake channels

Supported Activities

Supported Objects

Activities

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

Example

json
{
  "@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

json
{
  "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

ApproveReply PeerTube >= 6.2

PeerTube implements FEP-5624 draft so users can moderate comments of their videos.

If the video requires comments approval, the Video object includes

json
"canReply": "https://www.w3.org/ns/activitystreams#Public"

PeerTube sends back an ApproveReply activity to the Note origin server when the comment is approved. The Video origin server also forwards the Note to actors involved in the video.

Supported on

Objects

Video

INFO

This object extends the ActivityPub specification, and therefore some properties are not part of it.

TypeScript model: packages/models/src/activitypub/objects/video-object.ts.

ts
import { LiveVideoLatencyModeType, VideoCommentPolicyType, VideoStateType } from '../../videos/index.js'
import {
  ActivityIconObject,
  ActivityIdentifierObject,
  ActivityPubAttributedTo,
  ActivityTagObject,
  ActivityUrlObject
} from './common-objects.js'
import { VideoCaptionObject } from './video-caption-object.js'
import { VideoChapterObject } from './video-chapters-object.js'

export interface VideoObject {
  type: 'Video'
  id: string
  name: string
  duration: string
  uuid: string
  tag: ActivityTagObject[]
  category: ActivityIdentifierObject
  licence: ActivityIdentifierObject
  language: ActivityIdentifierObject
  subtitleLanguage: VideoCaptionObject[]

  views: number

  sensitive: boolean

  isLiveBroadcast: boolean
  liveSaveReplay: boolean
  permanentLive: boolean
  latencyMode: LiveVideoLatencyModeType

  commentsEnabled?: boolean
  commentsPolicy: VideoCommentPolicyType
  canReply: 'as:Public' | 'https://www.w3.org/ns/activitystreams#Public'

  downloadEnabled: boolean
  waitTranscoding: boolean
  state: VideoStateType

  published: string
  originallyPublishedAt: string
  updated: string
  uploadDate: string

  mediaType: 'text/markdown'
  content: string

  support: string

  aspectRatio: number

  icon: ActivityIconObject[]

  url: ActivityUrlObject[]

  likes: string
  dislikes: string
  shares: string
  comments: string
  hasParts: string | VideoChapterObject[]

  attributedTo: ActivityPubAttributedTo[]

  preview?: ActivityPubStoryboard[]

  to?: string[]
  cc?: string[]

  // For export
  attachment?: {
    type: 'Video'
    url: string
    mediaType: string
    height: number
    size: number
    fps: number
  }[]
}

export interface ActivityPubStoryboard {
  type: 'Image'
  rel: [ 'storyboard' ]
  url: {
    href: string
    mediaType: string
    width: number
    height: number
    tileWidth: number
    tileHeight: number
    tileDuration: string
  }[]
}
JSON
{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/v1",
    {
      "RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
    },
    {
      "pt": "https://joinpeertube.org/ns#",
      "sc": "http://schema.org/",
      "Hashtag": "as:Hashtag",
      "category": "sc:category",
      "licence": "sc:license",
      "subtitleLanguage": "sc:subtitleLanguage",
      "sensitive": "as:sensitive",
      "language": "sc:inLanguage",
      "identifier": "sc:identifier",
      "isLiveBroadcast": "sc:isLiveBroadcast",
      "liveSaveReplay": {
        "@type": "sc:Boolean",
        "@id": "pt:liveSaveReplay"
      },
      "permanentLive": {
        "@type": "sc:Boolean",
        "@id": "pt:permanentLive"
      },
      "latencyMode": {
        "@type": "sc:Number",
        "@id": "pt:latencyMode"
      },
      "Infohash": "pt:Infohash",
      "tileWidth": {
        "@type": "sc:Number",
        "@id": "pt:tileWidth"
      },
      "tileHeight": {
        "@type": "sc:Number",
        "@id": "pt:tileHeight"
      },
      "tileDuration": {
        "@type": "sc:Number",
        "@id": "pt:tileDuration"
      },
      "aspectRatio": {
        "@type": "sc:Float",
        "@id": "pt:aspectRatio"
      },
      "uuid": {
        "@type": "sc:identifier",
        "@id": "pt:uuid"
      },
      "originallyPublishedAt": "sc:datePublished",
      "uploadDate": "sc:uploadDate",
      "hasParts": "sc:hasParts",
      "views": {
        "@type": "sc:Number",
        "@id": "pt:views"
      },
      "state": {
        "@type": "sc:Number",
        "@id": "pt:state"
      },
      "size": {
        "@type": "sc:Number",
        "@id": "pt:size"
      },
      "fps": {
        "@type": "sc:Number",
        "@id": "pt:fps"
      },
      "commentsEnabled": {
        "@type": "sc:Boolean",
        "@id": "pt:commentsEnabled"
      },
      "canReply": "pt:canReply",
      "commentsPolicy": {
        "@type": "sc:Number",
        "@id": "pt:commentsPolicy"
      },
      "downloadEnabled": {
        "@type": "sc:Boolean",
        "@id": "pt:downloadEnabled"
      },
      "waitTranscoding": {
        "@type": "sc:Boolean",
        "@id": "pt:waitTranscoding"
      },
      "support": {
        "@type": "sc:Text",
        "@id": "pt:support"
      },
      "likes": {
        "@id": "as:likes",
        "@type": "@id"
      },
      "dislikes": {
        "@id": "as:dislikes",
        "@type": "@id"
      },
      "shares": {
        "@id": "as:shares",
        "@type": "@id"
      },
      "comments": {
        "@id": "as:comments",
        "@type": "@id"
      }
    }
  ],
  "to": [
    "https://www.w3.org/ns/activitystreams#Public"
  ],
  "cc": [
    "https://peertube2.cpy.re/accounts/root/followers"
  ],
  "type": "Video",
  "id": "https://peertube2.cpy.re/videos/watch/04af977f-4201-4697-be67-a8d8cae6fa7a",
  "name": "The Internet's Own Boy",
  "duration": "PT6299S",
  "uuid": "04af977f-4201-4697-be67-a8d8cae6fa7a",
  "category": {
    "identifier": "2",
    "name": "Films"
  },
  "licence": {
    "identifier": "5",
    "name": "Attribution - Non Commercial - Share Alike"
  },
  "language": {
    "identifier": "en",
    "name": "English"
  },
  "views": 11025,
  "sensitive": false,
  "waitTranscoding": false,
  "state": 1,
  "commentsEnabled": true,
  "canReply": null,
  "commentsPolicy": 1,
  "downloadEnabled": true,
  "published": "2017-10-17T14:04:23.288Z",
  "originallyPublishedAt": null,
  "updated": "2024-05-31T08:02:44.917Z",
  "tag": [
    {
      "type": "Hashtag",
      "name": "eertherth"
    }
  ],
  "mediaType": "text/markdown",
  "content": "The story of programming prodigy and information activist Aaron Swartz, who took his own life at the age of 26.",
  "support": null,
  "subtitleLanguage": [],
  "icon": [
    {
      "type": "Image",
      "url": "https://peertube2.cpy.re/lazy-static/thumbnails/22efe749-bd30-4b4e-83f3-3c9912d69b67.jpg",
      "mediaType": "image/jpeg",
      "width": 280,
      "height": 157
    },
    {
      "type": "Image",
      "url": "https://peertube2.cpy.re/lazy-static/previews/04af977f-4201-4697-be67-a8d8cae6fa7a.jpg",
      "mediaType": "image/jpeg",
      "width": 560,
      "height": 315
    }
  ],
  "preview": [
    {
      "type": "Image",
      "rel": [
        "storyboard"
      ],
      "url": [
        {
          "mediaType": "image/jpeg",
          "href": "https://peertube2.cpy.re/lazy-static/storyboards/3598a6b5-d9a6-4ef1-b3ae-ab3f79a8c5ac.jpg",
          "width": 1920,
          "height": 1080,
          "tileWidth": 192,
          "tileHeight": 108,
          "tileDuration": "PT63S"
        }
      ]
    }
  ],
  "aspectRatio": null,
  "url": [
    {
      "type": "Link",
      "mediaType": "text/html",
      "href": "https://peertube2.cpy.re/videos/watch/04af977f-4201-4697-be67-a8d8cae6fa7a"
    },
    {
      "type": "Link",
      "mediaType": "video/mp4",
      "href": "https://peertube2.cpy.re/static/web-videos/04af977f-4201-4697-be67-a8d8cae6fa7a-720.mp4",
      "height": 720,
      "width": null,
      "size": 942586378,
      "fps": -1
    },
    {
      "type": "Link",
      "rel": [
        "metadata",
        "video/mp4"
      ],
      "mediaType": "application/json",
      "href": "https://peertube2.cpy.re/api/v1/videos/04af977f-4201-4697-be67-a8d8cae6fa7a/metadata/14",
      "height": 720,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "application/x-bittorrent",
      "href": "https://peertube2.cpy.re/lazy-static/torrents/04af977f-4201-4697-be67-a8d8cae6fa7a-720.torrent",
      "height": 720,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
      "href": "magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Flazy-static%2Ftorrents%2F04af977f-4201-4697-be67-a8d8cae6fa7a-720.torrent&xt=urn:btih:96bc64e8731aa86269c1f9266177bc9f92581437&dn=The+Internet's+Own+Boy&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fweb-videos%2F04af977f-4201-4697-be67-a8d8cae6fa7a-720.mp4",
      "height": 720,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "video/mp4",
      "href": "https://peertube2.cpy.re/static/web-videos/04af977f-4201-4697-be67-a8d8cae6fa7a-480.mp4",
      "height": 480,
      "width": null,
      "size": 535692756,
      "fps": -1
    },
    {
      "type": "Link",
      "rel": [
        "metadata",
        "video/mp4"
      ],
      "mediaType": "application/json",
      "href": "https://peertube2.cpy.re/api/v1/videos/04af977f-4201-4697-be67-a8d8cae6fa7a/metadata/17",
      "height": 480,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "application/x-bittorrent",
      "href": "https://peertube2.cpy.re/lazy-static/torrents/04af977f-4201-4697-be67-a8d8cae6fa7a-480.torrent",
      "height": 480,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
      "href": "magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Flazy-static%2Ftorrents%2F04af977f-4201-4697-be67-a8d8cae6fa7a-480.torrent&xt=urn:btih:c962cbdcff46ded985b5dd2a56672040f46200bb&dn=The+Internet's+Own+Boy&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fweb-videos%2F04af977f-4201-4697-be67-a8d8cae6fa7a-480.mp4",
      "height": 480,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "video/mp4",
      "href": "https://peertube2.cpy.re/static/web-videos/04af977f-4201-4697-be67-a8d8cae6fa7a-360.mp4",
      "height": 360,
      "width": null,
      "size": 394767560,
      "fps": -1
    },
    {
      "type": "Link",
      "rel": [
        "metadata",
        "video/mp4"
      ],
      "mediaType": "application/json",
      "href": "https://peertube2.cpy.re/api/v1/videos/04af977f-4201-4697-be67-a8d8cae6fa7a/metadata/16",
      "height": 360,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "application/x-bittorrent",
      "href": "https://peertube2.cpy.re/lazy-static/torrents/04af977f-4201-4697-be67-a8d8cae6fa7a-360.torrent",
      "height": 360,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
      "href": "magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Flazy-static%2Ftorrents%2F04af977f-4201-4697-be67-a8d8cae6fa7a-360.torrent&xt=urn:btih:0db617d3091abf1b3a84e238028ccc008c1cbf3d&dn=The+Internet's+Own+Boy&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fweb-videos%2F04af977f-4201-4697-be67-a8d8cae6fa7a-360.mp4",
      "height": 360,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "video/mp4",
      "href": "https://peertube2.cpy.re/static/web-videos/04af977f-4201-4697-be67-a8d8cae6fa7a-240.mp4",
      "height": 240,
      "width": null,
      "size": 261723796,
      "fps": -1
    },
    {
      "type": "Link",
      "rel": [
        "metadata",
        "video/mp4"
      ],
      "mediaType": "application/json",
      "href": "https://peertube2.cpy.re/api/v1/videos/04af977f-4201-4697-be67-a8d8cae6fa7a/metadata/15",
      "height": 240,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "application/x-bittorrent",
      "href": "https://peertube2.cpy.re/lazy-static/torrents/04af977f-4201-4697-be67-a8d8cae6fa7a-240.torrent",
      "height": 240,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
      "href": "magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Flazy-static%2Ftorrents%2F04af977f-4201-4697-be67-a8d8cae6fa7a-240.torrent&xt=urn:btih:90cf3a384cc09737780f715eb77a2fe5a02ead15&dn=The+Internet's+Own+Boy&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fweb-videos%2F04af977f-4201-4697-be67-a8d8cae6fa7a-240.mp4",
      "height": 240,
      "width": null,
      "fps": -1
    },
    {
      "type": "Link",
      "mediaType": "application/x-mpegURL",
      "href": "https://peertube2.cpy.re/static/streaming-playlists/hls/04af977f-4201-4697-be67-a8d8cae6fa7a/754c65d0-ee08-4779-9133-229a0bda2ee2-master.m3u8",
      "tag": [
        {
          "type": "Infohash",
          "name": "a527fb0ec592862ec593d06f9bb70eab8c4092c6"
        },
        {
          "type": "Infohash",
          "name": "1d593a9ff05246a46a5f67bd32acaf97d4ff0e35"
        },
        {
          "type": "Infohash",
          "name": "5ae66b6da67306b2e60341217230775d9064d3a9"
        },
        {
          "type": "Infohash",
          "name": "abd4318e5a0904ab4bf6d7521a2214ab4b2d0b47"
        },
        {
          "type": "Link",
          "name": "sha256",
          "mediaType": "application/json",
          "href": "https://peertube2.cpy.re/static/streaming-playlists/hls/04af977f-4201-4697-be67-a8d8cae6fa7a/2cae232e-6eb2-4268-863f-5036deef8e97-segments-sha256.json"
        },
        {
          "type": "Link",
          "mediaType": "video/mp4",
          "href": "https://peertube2.cpy.re/static/streaming-playlists/hls/04af977f-4201-4697-be67-a8d8cae6fa7a/c7cc2798-5f06-418d-bf70-e03976f99e3f-720-fragmented.mp4",
          "height": 720,
          "width": null,
          "size": 818499517,
          "fps": 24
        },
        {
          "type": "Link",
          "rel": [
            "metadata",
            "video/mp4"
          ],
          "mediaType": "application/json",
          "href": "https://peertube2.cpy.re/api/v1/videos/04af977f-4201-4697-be67-a8d8cae6fa7a/metadata/5314509",
          "height": 720,
          "width": null,
          "fps": 24
        },
        {
          "type": "Link",
          "mediaType": "application/x-bittorrent",
          "href": "https://peertube2.cpy.re/lazy-static/torrents/e18ea17a-6cd9-43ce-97f3-a680f4d45b3b-720-hls.torrent",
          "height": 720,
          "width": null,
          "fps": 24
        },
        {
          "type": "Link",
          "mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
          "href": "magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Flazy-static%2Ftorrents%2Fe18ea17a-6cd9-43ce-97f3-a680f4d45b3b-720-hls.torrent&xt=urn:btih:c14330f9b7fb491cca0e72dbc511bdfd31a8da83&dn=The+Internet's+Own+Boy&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fstreaming-playlists%2Fhls%2F04af977f-4201-4697-be67-a8d8cae6fa7a%2Fc7cc2798-5f06-418d-bf70-e03976f99e3f-720-fragmented.mp4",
          "height": 720,
          "width": null,
          "fps": 24
        },
        {
          "type": "Link",
          "mediaType": "video/mp4",
          "href": "https://peertube2.cpy.re/static/streaming-playlists/hls/04af977f-4201-4697-be67-a8d8cae6fa7a/861a614e-42cb-4fdf-adf3-ae0655401884-480-fragmented.mp4",
          "height": 480,
          "width": null,
          "size": 485243564,
          "fps": 24
        },
        {
          "type": "Link",
          "rel": [
            "metadata",
            "video/mp4"
          ],
          "mediaType": "application/json",
          "href": "https://peertube2.cpy.re/api/v1/videos/04af977f-4201-4697-be67-a8d8cae6fa7a/metadata/5314512",
          "height": 480,
          "width": null,
          "fps": 24
        },
        {
          "type": "Link",
          "mediaType": "application/x-bittorrent",
          "href": "https://peertube2.cpy.re/lazy-static/torrents/5f249584-ab89-4e95-863b-71ec060cceb3-480-hls.torrent",
          "height": 480,
          "width": null,
          "fps": 24
        },
        {
          "type": "Link",
          "mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
          "href": "magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Flazy-static%2Ftorrents%2F5f249584-ab89-4e95-863b-71ec060cceb3-480-hls.torrent&xt=urn:btih:1cd5a3ebd0b494f0e6ad7f12e84482db36b862c4&dn=The+Internet's+Own+Boy&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fstreaming-playlists%2Fhls%2F04af977f-4201-4697-be67-a8d8cae6fa7a%2F861a614e-42cb-4fdf-adf3-ae0655401884-480-fragmented.mp4",
          "height": 480,
          "width": null,
          "fps": 24
        },
        {
          "type": "Link",
          "mediaType": "video/mp4",
          "href": "https://peertube2.cpy.re/static/streaming-playlists/hls/04af977f-4201-4697-be67-a8d8cae6fa7a/fc0116a8-6406-423a-bb8b-14f12325c501-240-fragmented.mp4",
          "height": 240,
          "width": null,
          "size": 247981291,
          "fps": 24
        },
        {
          "type": "Link",
          "rel": [
            "metadata",
            "video/mp4"
          ],
          "mediaType": "application/json",
          "href": "https://peertube2.cpy.re/api/v1/videos/04af977f-4201-4697-be67-a8d8cae6fa7a/metadata/5314511",
          "height": 240,
          "width": null,
          "fps": 24
        },
        {
          "type": "Link",
          "mediaType": "application/x-bittorrent",
          "href": "https://peertube2.cpy.re/lazy-static/torrents/c0315cb6-75bc-49f7-bed1-b0f62faaa9fa-240-hls.torrent",
          "height": 240,
          "width": null,
          "fps": 24
        },
        {
          "type": "Link",
          "mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
          "href": "magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Flazy-static%2Ftorrents%2Fc0315cb6-75bc-49f7-bed1-b0f62faaa9fa-240-hls.torrent&xt=urn:btih:0c49d76ac9027b5a8497f7cab2931d9c140e5a79&dn=The+Internet's+Own+Boy&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fstreaming-playlists%2Fhls%2F04af977f-4201-4697-be67-a8d8cae6fa7a%2Ffc0116a8-6406-423a-bb8b-14f12325c501-240-fragmented.mp4",
          "height": 240,
          "width": null,
          "fps": 24
        },
        {
          "type": "Link",
          "mediaType": "video/mp4",
          "href": "https://peertube2.cpy.re/static/streaming-playlists/hls/04af977f-4201-4697-be67-a8d8cae6fa7a/cc3c82be-16bf-47b9-b6af-28dca8bb8ff2-0-fragmented.mp4",
          "height": 0,
          "width": null,
          "size": 104103486,
          "fps": 0
        },
        {
          "type": "Link",
          "rel": [
            "metadata",
            "video/mp4"
          ],
          "mediaType": "application/json",
          "href": "https://peertube2.cpy.re/api/v1/videos/04af977f-4201-4697-be67-a8d8cae6fa7a/metadata/5314510",
          "height": 0,
          "width": null,
          "fps": 0
        },
        {
          "type": "Link",
          "mediaType": "application/x-bittorrent",
          "href": "https://peertube2.cpy.re/lazy-static/torrents/f79313be-0d3f-4538-ab19-b5ca67e34967-0-hls.torrent",
          "height": 0,
          "width": null,
          "fps": 0
        },
        {
          "type": "Link",
          "mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
          "href": "magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Flazy-static%2Ftorrents%2Ff79313be-0d3f-4538-ab19-b5ca67e34967-0-hls.torrent&xt=urn:btih:4310a4e63a3a57bbc823a756a542f18a97131e50&dn=The+Internet's+Own+Boy&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fstreaming-playlists%2Fhls%2F04af977f-4201-4697-be67-a8d8cae6fa7a%2Fcc3c82be-16bf-47b9-b6af-28dca8bb8ff2-0-fragmented.mp4",
          "height": 0,
          "width": null,
          "fps": 0
        }
      ]
    },
    {
      "type": "Link",
      "name": "tracker-http",
      "rel": [
        "tracker",
        "http"
      ],
      "href": "https://peertube2.cpy.re/tracker/announce"
    },
    {
      "type": "Link",
      "name": "tracker-websocket",
      "rel": [
        "tracker",
        "websocket"
      ],
      "href": "wss://peertube2.cpy.re:443/tracker/socket"
    }
  ],
  "likes": "https://peertube2.cpy.re/videos/watch/04af977f-4201-4697-be67-a8d8cae6fa7a/likes",
  "dislikes": "https://peertube2.cpy.re/videos/watch/04af977f-4201-4697-be67-a8d8cae6fa7a/dislikes",
  "shares": "https://peertube2.cpy.re/videos/watch/04af977f-4201-4697-be67-a8d8cae6fa7a/announces",
  "comments": "https://peertube2.cpy.re/videos/watch/04af977f-4201-4697-be67-a8d8cae6fa7a/comments",
  "hasParts": "https://peertube2.cpy.re/videos/watch/04af977f-4201-4697-be67-a8d8cae6fa7a/chapters",
  "attributedTo": [
    {
      "type": "Person",
      "id": "https://peertube2.cpy.re/accounts/root"
    },
    {
      "type": "Group",
      "id": "https://peertube2.cpy.re/video-channels/a75cbdf4-acf2-45c0-a491-e9b28939f8db"
    }
  ],
  "isLiveBroadcast": false,
  "liveSaveReplay": null,
  "permanentLive": null,
  "latencyMode": null
}

Playlist

INFO

This object is not standard to the ActivityPub specification.

TypeScript model: packages/models/src/activitypub/objects/playlist-object.ts.

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[]
}
JSON
{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/v1",
    {
      "RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
    },
    {
      "pt": "https://joinpeertube.org/ns#",
      "sc": "http://schema.org/",
      "Playlist": "pt:Playlist",
      "PlaylistElement": "pt:PlaylistElement",
      "position": {
        "@type": "sc:Number",
        "@id": "pt:position"
      },
      "startTimestamp": {
        "@type": "sc:Number",
        "@id": "pt:startTimestamp"
      },
      "stopTimestamp": {
        "@type": "sc:Number",
        "@id": "pt:stopTimestamp"
      },
      "uuid": {
        "@type": "sc:identifier",
        "@id": "pt:uuid"
      }
    }
  ],
  "to": [
    "https://www.w3.org/ns/activitystreams#Public"
  ],
  "cc": [
    "https://peertube2.cpy.re/accounts/chocobozzz/followers"
  ],
  "id": "https://peertube2.cpy.re/video-playlists/979ac324-4f2a-4554-a260-e0364e62d00f",
  "type": "Playlist",
  "totalItems": 3,
  "first": "https://peertube2.cpy.re/video-playlists/979ac324-4f2a-4554-a260-e0364e62d00f?page=1",
  "name": "Test",
  "content": "Test playlist",
  "mediaType": "text/markdown",
  "uuid": "979ac324-4f2a-4554-a260-e0364e62d00f",
  "published": "2020-08-20T08:49:01.196Z",
  "updated": "2020-08-20T08:53:26.402Z",
  "attributedTo": [
    "https://peertube2.cpy.re/video-channels/chocobozzz_channel"
  ],
  "icon": {
    "type": "Image",
    "url": "https://peertube2.cpy.re/lazy-static/thumbnails/playlist-979ac324-4f2a-4554-a260-e0364e62d00f.jpg",
    "mediaType": "image/jpeg",
    "width": 280,
    "height": 157
  }
}

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 they have put up a copy of that file. The origin server then adds the server emitting the CacheFile to the list of WebSeeds for that file so video players can download the video from multiple servers.

TypeScript model: packages/models/src/activitypub/objects/cache-file-object.ts.

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 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!

TypeScript model: packages/models/src/activitypub/objects/video-comment-object.ts.

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[]

  replyApproval: string | null

  to?: string[]
  cc?: string[]
}
json
{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/v1",
    {
      "RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
    },
    {
      "pt": "https://joinpeertube.org/ns#",
      "sc": "http://schema.org/",
      "replyApproval": "pt:replyApproval"
    }
  ],
  "to": [
    "https://www.w3.org/ns/activitystreams#Public"
  ],
  "cc": [
    "https://peertube2.cpy.re/accounts/chocobozzz/followers"
  ],
  "type": "Note",
  "id": "https://peertube2.cpy.re/videos/watch/04af977f-4201-4697-be67-a8d8cae6fa7a/comments/177352",
  "content": "Nice video!!!",
  "mediaType": "text/markdown",
  "inReplyTo": "https://peertube2.cpy.re/videos/watch/04af977f-4201-4697-be67-a8d8cae6fa7a",
  "updated": "2024-05-31T08:28:39.825Z",
  "published": "2024-05-31T08:28:39.805Z",
  "url": "https://peertube2.cpy.re/videos/watch/04af977f-4201-4697-be67-a8d8cae6fa7a/comments/177352",
  "attributedTo": "https://peertube2.cpy.re/accounts/chocobozzz",
  "replyApproval": "https://peertube2.cpy.re/videos/watch/04af977f-4201-4697-be67-a8d8cae6fa7a/comments/177352/approve-reply",
  "tag": []
}

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.

TypeScript model: packages/models/src/activitypub/objects/playlist-object.ts.

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[]
}
json
{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/v1",
    {
      "RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
    },
    {
      "pt": "https://joinpeertube.org/ns#",
      "sc": "http://schema.org/",
      "Playlist": "pt:Playlist",
      "PlaylistElement": "pt:PlaylistElement",
      "position": {
        "@type": "sc:Number",
        "@id": "pt:position"
      },
      "startTimestamp": {
        "@type": "sc:Number",
        "@id": "pt:startTimestamp"
      },
      "stopTimestamp": {
        "@type": "sc:Number",
        "@id": "pt:stopTimestamp"
      },
      "uuid": {
        "@type": "sc:identifier",
        "@id": "pt:uuid"
      }
    }
  ],
  "to": [
    "https://www.w3.org/ns/activitystreams#Public"
  ],
  "cc": [
    "https://peertube2.cpy.re/accounts/chocobozzz/followers"
  ],
  "id": "https://peertube2.cpy.re/video-playlists/979ac324-4f2a-4554-a260-e0364e62d00f",
  "type": "Playlist",
  "totalItems": 3,
  "first": "https://peertube2.cpy.re/video-playlists/979ac324-4f2a-4554-a260-e0364e62d00f?page=1",
  "name": "Test",
  "content": "Test playlist",
  "mediaType": "text/markdown",
  "uuid": "979ac324-4f2a-4554-a260-e0364e62d00f",
  "published": "2020-08-20T08:49:01.196Z",
  "updated": "2020-08-20T08:53:26.402Z",
  "attributedTo": [
    "https://peertube2.cpy.re/video-channels/chocobozzz_channel"
  ],
  "icon": {
    "type": "Image",
    "url": "https://peertube2.cpy.re/lazy-static/thumbnails/playlist-979ac324-4f2a-4554-a260-e0364e62d00f.jpg",
    "mediaType": "image/jpeg",
    "width": 280,
    "height": 157
  }
}

PlaylistElement

INFO

This object is not standard to the ActivityPub specification.

The object is used to represent a video playlist element inside the Playlist object.

TypeScript model: packages/models/src/activitypub/objects/playlist-element-object.ts.

ts
export interface PlaylistElementObject {
  id: string
  type: 'PlaylistElement'

  url: string
  position: number

  startTimestamp?: number
  stopTimestamp?: number
}
json
{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/v1",
    {
      "RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
    },
    {
      "pt": "https://joinpeertube.org/ns#",
      "sc": "http://schema.org/",
      "Playlist": "pt:Playlist",
      "PlaylistElement": "pt:PlaylistElement",
      "position": {
        "@type": "sc:Number",
        "@id": "pt:position"
      },
      "startTimestamp": {
        "@type": "sc:Number",
        "@id": "pt:startTimestamp"
      },
      "stopTimestamp": {
        "@type": "sc:Number",
        "@id": "pt:stopTimestamp"
      },
      "uuid": {
        "@type": "sc:identifier",
        "@id": "pt:uuid"
      }
    }
  ],
  "id": "https://peertube2.cpy.re/video-playlists/979ac324-4f2a-4554-a260-e0364e62d00f/videos/398616",
  "type": "PlaylistElement",
  "url": "https://peertube2.cpy.re/videos/watch/923a178d-d63a-41d4-8dd7-76b31625629a",
  "position": 1
}

Actor

An PeerTube Actor can be:

  • The instance (Application), used to follow other Actor or share anonymous activities like View or WatchAction
  • An account (Person), used to publish or comment videos, report abuses or create video channels
  • A video channel (Group), owned by an account and also used to publish videos. The channel is a Group because we plan to have multiple accounts that can manage the same channel in the future

When a video is published, the account sends a Create activity and the channel sends an Announce activity, both referencing the Video object.

A Video object has the attributedTo property to know the Person and the Group that own it.

ts
import { ActivityIconObject, ActivityPubAttributedTo } from './objects/common-objects.js'

export type ActivityPubActorType = 'Person' | 'Application' | 'Group' | 'Service' | 'Organization'

export interface ActivityPubActor {
  '@context': any[]
  type: ActivityPubActorType
  id: string
  following: string
  followers: string
  playlists?: string
  inbox: string
  outbox: string
  preferredUsername: string
  url: string
  name: string
  endpoints: {
    sharedInbox: string
  }
  summary: string
  attributedTo?: ActivityPubAttributedTo[]

  support?: string
  publicKey: {
    id: string
    owner: string
    publicKeyPem: string
  }

  // Lemmy attribute for groups
  postingRestrictedToMods?: boolean

  image?: ActivityIconObject | ActivityIconObject[]
  icon?: ActivityIconObject | ActivityIconObject[]

  published?: string

  // For export
  likes?: string
  dislikes?: string
}
json
{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/v1",
    {
      "RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
    },
    {
      "pt": "https://joinpeertube.org/ns#",
      "sc": "http://schema.org/",
      "playlists": {
        "@id": "pt:playlists",
        "@type": "@id"
      },
      "support": {
        "@type": "sc:Text",
        "@id": "pt:support"
      },
      "lemmy": "https://join-lemmy.org/ns#",
      "postingRestrictedToMods": "lemmy:postingRestrictedToMods",
      "icons": "as:icon"
    }
  ],
  "type": "Application",
  "id": "https://peertube2.cpy.re/accounts/peertube",
  "following": "https://peertube2.cpy.re/accounts/peertube/following",
  "followers": "https://peertube2.cpy.re/accounts/peertube/followers",
  "playlists": "https://peertube2.cpy.re/accounts/peertube/playlists",
  "inbox": "https://peertube2.cpy.re/accounts/peertube/inbox",
  "outbox": "https://peertube2.cpy.re/accounts/peertube/outbox",
  "preferredUsername": "peertube",
  "url": "https://peertube2.cpy.re/accounts/peertube",
  "name": "peertube",
  "endpoints": {
    "sharedInbox": "https://peertube2.cpy.re/inbox"
  },
  "publicKey": {
    "id": "https://peertube2.cpy.re/accounts/peertube#main-key",
    "owner": "https://peertube2.cpy.re/accounts/peertube",
    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq2szShm/NJow/5pQ2KOU\n73UIYl7Hvy55hBLTlsGPK4jmcYbg5CnjUYmj51jsEunX/grstDzySY3UkZXYm+Ov\n6FVz1A++CQYlMkhWP5tu3PU62zxNKkZHpTHTa28DEJMbcLdwrTAYSHHEN3Th9vp4\n9noMdrNjeF4qmiFd493I5PC7S0zGyrSmSGAjV+AwRNPikBC52KpNfYbsryWnlvgl\nUWUibQVTc8NAbY4WE/d0sTZWLmM3Yk7UtJtQXjjsVXC9xMJfiNvnaInoY88BUri6\n4wvvAwhI0ddvvq4/wQLqY0aztQ8+lfV1bSWw4sqkwY+cY2f4QXGRx6kIwr+oypNi\nuQIDAQAB\n-----END PUBLIC KEY-----"
  },
  "published": "2017-11-28T08:30:56.514Z",
  "icon": [
    {
      "type": "Image",
      "mediaType": "image/png",
      "height": 48,
      "width": 48,
      "url": "https://peertube2.cpy.re/lazy-static/avatars/abace30f-69ad-4ff2-a954-dea06c5db6eb.png"
    },
    {
      "type": "Image",
      "mediaType": "image/png",
      "height": 120,
      "width": 120,
      "url": "https://peertube2.cpy.re/lazy-static/avatars/1163da44-0367-4df9-bf10-a1b0dc0e3fb9.png"
    },
    {
      "type": "Image",
      "mediaType": "image/png",
      "height": 600,
      "width": 600,
      "url": "https://peertube2.cpy.re/lazy-static/avatars/177f70c4-ddef-4bb6-bc96-b00d5e2a0e05.png"
    },
    {
      "type": "Image",
      "mediaType": "image/png",
      "height": 1500,
      "width": 1500,
      "url": "https://peertube2.cpy.re/lazy-static/avatars/82936e50-9560-42e7-9e4b-d96309f5c9c9.png"
    }
  ],
  "summary": null
}
json
{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/v1",
    {
      "RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
    },
    {
      "pt": "https://joinpeertube.org/ns#",
      "sc": "http://schema.org/",
      "playlists": {
        "@id": "pt:playlists",
        "@type": "@id"
      },
      "support": {
        "@type": "sc:Text",
        "@id": "pt:support"
      },
      "lemmy": "https://join-lemmy.org/ns#",
      "postingRestrictedToMods": "lemmy:postingRestrictedToMods",
      "icons": "as:icon"
    }
  ],
  "type": "Person",
  "id": "https://peertube2.cpy.re/accounts/chocobozzz",
  "following": "https://peertube2.cpy.re/accounts/chocobozzz/following",
  "followers": "https://peertube2.cpy.re/accounts/chocobozzz/followers",
  "playlists": "https://peertube2.cpy.re/accounts/chocobozzz/playlists",
  "inbox": "https://peertube2.cpy.re/accounts/chocobozzz/inbox",
  "outbox": "https://peertube2.cpy.re/accounts/chocobozzz/outbox",
  "preferredUsername": "chocobozzz",
  "url": "https://peertube2.cpy.re/accounts/chocobozzz",
  "name": "chocobozzz",
  "endpoints": {
    "sharedInbox": "https://peertube2.cpy.re/inbox"
  },
  "publicKey": {
    "id": "https://peertube2.cpy.re/accounts/chocobozzz#main-key",
    "owner": "https://peertube2.cpy.re/accounts/chocobozzz",
    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy9i2I+4Bf3p+l8hELlqG\n4mtYC6tjFp5S6lNtM/9mgJTXHe35GI38gXY3uGKm0eF0DZFZZCWr5kKrz4U0hzEV\now6n0q4MIspq7FV8dOH8+e37W3d9+PJpkOarJry7/Kxvjir6U/uHUucIkTKFuPU5\nzbzImwxN5gg8T3ApjGhn3OQMBxdHR0zufqkakKiDK15KULVrONB/T/BmBafjD7C6\njB//dWtpKQPGUWGtLd5JkxBLwb1gTIfQe13pbhy85jMpjTQQ0+tMULldN3a7xbpB\n4m4MViqZXBzT1mrK66lKMxLRgluMPJUWgkkfzPXrtMhSlrwgG+v7FArTq+ci8wog\ntwIDAQAB\n-----END PUBLIC KEY-----"
  },
  "published": "2019-03-29T15:49:24.036Z",
  "icon": [
    {
      "type": "Image",
      "mediaType": "image/png",
      "height": 48,
      "width": 48,
      "url": "https://peertube2.cpy.re/lazy-static/avatars/b24bc0df-e472-4e60-8c2f-9ccada1599af.png"
    },
    {
      "type": "Image",
      "mediaType": "image/png",
      "height": 120,
      "width": 120,
      "url": "https://peertube2.cpy.re/lazy-static/avatars/69e95cbe-9293-4859-a996-a24a4ab7befb.png"
    }
  ],
  "summary": null
}
json
{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/v1",
    {
      "RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
    },
    {
      "pt": "https://joinpeertube.org/ns#",
      "sc": "http://schema.org/",
      "playlists": {
        "@id": "pt:playlists",
        "@type": "@id"
      },
      "support": {
        "@type": "sc:Text",
        "@id": "pt:support"
      },
      "lemmy": "https://join-lemmy.org/ns#",
      "postingRestrictedToMods": "lemmy:postingRestrictedToMods",
      "icons": "as:icon"
    }
  ],
  "type": "Group",
  "id": "https://peertube2.cpy.re/video-channels/chocobozzz_channel",
  "following": "https://peertube2.cpy.re/video-channels/chocobozzz_channel/following",
  "followers": "https://peertube2.cpy.re/video-channels/chocobozzz_channel/followers",
  "playlists": "https://peertube2.cpy.re/video-channels/chocobozzz_channel/playlists",
  "inbox": "https://peertube2.cpy.re/video-channels/chocobozzz_channel/inbox",
  "outbox": "https://peertube2.cpy.re/video-channels/chocobozzz_channel/outbox",
  "preferredUsername": "chocobozzz_channel",
  "url": "https://peertube2.cpy.re/video-channels/chocobozzz_channel",
  "name": "Main chocobozzz channel",
  "endpoints": {
    "sharedInbox": "https://peertube2.cpy.re/inbox"
  },
  "publicKey": {
    "id": "https://peertube2.cpy.re/video-channels/chocobozzz_channel#main-key",
    "owner": "https://peertube2.cpy.re/video-channels/chocobozzz_channel",
    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1Wq/69fJRaBK4RQE88Kc\nv1yyGtgphMNdw4cqGSN1dDyes4eCH2EHPKdMav61eP3bc2AjBnpwJXf07UKL/+N+\nFZO3NVTChwm9H1wvYVuXUeOQOMDRevvabrRL7OkmaRKJ1t1INFwe8fMnMgXKpaM7\n92OkFc+nUbkPdbR4HkjEZgVFDIXItoTiIKY/7cez4QxTv4wVOTBaZkJFLfYolryV\nbGvuwtzoVw83/P65Ig3f/BnFnXKmvx55VaE+7EDlIVWERRnahWI+MI/hLb5OkQAc\nU0z8YuJvz+NqLecuFNOIHOW1u++yGm9doDOEhNTuF6N1pjTunCjvkfTtRaY+qlpL\nNwIDAQAB\n-----END PUBLIC KEY-----"
  },
  "published": "2019-03-29T15:49:24.067Z",
  "icon": [
    {
      "type": "Image",
      "mediaType": "image/jpeg",
      "height": 48,
      "width": 48,
      "url": "https://peertube2.cpy.re/lazy-static/avatars/5b9bf735-d9a7-4967-836d-161496fcb0b3.jpg"
    },
    {
      "type": "Image",
      "mediaType": "image/jpeg",
      "height": 120,
      "width": 120,
      "url": "https://peertube2.cpy.re/lazy-static/avatars/14ee9081-9d4c-444e-af97-9cfb69fef83d.jpg"
    }
  ],
  "image": [
    {
      "type": "Image",
      "mediaType": "image/jpeg",
      "height": 317,
      "width": 1920,
      "url": "https://peertube2.cpy.re/lazy-static/banners/49081f1e-f9c3-403a-b657-dff113b023b4.jpg"
    }
  ],
  "summary": null,
  "support": null,
  "postingRestrictedToMods": true,
  "attributedTo": [
    {
      "type": "Person",
      "id": "https://peertube2.cpy.re/accounts/chocobozzz"
    }
  ]
}

WatchAction

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.

TypeScript model: packages/models/src/activitypub/objects/watch-action-object.ts.

ts
export interface WatchActionObject {
  id: string
  type: 'WatchAction'

  startTime: string
  endTime: string

  location?: {
    addressCountry: string
    addressRegion: string
  }

  uuid: string
  object: string
  actionStatus: 'CompletedActionStatus'

  duration: string

  watchSections: {
    startTimestamp: number
    endTimestamp: number
  }[]
}