full diff

place.stream.media.finalizeLivestream

stream.place +10 −58
From
bafyreibefveohfqtht24oep6cn3fblgz3hufteaxupdno4xr3j5xvgnwua indexed 2026-11-04 01:29 UTC View this version
To
bafyreid7oqrjuv2wwuyffqaaxax6sov7wv4g6lrf3m7gfaqwplltyd644u indexed 2026-08-20 16:29 UTC View this version

Compatibility

breaking 24 breaking changes, 2 non-breaking changes.

Breaking changes (24)
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "place.stream.media.finalizeLivestream:input", src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.livestream", kind: "prop", name: Some("livestream") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "place.stream.media.finalizeLivestream:output", src: "place.stream.media.finalizeLivestream:output", tgt: "place.stream.media.finalizeLivestream:output.draftUri", kind: "prop", name: Some("draftUri") }
  • RemovedVertex RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.description" }
  • RemovedVertex RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.endLivestream" }
  • RemovedVertex RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.livestreams" }
  • RemovedVertex RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.livestreams:items" }
  • RemovedVertex RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.publish" }
  • RemovedVertex RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.title" }
  • RemovedVertex RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:output.ended" }
  • RemovedVertex RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:output.ended:items" }
  • RemovedVertex RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:output.livestreams" }
  • RemovedVertex RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:output.livestreams:items" }
  • RemovedVertex RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:output.objects" }
  • RemovedEdge RemovedEdge { src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.description", kind: "prop", name: Some("description") }
  • RemovedEdge RemovedEdge { src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.endLivestream", kind: "prop", name: Some("endLivestream") }
  • RemovedEdge RemovedEdge { src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.livestreams", kind: "prop", name: Some("livestreams") }
  • RemovedEdge RemovedEdge { src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.publish", kind: "prop", name: Some("publish") }
  • RemovedEdge RemovedEdge { src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.title", kind: "prop", name: Some("title") }
  • RemovedEdge RemovedEdge { src: "place.stream.media.finalizeLivestream:input.livestreams", tgt: "place.stream.media.finalizeLivestream:input.livestreams:items", kind: "items", name: None }
  • RemovedEdge RemovedEdge { src: "place.stream.media.finalizeLivestream:output", tgt: "place.stream.media.finalizeLivestream:output.ended", kind: "prop", name: Some("ended") }
  • RemovedEdge RemovedEdge { src: "place.stream.media.finalizeLivestream:output", tgt: "place.stream.media.finalizeLivestream:output.livestreams", kind: "prop", name: Some("livestreams") }
  • RemovedEdge RemovedEdge { src: "place.stream.media.finalizeLivestream:output", tgt: "place.stream.media.finalizeLivestream:output.objects", kind: "prop", name: Some("objects") }
  • RemovedEdge RemovedEdge { src: "place.stream.media.finalizeLivestream:output.ended", tgt: "place.stream.media.finalizeLivestream:output.ended:items", kind: "items", name: None }
  • RemovedEdge RemovedEdge { src: "place.stream.media.finalizeLivestream:output.livestreams", tgt: "place.stream.media.finalizeLivestream:output.livestreams:items", kind: "items", name: None }
Non-breaking changes (2)
  • AddedVertex AddedVertex { vertex_id: "place.stream.media.finalizeLivestream:params" }
  • AddedEdge AddedEdge { src: "place.stream.media.finalizeLivestream", tgt: "place.stream.media.finalizeLivestream:params", kind: "prop", name: Some("parameters") }

Migration guidance

Removed

  • RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.description" }
  • RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.endLivestream" }
  • RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.livestreams" }
  • RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.livestreams:items" }
  • RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.publish" }
  • RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:input.title" }
  • RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:output.ended" }
  • RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:output.ended:items" }
  • RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:output.livestreams" }
  • RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:output.livestreams:items" }
  • RemovedVertex { vertex_id: "place.stream.media.finalizeLivestream:output.objects" }

Added

  • AddedVertex { vertex_id: "place.stream.media.finalizeLivestream:params" }

Notes

  • Breaking: RequiredEdgeAdded { vertex_id: "place.stream.media.finalizeLivestream:output", src: "place.stream.media.finalizeLivestream:output", tgt: "place.stream.media.finalizeLivestream:output.draftUri", kind: "prop", name: Some("draftUri") }
  • Breaking: RequiredEdgeAdded { vertex_id: "place.stream.media.finalizeLivestream:input", src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.livestream", kind: "prop", name: Some("livestream") }
  • Breaking: RemovedEdge { src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.description", kind: "prop", name: Some("description") }
  • Breaking: RemovedEdge { src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.endLivestream", kind: "prop", name: Some("endLivestream") }
  • Breaking: RemovedEdge { src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.livestreams", kind: "prop", name: Some("livestreams") }
  • Breaking: RemovedEdge { src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.publish", kind: "prop", name: Some("publish") }
  • Breaking: RemovedEdge { src: "place.stream.media.finalizeLivestream:input", tgt: "place.stream.media.finalizeLivestream:input.title", kind: "prop", name: Some("title") }
  • Breaking: RemovedEdge { src: "place.stream.media.finalizeLivestream:input.livestreams", tgt: "place.stream.media.finalizeLivestream:input.livestreams:items", kind: "items", name: None }
  • Breaking: RemovedEdge { src: "place.stream.media.finalizeLivestream:output", tgt: "place.stream.media.finalizeLivestream:output.ended", kind: "prop", name: Some("ended") }
  • Breaking: RemovedEdge { src: "place.stream.media.finalizeLivestream:output", tgt: "place.stream.media.finalizeLivestream:output.livestreams", kind: "prop", name: Some("livestreams") }
  • Breaking: RemovedEdge { src: "place.stream.media.finalizeLivestream:output", tgt: "place.stream.media.finalizeLivestream:output.objects", kind: "prop", name: Some("objects") }
  • Breaking: RemovedEdge { src: "place.stream.media.finalizeLivestream:output.ended", tgt: "place.stream.media.finalizeLivestream:output.ended:items", kind: "items", name: None }
  • Breaking: RemovedEdge { src: "place.stream.media.finalizeLivestream:output.livestreams", tgt: "place.stream.media.finalizeLivestream:output.livestreams:items", kind: "items", name: None }
  • Non-breaking: AddedEdge { src: "place.stream.media.finalizeLivestream", tgt: "place.stream.media.finalizeLivestream:params", kind: "prop", name: Some("parameters") }

Changes

11{
22 "$type": "com.atproto.lexicon.schema",
33 "defs": {
44 "main": {
5 "description": "Turn a finished livestream into a VOD. The server concatenates the MUXL segments it recorded for the livestream(s) into a single content blob, derives the playback sidecars, and publishes the place.stream.media.track records. By default it leaves a draft VOD the streamer publishes later via place.stream.vod.publishDraft; with publish set it publishes the place.stream.video record as soon as the VOD is finalized. The caller must be the streamer, or a moderator they have granted livestream.manage; every record is written with the streamer's session.",
5 "description": "Turn a finished livestream into a VOD. The server concatenates the MUXL segments it recorded for the livestream into a single content blob, derives the playback sidecars, and publishes the place.stream.media.track records. Processing completes server-side and creates a draft VOD; the client does not need to poll or publish — the user publishes the draft later via place.stream.vod.publishDraft. Returns the draft's ats:// URI so the client can navigate to it, alongside an uploadId for backwards compatibility.",
66 "errors": [
77 {
8 "description": "No livestream with the given URI is known to this node, or the livestreams belong to different streamers.",
8 "description": "No livestream with the given URI is known, or it does not belong to the authenticated user.",
99 "name": "LivestreamNotFound"
1010 },
1111 {
1212 "description": "The livestream has no recorded MUXL segments to finalize (recording was not enabled, or none completed).",
1313 "name": "NoRecording"
14 },
15 {
16 "description": "The caller is neither the streamer nor a moderator with livestream.manage from them.",
17 "name": "NotPermitted"
1814 }
1915 ],
2016 "input": {
2117 "encoding": "application/json",
2218 "schema": {
2319 "properties": {
24 "description": {
25 "description": "Description of the video record.",
26 "maxLength": 10000,
27 "type": "string"
28 },
29 "endLivestream": {
30 "default": false,
31 "description": "Also end any of the livestream records that were never stopped, so the streamer's page stops reading as live.",
32 "type": "boolean"
33 },
3420 "livestream": {
35 "description": "AT-URI of the place.stream.livestream record to finalize into a VOD. Either this or livestreams is required.",
21 "description": "AT-URI of the place.stream.livestream record to finalize into a VOD. Must belong to the authenticated user.",
3622 "format": "at-uri",
3723 "type": "string"
38 },
39 "livestreams": {
40 "description": "Several livestream records whose recordings make up one VOD: a streamer who started a new record mid-stream splits the recording across them. Recordings are concatenated in the records' creation order, whatever order they are listed in. All must belong to one streamer.",
41 "items": {
42 "format": "at-uri",
43 "type": "string"
44 },
45 "type": "array"
46 },
47 "publish": {
48 "default": false,
49 "description": "Publish the place.stream.video record as soon as the VOD is finalized, instead of leaving a draft.",
50 "type": "boolean"
51 },
52 "title": {
53 "description": "Title of the video record; the first livestream's title when empty.",
54 "maxLength": 1000,
55 "type": "string"
5624 }
5725 },
58 "required": [],
26 "required": [
27 "livestream"
28 ],
5929 "type": "object"
6030 }
6131 },
6232 "output": {
6333 "encoding": "application/json",
6434 "schema": {
6535 "properties": {
6636 "draftUri": {
67 "description": "The ats:// URI of the draft VOD created for this finalize, when publish is not set. The draft reaches status 'ready' when processing completes.",
37 "description": "The ats:// URI of the draft VOD created for this finalize. The draft reaches status 'ready' when processing completes; the user publishes it from the Drafts tab via place.stream.vod.publishDraft.",
6838 "type": "string"
6939 },
70 "ended": {
71 "description": "Livestream records that are now ended (already, or by endLivestream).",
72 "items": {
73 "format": "at-uri",
74 "type": "string"
75 },
76 "type": "array"
77 },
78 "livestreams": {
79 "description": "The livestream records the VOD is made of, in recording order.",
80 "items": {
81 "format": "at-uri",
82 "type": "string"
83 },
84 "type": "array"
85 },
86 "objects": {
87 "description": "How many recorded objects will be concatenated.",
88 "type": "integer"
89 },
9040 "uploadId": {
9141 "description": "Identifier for the finalize job. Retained for backwards compatibility; the draft flow no longer requires the client to poll getUploadStatus.",
9242 "type": "string"
9343 }
9444 },
9545 "required": [
96 "uploadId"
46 "uploadId",
47 "draftUri"
9748 ],
9849 "type": "object"
9950 }
10051 },
52 "parameters": null,
10153 "type": "procedure"
10254 }
10355 },
10456 "id": "place.stream.media.finalizeLivestream",
10557 "lexicon": 1
10658}