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