]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame_incremental - client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts
Bumped to version v5.2.1
[github/Chocobozzz/PeerTube.git] / client / src / app / +videos / +video-edit / video-add-components / video-go-live.component.ts
... / ...
CommitLineData
1import { forkJoin } from 'rxjs'
2import { AfterViewInit, Component, EventEmitter, OnInit, Output } from '@angular/core'
3import { Router } from '@angular/router'
4import { AuthService, CanComponentDeactivate, HooksService, Notifier, ServerService } from '@app/core'
5import { scrollToTop } from '@app/helpers'
6import { FormReactiveService } from '@app/shared/shared-forms'
7import { Video, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main'
8import { LiveVideoService } from '@app/shared/shared-video-live'
9import { LoadingBarService } from '@ngx-loading-bar/core'
10import { logger } from '@root-helpers/logger'
11import {
12 LiveVideo,
13 LiveVideoCreate,
14 LiveVideoLatencyMode,
15 LiveVideoUpdate,
16 PeerTubeProblemDocument,
17 ServerErrorCode,
18 VideoPrivacy
19} from '@shared/models'
20import { VideoSend } from './video-send'
21
22@Component({
23 selector: 'my-video-go-live',
24 templateUrl: './video-go-live.component.html',
25 styleUrls: [
26 '../shared/video-edit.component.scss',
27 './video-go-live.component.scss',
28 './video-send.scss'
29 ]
30})
31export class VideoGoLiveComponent extends VideoSend implements OnInit, AfterViewInit, CanComponentDeactivate {
32 @Output() firstStepDone = new EventEmitter<string>()
33 @Output() firstStepError = new EventEmitter<void>()
34
35 firstStepPermanentLive: boolean
36
37 isInUpdateForm = false
38 isUpdatingVideo = false
39 isOrHasGoingLive = false
40
41 liveVideo: LiveVideo
42
43 videoId: number
44 videoUUID: string
45 videoShortUUID: string
46
47 error: string
48
49 constructor (
50 protected formReactiveService: FormReactiveService,
51 protected loadingBar: LoadingBarService,
52 protected notifier: Notifier,
53 protected authService: AuthService,
54 protected serverService: ServerService,
55 protected videoService: VideoService,
56 protected videoCaptionService: VideoCaptionService,
57 private liveVideoService: LiveVideoService,
58 private router: Router,
59 private hooks: HooksService
60 ) {
61 super()
62 }
63
64 ngOnInit () {
65 super.ngOnInit()
66 }
67
68 ngAfterViewInit () {
69 this.hooks.runAction('action:go-live.init', 'video-edit')
70 }
71
72 canDeactivate () {
73 return { canDeactivate: true }
74 }
75
76 goLive () {
77 if (this.isOrHasGoingLive) return
78 this.isOrHasGoingLive = true
79
80 const name = 'Live'
81
82 const video: LiveVideoCreate = {
83 name,
84 privacy: this.highestPrivacy,
85 nsfw: this.serverConfig.instance.isNSFW,
86 waitTranscoding: true,
87 permanentLive: this.firstStepPermanentLive,
88 latencyMode: LiveVideoLatencyMode.DEFAULT,
89 saveReplay: this.isReplayAllowed(),
90 replaySettings: { privacy: VideoPrivacy.PRIVATE },
91 channelId: this.firstStepChannelId
92 }
93
94 // Go live in private mode, but correctly fill the update form with the first user choice
95 const toPatch = { ...video, privacy: this.firstStepPrivacyId, replayPrivacy: video.replaySettings.privacy }
96 this.form.patchValue(toPatch)
97
98 this.liveVideoService.goLive(video)
99 .subscribe({
100 next: res => {
101 this.videoId = res.video.id
102 this.videoUUID = res.video.uuid
103 this.videoShortUUID = res.video.shortUUID
104 this.isInUpdateForm = true
105
106 this.firstStepDone.emit(name)
107
108 this.fetchVideoLive()
109 },
110
111 error: err => {
112 this.firstStepError.emit()
113
114 let message = err.message
115
116 const error = err.body as PeerTubeProblemDocument
117
118 if (error?.code === ServerErrorCode.MAX_INSTANCE_LIVES_LIMIT_REACHED) {
119 message = $localize`Cannot create live because this instance have too many created lives`
120 } else if (error?.code === ServerErrorCode.MAX_USER_LIVES_LIMIT_REACHED) {
121 message = $localize`Cannot create live because you created too many lives`
122 }
123
124 this.notifier.error(message)
125 }
126 })
127 }
128
129 async updateSecondStep () {
130 if (!await this.isFormValid()) return
131
132 this.isUpdatingVideo = true
133
134 const video = new VideoEdit()
135 video.patch(this.form.value)
136 video.id = this.videoId
137 video.uuid = this.videoUUID
138 video.shortUUID = this.videoShortUUID
139
140 const saveReplay = this.form.value.saveReplay
141 const replaySettings = saveReplay
142 ? { privacy: this.form.value.replayPrivacy }
143 : undefined
144
145 const liveVideoUpdate: LiveVideoUpdate = {
146 saveReplay,
147 replaySettings,
148 latencyMode: this.form.value.latencyMode,
149 permanentLive: this.form.value.permanentLive
150 }
151
152 // Update the video
153 forkJoin([
154 this.updateVideoAndCaptions(video),
155
156 this.liveVideoService.updateLive(this.videoId, liveVideoUpdate)
157 ]).subscribe({
158 next: () => {
159 this.isUpdatingVideo = false
160
161 this.notifier.success($localize`Live published.`)
162
163 this.router.navigateByUrl(Video.buildWatchUrl(video))
164 },
165
166 error: err => {
167 this.error = err.message
168 scrollToTop()
169 logger.error(err)
170 }
171 })
172 }
173
174 getMaxLiveDuration () {
175 return this.serverConfig.live.maxDuration / 1000
176 }
177
178 getNormalLiveDescription () {
179 if (this.isReplayAllowed()) {
180 return $localize`Stream only once, replay will replace your live`
181 }
182
183 return $localize`Stream only once`
184 }
185
186 getPermanentLiveDescription () {
187 if (this.isReplayAllowed()) {
188 return $localize`Stream multiple times, replays will be separate videos`
189 }
190
191 return $localize`Stream multiple times using the same URL`
192 }
193
194 private isReplayAllowed () {
195 return this.serverConfig.live.allowReplay
196 }
197
198 private fetchVideoLive () {
199 this.liveVideoService.getVideoLive(this.videoId)
200 .subscribe({
201 next: liveVideo => {
202 this.liveVideo = liveVideo
203 },
204
205 error: err => {
206 this.firstStepError.emit()
207 this.notifier.error(err.message)
208 }
209 })
210 }
211}