From 59c9bb7ec6ecc2675dad22f22a23124e58733218 Mon Sep 17 00:00:00 2001 From: marvinoffers Date: Wed, 19 Feb 2025 15:42:46 +0100 Subject: [PATCH 1/8] additional tracking --- .../highlighter/ExportModal.tsx | 14 +++++++++++-- .../highlighter/PreviewModal.tsx | 9 ++++++++- .../highlighter/SettingsView.tsx | 2 +- .../highlighter/YoutubeUpload.tsx | 20 +++++++++++++------ app/components-react/pages/Highlighter.tsx | 10 +++++++++- .../windows/go-live/AiHighlighterToggle.tsx | 2 +- app/services/highlighter/index.ts | 15 ++++++++++++-- .../highlighter/rendering/start-rendering.ts | 3 +++ 8 files changed, 61 insertions(+), 14 deletions(-) diff --git a/app/components-react/highlighter/ExportModal.tsx b/app/components-react/highlighter/ExportModal.tsx index e443442b697a..fe840f3caa9a 100644 --- a/app/components-react/highlighter/ExportModal.tsx +++ b/app/components-react/highlighter/ExportModal.tsx @@ -301,7 +301,15 @@ function ExportOptions({ ); } -function PlatformSelect({ onClose, videoName }: { onClose: () => void; videoName: string }) { +function PlatformSelect({ + onClose, + videoName, + streamId, +}: { + onClose: () => void; + videoName: string; + streamId: string | undefined; +}) { const { store, clearUpload, getStreamTitle } = useController(ExportModalCtx); const { UserService } = Services; const { isYoutubeLinked } = useVuex(() => ({ @@ -332,7 +340,9 @@ function PlatformSelect({ onClose, videoName }: { onClose: () => void; videoName nowrap options={platformOptions} /> - {platform === 'youtube' && } + {platform === 'youtube' && ( + + )} {platform !== 'youtube' && } ); diff --git a/app/components-react/highlighter/PreviewModal.tsx b/app/components-react/highlighter/PreviewModal.tsx index f4f0acdbef8d..55ab2673fb2c 100644 --- a/app/components-react/highlighter/PreviewModal.tsx +++ b/app/components-react/highlighter/PreviewModal.tsx @@ -13,7 +13,7 @@ export default function PreviewModal({ close: () => void; streamId: string | undefined; }) { - const { HighlighterService } = Services; + const { HighlighterService, UsageStatisticsService } = Services; const clips = HighlighterService.getClips(HighlighterService.views.clips, streamId); const { intro, outro } = HighlighterService.views.video; const audioSettings = HighlighterService.views.audio; @@ -21,6 +21,13 @@ export default function PreviewModal({ const currentClipIndexRef = useRef(0); const sortedClips = [...sortClipsByOrder(clips, streamId).filter(c => c.enabled)]; + useEffect(() => { + UsageStatisticsService.recordAnalyticsEvent('AIHighlighter', { + type: 'PreviewViewed', + streamId, + }); + }, []); + const playlist = [ ...(intro.duration ? [ diff --git a/app/components-react/highlighter/SettingsView.tsx b/app/components-react/highlighter/SettingsView.tsx index ff7e0acd6f90..a8b1f1117048 100644 --- a/app/components-react/highlighter/SettingsView.tsx +++ b/app/components-react/highlighter/SettingsView.tsx @@ -175,7 +175,7 @@ export default function SettingsView({ style={{ width: 'fit-content' }} type="primary" onClick={() => { - HighlighterService.actions.installAiHighlighter(true); + HighlighterService.actions.installAiHighlighter(true, 'Highlighter-tab'); }} > {$t('Install AI Highlighter App')} diff --git a/app/components-react/highlighter/YoutubeUpload.tsx b/app/components-react/highlighter/YoutubeUpload.tsx index 727979b4b9f0..97da59cc847e 100644 --- a/app/components-react/highlighter/YoutubeUpload.tsx +++ b/app/components-react/highlighter/YoutubeUpload.tsx @@ -12,8 +12,13 @@ import * as remote from '@electron/remote'; import VideoPreview from './VideoPreview'; import UploadProgress from './UploadProgress'; -export default function YoutubeUpload(props: { defaultTitle: string; close: () => void }) { +export default function YoutubeUpload(props: { + defaultTitle: string; + close: () => void; + streamId: string | undefined; +}) { const [title, setTitle] = useState(props.defaultTitle); + const streamId = props.streamId; const [description, setDescription] = useState(''); const [privacy, setPrivacy] = useState('private'); const [urlCopied, setUrlCopied] = useState(false); @@ -107,11 +112,14 @@ export default function YoutubeUpload(props: { defaultTitle: string; close: () = type="primary" onClick={() => { UsageStatisticsService.actions.recordFeatureUsage('HighlighterUpload'); - HighlighterService.actions.uploadYoutube({ - title, - description, - privacyStatus: privacy as TPrivacyStatus, - }); + HighlighterService.actions.uploadYoutube( + { + title, + description, + privacyStatus: privacy as TPrivacyStatus, + }, + streamId, + ); }} > {$t('Publish')} diff --git a/app/components-react/pages/Highlighter.tsx b/app/components-react/pages/Highlighter.tsx index bf698b2ffead..b4a70676f033 100644 --- a/app/components-react/pages/Highlighter.tsx +++ b/app/components-react/pages/Highlighter.tsx @@ -9,7 +9,7 @@ import UpdateModal from 'components-react/highlighter/UpdateModal'; import { EAvailableFeatures } from 'services/incremental-rollout'; export default function Highlighter(props: { params?: { view: string } }) { - const { HighlighterService, IncrementalRolloutService } = Services; + const { HighlighterService, IncrementalRolloutService, UsageStatisticsService } = Services; const aiHighlighterFeatureEnabled = IncrementalRolloutService.views.featureIsEnabled( EAvailableFeatures.aiHighlighter, ); @@ -50,6 +50,14 @@ export default function Highlighter(props: { params?: { view: string } }) { }, []); const [viewState, setViewState] = useState(initialViewState); + + useEffect(() => { + UsageStatisticsService.recordAnalyticsEvent('Highlighter', { + type: 'HighlighterTabViewed', + view: viewState, + }); + }, [viewState]); + const updaterModal = ( { - HighlighterService.installAiHighlighter(); + HighlighterService.installAiHighlighter(false, 'Go-live-flow'); }} > Install AI Highlighter diff --git a/app/services/highlighter/index.ts b/app/services/highlighter/index.ts index d090b939520c..70b1febc4e02 100644 --- a/app/services/highlighter/index.ts +++ b/app/services/highlighter/index.ts @@ -991,6 +991,7 @@ export class HighlighterService extends PersistentStatefulService Date: Wed, 19 Feb 2025 18:34:45 +0100 Subject: [PATCH 2/8] forgot property --- app/components-react/highlighter/ExportModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components-react/highlighter/ExportModal.tsx b/app/components-react/highlighter/ExportModal.tsx index fe840f3caa9a..56e2dee37a7e 100644 --- a/app/components-react/highlighter/ExportModal.tsx +++ b/app/components-react/highlighter/ExportModal.tsx @@ -119,7 +119,7 @@ function ExportModal({ close, streamId }: { close: () => void; streamId: string /> ); } - return ; + return ; } function ExportProgress() { From aa35f17edbf5d26ef3c1779247611db2594d75de Mon Sep 17 00:00:00 2001 From: marvinoffers Date: Thu, 20 Feb 2025 09:37:48 +0100 Subject: [PATCH 3/8] switched tracking to record shown --- app/components-react/highlighter/PreviewModal.tsx | 5 +---- app/components-react/pages/Highlighter.tsx | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/app/components-react/highlighter/PreviewModal.tsx b/app/components-react/highlighter/PreviewModal.tsx index 55ab2673fb2c..e43cffa7b32d 100644 --- a/app/components-react/highlighter/PreviewModal.tsx +++ b/app/components-react/highlighter/PreviewModal.tsx @@ -22,10 +22,7 @@ export default function PreviewModal({ const sortedClips = [...sortClipsByOrder(clips, streamId).filter(c => c.enabled)]; useEffect(() => { - UsageStatisticsService.recordAnalyticsEvent('AIHighlighter', { - type: 'PreviewViewed', - streamId, - }); + UsageStatisticsService.recordShown('ClipsPreview', streamId); }, []); const playlist = [ diff --git a/app/components-react/pages/Highlighter.tsx b/app/components-react/pages/Highlighter.tsx index b4a70676f033..5f00ccd6c94d 100644 --- a/app/components-react/pages/Highlighter.tsx +++ b/app/components-react/pages/Highlighter.tsx @@ -52,10 +52,7 @@ export default function Highlighter(props: { params?: { view: string } }) { const [viewState, setViewState] = useState(initialViewState); useEffect(() => { - UsageStatisticsService.recordAnalyticsEvent('Highlighter', { - type: 'HighlighterTabViewed', - view: viewState, - }); + UsageStatisticsService.recordShown('HighlighterTab', viewState.view); }, [viewState]); const updaterModal = ( From 661ef418787e212be267d5112a651e6714aa5cc4 Mon Sep 17 00:00:00 2001 From: marvinoffers Date: Wed, 26 Feb 2025 17:03:57 +0100 Subject: [PATCH 4/8] removed unused logs --- app/components-react/highlighter/utils.ts | 40 ----------------------- 1 file changed, 40 deletions(-) diff --git a/app/components-react/highlighter/utils.ts b/app/components-react/highlighter/utils.ts index 7be46c8b05b3..5643f75f410a 100644 --- a/app/components-react/highlighter/utils.ts +++ b/app/components-react/highlighter/utils.ts @@ -103,48 +103,27 @@ export function aiFilterClips( ] : rounds; - // console.log('selectedRounds', selectedRounds); - // Sort rounds by score (descending) const sortedRounds = selectedRounds.sort( (a, b) => getRoundScore(b, clips) - getRoundScore(a, clips), ); - // console.log('sortedRounds by rooundScore', sortedRounds); - let clipsFromRounds: TClip[] = []; let totalDuration = 0; for (let i = 0; i < sortedRounds.length; ++i) { if (totalDuration > targetDuration) { - // console.log(`Duration: ${totalDuration} more than target: ${targetDuration}`); break; } else { - // console.log(`Duration: ${totalDuration} less than target: ${targetDuration}`); //Todo M: how do sort? Per round or all together and then the rounds are in the stream order again? const roundIndex = sortedRounds[i]; - // console.log('include round ', roundIndex); const roundClips = sortClipsByOrder(getClipsOfRound(roundIndex, clips), streamId); - // console.log( - // 'roundClips before adding:', - // roundClips.map(c => ({ - // duration: c.duration, - // })), - // ); clipsFromRounds = [...clipsFromRounds, ...roundClips]; - // console.log( - // 'clipsFromRounds after adding:', - // clipsFromRounds.map(c => ({ - // duration: c.duration, - // })), - // ); totalDuration = getCombinedClipsDuration(clipsFromRounds); - // console.log('new totalDuration:', totalDuration); } - // console.log('clipsFromRounds', clipsFromRounds); } const contextTypes = [ EHighlighterInputTypes.DEPLOY, @@ -156,25 +135,12 @@ export function aiFilterClips( clips => !(clips as IAiClip).aiInfo.inputs.some(input => contextTypes.includes(input.type)), ) .sort((a, b) => (a as IAiClip).aiInfo.score - (b as IAiClip).aiInfo.score); - // console.log( - // 'clipsSortedByScore', - // clipsSortedByScore.map(clip => { - // return { - // score: (clip as IAiClip).aiInfo.score, - // inputs: JSON.stringify((clip as IAiClip).aiInfo.inputs), - // }; - // }), - // ); - // console.log('clipsFromRounds', clipsFromRounds); const filteredClips: TClip[] = clipsFromRounds; let currentDuration = getCombinedClipsDuration(filteredClips); - // console.log('remove clipswise to get closer to target'); - const BUFFER_SEC = 0; while (currentDuration > targetDuration + BUFFER_SEC) { - // console.log('ruuun currentDuration', currentDuration); if (clipsSortedByScore === undefined || clipsSortedByScore.length === 0) { break; } @@ -187,12 +153,6 @@ export function aiFilterClips( if (index > -1) { filteredClips.splice(index, 1); // 2nd parameter means remove one item only currentDuration = getCombinedClipsDuration(filteredClips); - // console.log( - // 'removed, new currentDuration:', - // currentDuration, - // 'target:', - // targetDuration + BUFFER_SEC, - // ); } } From 7bb83ea50c97ab993455f32d9904f9a16f7555a1 Mon Sep 17 00:00:00 2001 From: marvinoffers Date: Wed, 26 Feb 2025 17:06:48 +0100 Subject: [PATCH 5/8] Revert "removed unused logs" This reverts commit 661ef418787e212be267d5112a651e6714aa5cc4. --- app/components-react/highlighter/utils.ts | 40 +++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/app/components-react/highlighter/utils.ts b/app/components-react/highlighter/utils.ts index 5643f75f410a..7be46c8b05b3 100644 --- a/app/components-react/highlighter/utils.ts +++ b/app/components-react/highlighter/utils.ts @@ -103,27 +103,48 @@ export function aiFilterClips( ] : rounds; + // console.log('selectedRounds', selectedRounds); + // Sort rounds by score (descending) const sortedRounds = selectedRounds.sort( (a, b) => getRoundScore(b, clips) - getRoundScore(a, clips), ); + // console.log('sortedRounds by rooundScore', sortedRounds); + let clipsFromRounds: TClip[] = []; let totalDuration = 0; for (let i = 0; i < sortedRounds.length; ++i) { if (totalDuration > targetDuration) { + // console.log(`Duration: ${totalDuration} more than target: ${targetDuration}`); break; } else { + // console.log(`Duration: ${totalDuration} less than target: ${targetDuration}`); //Todo M: how do sort? Per round or all together and then the rounds are in the stream order again? const roundIndex = sortedRounds[i]; + // console.log('include round ', roundIndex); const roundClips = sortClipsByOrder(getClipsOfRound(roundIndex, clips), streamId); + // console.log( + // 'roundClips before adding:', + // roundClips.map(c => ({ + // duration: c.duration, + // })), + // ); clipsFromRounds = [...clipsFromRounds, ...roundClips]; + // console.log( + // 'clipsFromRounds after adding:', + // clipsFromRounds.map(c => ({ + // duration: c.duration, + // })), + // ); totalDuration = getCombinedClipsDuration(clipsFromRounds); + // console.log('new totalDuration:', totalDuration); } + // console.log('clipsFromRounds', clipsFromRounds); } const contextTypes = [ EHighlighterInputTypes.DEPLOY, @@ -135,12 +156,25 @@ export function aiFilterClips( clips => !(clips as IAiClip).aiInfo.inputs.some(input => contextTypes.includes(input.type)), ) .sort((a, b) => (a as IAiClip).aiInfo.score - (b as IAiClip).aiInfo.score); + // console.log( + // 'clipsSortedByScore', + // clipsSortedByScore.map(clip => { + // return { + // score: (clip as IAiClip).aiInfo.score, + // inputs: JSON.stringify((clip as IAiClip).aiInfo.inputs), + // }; + // }), + // ); + // console.log('clipsFromRounds', clipsFromRounds); const filteredClips: TClip[] = clipsFromRounds; let currentDuration = getCombinedClipsDuration(filteredClips); + // console.log('remove clipswise to get closer to target'); + const BUFFER_SEC = 0; while (currentDuration > targetDuration + BUFFER_SEC) { + // console.log('ruuun currentDuration', currentDuration); if (clipsSortedByScore === undefined || clipsSortedByScore.length === 0) { break; } @@ -153,6 +187,12 @@ export function aiFilterClips( if (index > -1) { filteredClips.splice(index, 1); // 2nd parameter means remove one item only currentDuration = getCombinedClipsDuration(filteredClips); + // console.log( + // 'removed, new currentDuration:', + // currentDuration, + // 'target:', + // targetDuration + BUFFER_SEC, + // ); } } From 105480d4ad99ef0da730eec9e87923db01c9526e Mon Sep 17 00:00:00 2001 From: marvinoffers Date: Thu, 27 Feb 2025 18:16:22 +0100 Subject: [PATCH 6/8] added error tracking --- app/services/highlighter/index.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/services/highlighter/index.ts b/app/services/highlighter/index.ts index d090b939520c..33eaa4bfd06f 100644 --- a/app/services/highlighter/index.ts +++ b/app/services/highlighter/index.ts @@ -1253,9 +1253,19 @@ export class HighlighterService extends PersistentStatefulService Date: Fri, 28 Feb 2025 12:22:30 +0100 Subject: [PATCH 7/8] track update error --- app/services/highlighter/ai-highlighter-updater.ts | 4 ++-- app/services/highlighter/index.ts | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/services/highlighter/ai-highlighter-updater.ts b/app/services/highlighter/ai-highlighter-updater.ts index 0972b9cc3395..d1ecfd135861 100644 --- a/app/services/highlighter/ai-highlighter-updater.ts +++ b/app/services/highlighter/ai-highlighter-updater.ts @@ -129,7 +129,7 @@ export class AiHighlighterUpdater { */ public async isNewVersionAvailable(): Promise { // check if updater checked version in current session already - if (this.versionChecked) { + if (this.versionChecked || Utils.getHighlighterEnvironment() === 'local') { return false; } @@ -235,7 +235,7 @@ export class AiHighlighterUpdater { const binPath = path.resolve(AiHighlighterUpdater.basepath, 'bin'); const outdateVersionPresent = existsSync(binPath); - // backup the ouotdated version in case something goes bad + // backup the outdated version in case something goes bad if (outdateVersionPresent) { console.log('backing up outdated version...'); await fs.rename(binPath, path.resolve(AiHighlighterUpdater.basepath, 'bin.bkp')); diff --git a/app/services/highlighter/index.ts b/app/services/highlighter/index.ts index 6ed78931de22..ad43b03690bb 100644 --- a/app/services/highlighter/index.ts +++ b/app/services/highlighter/index.ts @@ -1145,6 +1145,12 @@ export class HighlighterService extends PersistentStatefulService this.updateProgress(progress)); + } catch (e: unknown) { + console.error('Error updating AI Highlighter:', e); + this.usageStatisticsService.recordAnalyticsEvent('Highlighter', { + type: 'UpdateError', + new_version: this.aiHighlighterUpdater.version, + }); } finally { this.SET_UPDATER_STATE(false); } From b7faa4453bc51dfd691be118c2886bb6be64c353 Mon Sep 17 00:00:00 2001 From: jankalthoefer Date: Fri, 28 Feb 2025 13:19:35 +0100 Subject: [PATCH 8/8] fix tracking property casing --- app/services/highlighter/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/highlighter/index.ts b/app/services/highlighter/index.ts index ad43b03690bb..414d58cd1198 100644 --- a/app/services/highlighter/index.ts +++ b/app/services/highlighter/index.ts @@ -1149,7 +1149,7 @@ export class HighlighterService extends PersistentStatefulService