From b50dbd27563f00f71ac86919edb901a3d70567aa Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Tue, 19 Nov 2024 16:44:52 -0800 Subject: [PATCH 01/18] Add enable option to service layer --- app/services/platforms/youtube.ts | 51 +++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index 514f74f46d0e..b66cb3d5ff8a 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -42,6 +42,7 @@ export interface IYoutubeStartStreamOptions extends IExtraBroadcastSettings { privacyStatus?: 'private' | 'public' | 'unlisted'; scheduledStartTime?: number; mode?: TOutputOrientation; + monetizationEnabled?: boolean; } /** @@ -95,8 +96,22 @@ export interface IYoutubeLiveBroadcast { madeForKids: boolean; selfDeclaredMadeForKids: boolean; }; + monetizationDetails?: { + cuepointSchedule: { + enabled?: boolean; + pauseAdsUntil?: Date; + scheduleStrategy?: string; + repeatIntervalSecs?: number; + }; + }; } +type TYoutubeLiveBroadcastKey = keyof IYoutubeLiveBroadcast; +interface IYoutubeLiveBroadcastPatch + extends Partial< + Record> + > {} + /** * A liveStream resource contains information about the video stream that you are transmitting to YouTube. * The stream provides the content that will be broadcast to YouTube users. Once created, @@ -501,7 +516,7 @@ export class YoutubeService const scheduledStartTime = params.scheduledStartTime ? new Date(params.scheduledStartTime) : new Date(); - const data: Dictionary = { + const data: IYoutubeLiveBroadcastPatch = { snippet: { title: params.title, scheduledStartTime: scheduledStartTime.toISOString(), @@ -520,6 +535,14 @@ export class YoutubeService }, }; + if (params.monetizationEnabled) { + data.monetizationDetails = { + cuepointSchedule: { + enabled: params.monetizationEnabled, + }, + }; + } + const broadcast = await this.requestYoutube({ body: JSON.stringify(data), method: 'POST', @@ -553,7 +576,7 @@ export class YoutubeService scheduledStartTime: scheduledStartTime.toISOString(), }; - const contentDetails: Dictionary = { + const contentDetails: Partial = { enableAutoStart: isMidStreamMode ? broadcast.contentDetails.enableAutoStart : params.enableAutoStart, @@ -582,8 +605,30 @@ export class YoutubeService }; const fields = ['snippet', 'status', 'contentDetails']; + + let monetizationDetails: Partial; + if (broadcast.monetizationDetails) { + fields.push('monetizationDetails'); + + const moneyInfo = broadcast.monetizationDetails.cuepointSchedule; + monetizationDetails = { + cuepointSchedule: { + enabled: moneyInfo.enabled, + pauseAdsUntil: moneyInfo.pauseAdsUntil, + scheduleStrategy: moneyInfo.scheduleStrategy, + repeatIntervalSecs: moneyInfo.repeatIntervalSecs, + }, + }; + } + const endpoint = `liveBroadcasts?part=${fields.join(',')}&id=${id}`; - const body: Dictionary = { id, snippet, contentDetails, status }; + const body: IYoutubeLiveBroadcastPatch = { + id, + snippet, + contentDetails, + status, + monetizationDetails, + }; broadcast = await this.requestYoutube({ body: JSON.stringify(body), From f4eaf78e8c5e97cc3fa7ec51567d40d57b8932f7 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Wed, 20 Nov 2024 10:47:36 -0800 Subject: [PATCH 02/18] Add Frontend input --- .../windows/go-live/platforms/YoutubeEditStreamInfo.tsx | 5 +++++ app/services/platforms/youtube.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx b/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx index 63e173b554cf..4edb8532af35 100644 --- a/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx +++ b/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx @@ -40,6 +40,8 @@ export const YoutubeEditStreamInfo = InputComponent((p: IPlatformComponentParams fieldName => ({ disabled: fieldIsDisabled(fieldName as keyof IYoutubeStartStreamOptions) }), ); + const monetizationElligible = true; + const { broadcastsQuery } = useModule(() => { const youtube = inject(YoutubeService); @@ -207,6 +209,9 @@ export const YoutubeEditStreamInfo = InputComponent((p: IPlatformComponentParams )}

)} + {monetizationElligible && ( + + )} )} diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index b66cb3d5ff8a..bf6434e68a93 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -613,7 +613,7 @@ export class YoutubeService const moneyInfo = broadcast.monetizationDetails.cuepointSchedule; monetizationDetails = { cuepointSchedule: { - enabled: moneyInfo.enabled, + enabled: isMidStreamMode ? moneyInfo.enabled : params.monetizationEnabled, pauseAdsUntil: moneyInfo.pauseAdsUntil, scheduleStrategy: moneyInfo.scheduleStrategy, repeatIntervalSecs: moneyInfo.repeatIntervalSecs, From 4d7092d515321d04dafe046ad64b80c9a58cb87b Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Mon, 16 Dec 2024 15:18:12 -0800 Subject: [PATCH 03/18] Add elligibility check --- .../windows/go-live/platforms/YoutubeEditStreamInfo.tsx | 6 ++---- app/services/platforms/youtube.ts | 5 +++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx b/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx index 4edb8532af35..cc946a336b50 100644 --- a/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx +++ b/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx @@ -6,7 +6,7 @@ import { InputComponent, ListInput, } from '../../../shared/inputs'; -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { Services } from '../../../service-provider'; import { $t } from '../../../../services/i18n'; import BroadcastInput from './BroadcastInput'; @@ -40,8 +40,6 @@ export const YoutubeEditStreamInfo = InputComponent((p: IPlatformComponentParams fieldName => ({ disabled: fieldIsDisabled(fieldName as keyof IYoutubeStartStreamOptions) }), ); - const monetizationElligible = true; - const { broadcastsQuery } = useModule(() => { const youtube = inject(YoutubeService); @@ -209,7 +207,7 @@ export const YoutubeEditStreamInfo = InputComponent((p: IPlatformComponentParams )}

)} - {monetizationElligible && ( + {ytSettings.elligibleForMonetization && ( )} diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index bf6434e68a93..55de7f0a4ff0 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -43,6 +43,7 @@ export interface IYoutubeStartStreamOptions extends IExtraBroadcastSettings { scheduledStartTime?: number; mode?: TOutputOrientation; monetizationEnabled?: boolean; + elligibleForMonetization?: boolean; } /** @@ -103,6 +104,7 @@ export interface IYoutubeLiveBroadcast { scheduleStrategy?: string; repeatIntervalSecs?: number; }; + elligibleForAdsMonetization?: boolean; }; } @@ -221,6 +223,7 @@ export class YoutubeService thumbnail: '', video: undefined, mode: undefined, + monetizationEnabled: false, }, }; @@ -805,6 +808,8 @@ export class YoutubeService latencyPreference, categoryId: video.snippet.categoryId, thumbnail: broadcast.snippet.thumbnails.default.url, + monetizationEnabled: broadcast.monetizationDetails?.cuepointSchedule?.enabled, + elligibleForMonetization: broadcast.monetizationDetails?.elligibleForAdsMonetization, }; } From 80e81bb8b08f53f747f17370c288c500b5220440 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Mon, 16 Dec 2024 16:49:28 -0800 Subject: [PATCH 04/18] Add logs --- app/services/platforms/youtube.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index 55de7f0a4ff0..d7e7da989f65 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -794,6 +794,10 @@ export class YoutubeService this.fetchBroadcast(broadcastId), this.fetchVideo(broadcastId), ]); + console.log('BROADCAST'); + console.log(broadcast); + console.log('VIDEO'); + console.log(video); const { title, description } = broadcast.snippet; const { privacyStatus, selfDeclaredMadeForKids } = broadcast.status; const { enableDvr, projection, latencyPreference } = broadcast.contentDetails; From 33578558bef93e51791896a507e63a133a6dc569 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Mon, 16 Dec 2024 17:07:18 -0800 Subject: [PATCH 05/18] Fix logs --- app/services/platforms/youtube.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index d7e7da989f65..f77beabb4c5a 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -795,9 +795,9 @@ export class YoutubeService this.fetchVideo(broadcastId), ]); console.log('BROADCAST'); - console.log(broadcast); + console.log(JSON.stringify(broadcast, null, 2)); console.log('VIDEO'); - console.log(video); + console.log(JSON.stringify(video, null, 2)); const { title, description } = broadcast.snippet; const { privacyStatus, selfDeclaredMadeForKids } = broadcast.status; const { enableDvr, projection, latencyPreference } = broadcast.contentDetails; From ad9a73472c242702f6845eb2283e0ffe6b9560a9 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Tue, 17 Dec 2024 10:33:43 -0800 Subject: [PATCH 06/18] Add monetizationDetails to fetch --- app/services/platforms/youtube.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index f77beabb4c5a..f1550f09bbf9 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -764,7 +764,7 @@ export class YoutubeService async fetchBroadcast( id: string, - fields = ['snippet', 'contentDetails', 'status'], + fields = ['snippet', 'contentDetails', 'status', 'monetizationDetails'], ): Promise { const filter = `&id=${id}`; const query = `part=${fields.join(',')}${filter}&maxResults=1`; From 7e87c0b9b30ce841b50087e95f68e059752c3571 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Fri, 20 Dec 2024 10:21:55 -0800 Subject: [PATCH 07/18] Fix typo --- .../windows/go-live/platforms/YoutubeEditStreamInfo.tsx | 2 +- app/services/platforms/youtube.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx b/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx index cc946a336b50..37afe5cdb27c 100644 --- a/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx +++ b/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx @@ -207,7 +207,7 @@ export const YoutubeEditStreamInfo = InputComponent((p: IPlatformComponentParams )}

)} - {ytSettings.elligibleForMonetization && ( + {ytSettings.eligibleForMonetization && ( )} diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index f1550f09bbf9..b7fad5a2b906 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -43,7 +43,7 @@ export interface IYoutubeStartStreamOptions extends IExtraBroadcastSettings { scheduledStartTime?: number; mode?: TOutputOrientation; monetizationEnabled?: boolean; - elligibleForMonetization?: boolean; + eligibleForMonetization?: boolean; } /** @@ -104,7 +104,7 @@ export interface IYoutubeLiveBroadcast { scheduleStrategy?: string; repeatIntervalSecs?: number; }; - elligibleForAdsMonetization?: boolean; + eligibleForAdsMonetization?: boolean; }; } @@ -813,7 +813,7 @@ export class YoutubeService categoryId: video.snippet.categoryId, thumbnail: broadcast.snippet.thumbnails.default.url, monetizationEnabled: broadcast.monetizationDetails?.cuepointSchedule?.enabled, - elligibleForMonetization: broadcast.monetizationDetails?.elligibleForAdsMonetization, + eligibleForMonetization: broadcast.monetizationDetails?.eligibleForAdsMonetization, }; } From f8630b7ee4a1f21202d1bfdbdf53b7a7f2f16414 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Fri, 20 Dec 2024 14:41:51 -0800 Subject: [PATCH 08/18] Fix createBroadcast --- app/services/platforms/youtube.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index b7fad5a2b906..301886544625 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -539,6 +539,7 @@ export class YoutubeService }; if (params.monetizationEnabled) { + fields.push('monetizationDetails'); data.monetizationDetails = { cuepointSchedule: { enabled: params.monetizationEnabled, From b5cb91e585b6561614b4e959ced7d1e38bcacf53 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Thu, 9 Jan 2025 14:13:30 -0800 Subject: [PATCH 09/18] Fix optional strings --- app/services/platforms/youtube.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index 301886544625..a5957fb03e56 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -100,7 +100,7 @@ export interface IYoutubeLiveBroadcast { monetizationDetails?: { cuepointSchedule: { enabled?: boolean; - pauseAdsUntil?: Date; + pauseAdsUntil?: string; scheduleStrategy?: string; repeatIntervalSecs?: number; }; @@ -617,10 +617,10 @@ export class YoutubeService const moneyInfo = broadcast.monetizationDetails.cuepointSchedule; monetizationDetails = { cuepointSchedule: { - enabled: isMidStreamMode ? moneyInfo.enabled : params.monetizationEnabled, - pauseAdsUntil: moneyInfo.pauseAdsUntil, - scheduleStrategy: moneyInfo.scheduleStrategy, - repeatIntervalSecs: moneyInfo.repeatIntervalSecs, + enabled: isMidStreamMode ? moneyInfo?.enabled : params.monetizationEnabled, + pauseAdsUntil: moneyInfo?.pauseAdsUntil, + scheduleStrategy: moneyInfo?.scheduleStrategy, + repeatIntervalSecs: moneyInfo?.repeatIntervalSecs, }, }; } From 676371ac7209b96e99ab4599ed919e0b473d18bc Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Thu, 9 Jan 2025 15:57:17 -0800 Subject: [PATCH 10/18] Add missing field --- app/services/platforms/youtube.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index a5957fb03e56..f6a1316318ec 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -104,6 +104,7 @@ export interface IYoutubeLiveBroadcast { scheduleStrategy?: string; repeatIntervalSecs?: number; }; + adsMonetizationStatus?: 'on' | 'off'; eligibleForAdsMonetization?: boolean; }; } @@ -541,6 +542,7 @@ export class YoutubeService if (params.monetizationEnabled) { fields.push('monetizationDetails'); data.monetizationDetails = { + adsMonetizationStatus: this.getMonetizationStatus(params.monetizationEnabled), cuepointSchedule: { enabled: params.monetizationEnabled, }, @@ -616,6 +618,9 @@ export class YoutubeService const moneyInfo = broadcast.monetizationDetails.cuepointSchedule; monetizationDetails = { + adsMonetizationStatus: this.getMonetizationStatus( + isMidStreamMode ? moneyInfo?.enabled : params.monetizationEnabled, + ), cuepointSchedule: { enabled: isMidStreamMode ? moneyInfo?.enabled : params.monetizationEnabled, pauseAdsUntil: moneyInfo?.pauseAdsUntil, @@ -777,6 +782,10 @@ export class YoutubeService ).items[0]; } + getMonetizationStatus(val: boolean) { + return val ? 'on' : 'off'; + } + get chatUrl() { const broadcastId = this.state.settings.broadcastId; if (!broadcastId) return ''; @@ -813,7 +822,7 @@ export class YoutubeService latencyPreference, categoryId: video.snippet.categoryId, thumbnail: broadcast.snippet.thumbnails.default.url, - monetizationEnabled: broadcast.monetizationDetails?.cuepointSchedule?.enabled, + monetizationEnabled: broadcast.monetizationDetails?.adsMonetizationStatus === 'on', eligibleForMonetization: broadcast.monetizationDetails?.eligibleForAdsMonetization, }; } From 98fdee47a3364a6b3696a480f32558f46e433366 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Thu, 9 Jan 2025 16:12:53 -0800 Subject: [PATCH 11/18] Fix wrongly existing cuepoint --- app/services/platforms/youtube.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index f6a1316318ec..2ffc0586efbc 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -616,18 +616,16 @@ export class YoutubeService if (broadcast.monetizationDetails) { fields.push('monetizationDetails'); - const moneyInfo = broadcast.monetizationDetails.cuepointSchedule; + const moneyInfo = broadcast.monetizationDetails; monetizationDetails = { - adsMonetizationStatus: this.getMonetizationStatus( - isMidStreamMode ? moneyInfo?.enabled : params.monetizationEnabled, - ), - cuepointSchedule: { - enabled: isMidStreamMode ? moneyInfo?.enabled : params.monetizationEnabled, - pauseAdsUntil: moneyInfo?.pauseAdsUntil, - scheduleStrategy: moneyInfo?.scheduleStrategy, - repeatIntervalSecs: moneyInfo?.repeatIntervalSecs, - }, + adsMonetizationStatus: isMidStreamMode ? moneyInfo?.adsMonetizationStatus : this.getMonetizationStatus(params.monetizationEnabled),, }; + if (!isMidStreamMode && params.monetizationEnabled) { + monetizationDetails.cuepointSchedule = { + ...moneyInfo.cuepointSchedule, + enabled: params.monetizationEnabled, + } + } } const endpoint = `liveBroadcasts?part=${fields.join(',')}&id=${id}`; From d09b286918ccff2e3c82b6ce5eb69a5982d93526 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Thu, 9 Jan 2025 16:24:15 -0800 Subject: [PATCH 12/18] Fix compilation error --- app/services/platforms/youtube.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index 2ffc0586efbc..be1baff35ad9 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -618,13 +618,15 @@ export class YoutubeService const moneyInfo = broadcast.monetizationDetails; monetizationDetails = { - adsMonetizationStatus: isMidStreamMode ? moneyInfo?.adsMonetizationStatus : this.getMonetizationStatus(params.monetizationEnabled),, + adsMonetizationStatus: isMidStreamMode + ? moneyInfo?.adsMonetizationStatus + : this.getMonetizationStatus(params.monetizationEnabled), }; if (!isMidStreamMode && params.monetizationEnabled) { monetizationDetails.cuepointSchedule = { ...moneyInfo.cuepointSchedule, enabled: params.monetizationEnabled, - } + }; } } From 8a93cc0c924177fbabadb78cfabcb207bef98eb8 Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Thu, 9 Jan 2025 16:46:28 -0800 Subject: [PATCH 13/18] Fix config error --- app/services/platforms/youtube.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index be1baff35ad9..4bdba1013953 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -101,8 +101,8 @@ export interface IYoutubeLiveBroadcast { cuepointSchedule: { enabled?: boolean; pauseAdsUntil?: string; - scheduleStrategy?: string; - repeatIntervalSecs?: number; + creatorCuepointConfig?: any; + ytOptimizedCuepointConfig?: 'CONSERVATIVE' | 'BALANCED' | 'AGGRESSIVE'; }; adsMonetizationStatus?: 'on' | 'off'; eligibleForAdsMonetization?: boolean; @@ -545,6 +545,7 @@ export class YoutubeService adsMonetizationStatus: this.getMonetizationStatus(params.monetizationEnabled), cuepointSchedule: { enabled: params.monetizationEnabled, + ytOptimizedCuepointConfig: 'BALANCED', }, }; } @@ -626,6 +627,8 @@ export class YoutubeService monetizationDetails.cuepointSchedule = { ...moneyInfo.cuepointSchedule, enabled: params.monetizationEnabled, + ytOptimizedCuepointConfig: 'BALANCED', + creatorCuepointConfig: undefined, }; } } From 86b6e0ecb6daca6a90a300b3a34ef09825996a3e Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Mon, 13 Jan 2025 12:58:03 -0800 Subject: [PATCH 14/18] Fix unexpected part error --- app/services/platforms/youtube.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index 4bdba1013953..8b94bc9ab43f 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -516,7 +516,6 @@ export class YoutubeService params: IYoutubeStartStreamOptions & { scheduledStartTime?: number }, ): Promise { const fields = ['snippet', 'contentDetails', 'status']; - const endpoint = `liveBroadcasts?part=${fields.join(',')}`; const scheduledStartTime = params.scheduledStartTime ? new Date(params.scheduledStartTime) : new Date(); @@ -550,6 +549,7 @@ export class YoutubeService }; } + const endpoint = `liveBroadcasts?part=${fields.join(',')}`; const broadcast = await this.requestYoutube({ body: JSON.stringify(data), method: 'POST', From 34932e5659ef5106f048b8d4d4fc1f3f4b7a945d Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Tue, 14 Jan 2025 12:18:14 -0800 Subject: [PATCH 15/18] Fix monetization not POSTable --- .../platforms/YoutubeEditStreamInfo.tsx | 2 +- app/services/platforms/youtube.ts | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx b/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx index 37afe5cdb27c..dcc13eae065a 100644 --- a/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx +++ b/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx @@ -207,7 +207,7 @@ export const YoutubeEditStreamInfo = InputComponent((p: IPlatformComponentParams )}

)} - {ytSettings.eligibleForMonetization && ( + {!isScheduleMode && ytSettings.eligibleForMonetization && ( )} diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index 8b94bc9ab43f..83163de403ed 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -306,6 +306,11 @@ export class YoutubeService let broadcast: IYoutubeLiveBroadcast; if (!streamToScheduledBroadcast) { broadcast = await this.createBroadcast(ytSettings); + + // Current YT api doesn't let us POST with monetization settings so need to patch it in after creation + if (ytSettings.monetizationEnabled) { + await this.updateBroadcast(broadcast.id, ytSettings); + } } else { assertIsDefined(ytSettings.broadcastId); await this.updateBroadcast(ytSettings.broadcastId, ytSettings); @@ -516,6 +521,7 @@ export class YoutubeService params: IYoutubeStartStreamOptions & { scheduledStartTime?: number }, ): Promise { const fields = ['snippet', 'contentDetails', 'status']; + const endpoint = `liveBroadcasts?part=${fields.join(',')}`; const scheduledStartTime = params.scheduledStartTime ? new Date(params.scheduledStartTime) : new Date(); @@ -538,18 +544,6 @@ export class YoutubeService }, }; - if (params.monetizationEnabled) { - fields.push('monetizationDetails'); - data.monetizationDetails = { - adsMonetizationStatus: this.getMonetizationStatus(params.monetizationEnabled), - cuepointSchedule: { - enabled: params.monetizationEnabled, - ytOptimizedCuepointConfig: 'BALANCED', - }, - }; - } - - const endpoint = `liveBroadcasts?part=${fields.join(',')}`; const broadcast = await this.requestYoutube({ body: JSON.stringify(data), method: 'POST', From 901642723d0ff14f1af0f3ec9201c3022802a6dc Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Tue, 14 Jan 2025 12:52:36 -0800 Subject: [PATCH 16/18] Clear monetization if switching to new broadcast event --- .../windows/go-live/platforms/YoutubeEditStreamInfo.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx b/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx index dcc13eae065a..a0ede3a21705 100644 --- a/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx +++ b/app/components-react/windows/go-live/platforms/YoutubeEditStreamInfo.tsx @@ -63,7 +63,11 @@ export const YoutubeEditStreamInfo = InputComponent((p: IPlatformComponentParams // re-fill form when the broadcastId selected useEffect(() => { - if (!broadcastId) return; + if (!broadcastId) { + // Cannot have monetization enabled before the broadcast is checked + updateSettings({ monetizationEnabled: false, eligibleForMonetization: false }); + return; + } Services.YoutubeService.actions.return .fetchStartStreamOptionsForBroadcast(broadcastId) .then(newYtSettings => { From 0e9c499dc44bc0f695b2a04eea0c9cfa6b83b7bb Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Fri, 24 Jan 2025 16:15:05 -0800 Subject: [PATCH 17/18] Add analytics to yt monetization --- app/services/platforms/youtube.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index 83163de403ed..2d173c235ae6 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -24,6 +24,7 @@ import * as remote from '@electron/remote'; import { IVideo } from 'obs-studio-node'; import pick from 'lodash/pick'; import { TOutputOrientation } from 'services/restream'; +import { UsageStatisticsService } from 'services/usage-statistics'; interface IYoutubeServiceState extends IPlatformState { liveStreamingEnabled: boolean; @@ -190,6 +191,7 @@ export class YoutubeService @Inject() private customizationService: CustomizationService; @Inject() private windowsService: WindowsService; @Inject() private i18nService: I18nService; + @Inject() private usageStatisticsService: UsageStatisticsService; @lazyModule(YoutubeUploader) uploader: YoutubeUploader; @@ -610,6 +612,7 @@ export class YoutubeService let monetizationDetails: Partial; if (broadcast.monetizationDetails) { fields.push('monetizationDetails'); + this.usageStatisticsService.actions.recordFeatureUsage('YouTubeMonetization'); const moneyInfo = broadcast.monetizationDetails; monetizationDetails = { From 50753b45a27ab98bf2db43508f003bdfc58a3a4f Mon Sep 17 00:00:00 2001 From: Sean Beyer Date: Thu, 24 Jul 2025 12:51:45 -0700 Subject: [PATCH 18/18] Update api wording --- app/services/platforms/youtube.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/platforms/youtube.ts b/app/services/platforms/youtube.ts index 3a1e2f783940..b5b303234ee2 100644 --- a/app/services/platforms/youtube.ts +++ b/app/services/platforms/youtube.ts @@ -106,7 +106,7 @@ export interface IYoutubeLiveBroadcast { enabled?: boolean; pauseAdsUntil?: string; creatorCuepointConfig?: any; - ytOptimizedCuepointConfig?: 'CONSERVATIVE' | 'BALANCED' | 'AGGRESSIVE'; + ytOptimizedCuepointConfig?: 'LOW' | 'MEDIUM' | 'HIGH'; }; adsMonetizationStatus?: 'on' | 'off'; eligibleForAdsMonetization?: boolean; @@ -731,7 +731,7 @@ export class YoutubeService monetizationDetails.cuepointSchedule = { ...moneyInfo.cuepointSchedule, enabled: params.monetizationEnabled, - ytOptimizedCuepointConfig: 'BALANCED', + ytOptimizedCuepointConfig: 'MEDIUM', creatorCuepointConfig: undefined, }; }