Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Highlighter] - Additional tracking #5310

Merged
merged 11 commits into from
Mar 1, 2025
16 changes: 13 additions & 3 deletions app/components-react/highlighter/ExportModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function ExportModal({ close, streamId }: { close: () => void; streamId: string
/>
);
}
return <PlatformSelect onClose={close} videoName={videoName} />;
return <PlatformSelect onClose={close} videoName={videoName} streamId={streamId} />;
}

function ExportProgress() {
Expand Down Expand Up @@ -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(() => ({
Expand Down Expand Up @@ -332,7 +340,9 @@ function PlatformSelect({ onClose, videoName }: { onClose: () => void; videoName
nowrap
options={platformOptions}
/>
{platform === 'youtube' && <YoutubeUpload defaultTitle={videoName} close={onClose} />}
{platform === 'youtube' && (
<YoutubeUpload defaultTitle={videoName} close={onClose} streamId={streamId} />
)}
{platform !== 'youtube' && <StorageUpload onClose={onClose} platform={platform} />}
</Form>
);
Expand Down
6 changes: 5 additions & 1 deletion app/components-react/highlighter/PreviewModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default function PreviewModal({
streamId: string | undefined;
emitSetShowModal: (modal: TModalClipsView | null) => void;
}) {
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;
Expand All @@ -41,6 +41,10 @@ export default function PreviewModal({
const currentClipIndexRef = useRef(initialIndex);
const [showDisabled, setShowDisabled] = useState(true);

useEffect(() => {
UsageStatisticsService.recordShown('ClipsPreview', streamId);
}, []);

function getInitialIndex(introDuration: number | null, sortedClips: TClip[]): number {
if (introDuration) return 0;
const firstEnabledIndex = sortedClips.findIndex(clip => clip.enabled);
Expand Down
2 changes: 1 addition & 1 deletion app/components-react/highlighter/SettingsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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')}
Expand Down
20 changes: 14 additions & 6 deletions app/components-react/highlighter/YoutubeUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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')}
Expand Down
7 changes: 6 additions & 1 deletion app/components-react/pages/Highlighter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
);
Expand Down Expand Up @@ -50,6 +50,11 @@ export default function Highlighter(props: { params?: { view: string } }) {
}, []);

const [viewState, setViewState] = useState<IViewState>(initialViewState);

useEffect(() => {
UsageStatisticsService.recordShown('HighlighterTab', viewState.view);
}, [viewState]);

const updaterModal = (
<UpdateModal
version={v.highlighterVersion}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export default function AiHighlighterToggle({
size="small"
type="primary"
onClick={() => {
HighlighterService.installAiHighlighter();
HighlighterService.installAiHighlighter(false, 'Go-live-flow');
}}
>
Install AI Highlighter
Expand Down
4 changes: 2 additions & 2 deletions app/services/highlighter/ai-highlighter-updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export class AiHighlighterUpdater {
*/
public async isNewVersionAvailable(): Promise<boolean> {
// check if updater checked version in current session already
if (this.versionChecked) {
if (this.versionChecked || Utils.getHighlighterEnvironment() === 'local') {
return false;
}

Expand Down Expand Up @@ -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'));
Expand Down
31 changes: 29 additions & 2 deletions app/services/highlighter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,7 @@ export class HighlighterService extends PersistentStatefulService<IHighlighterSt
transitionDuration: this.views.transitionDuration,
transition: this.views.transition,
useAiHighlighter: this.views.useAiHighlighter,
streamId,
},
handleFrame,
setExportInfo,
Expand Down Expand Up @@ -1110,7 +1111,15 @@ export class HighlighterService extends PersistentStatefulService<IHighlighterSt
}
}

async installAiHighlighter(downloadNow: boolean = false) {
async installAiHighlighter(
downloadNow: boolean = false,
location: 'Highlighter-tab' | 'Go-live-flow',
) {
this.usageStatisticsService.recordAnalyticsEvent('AIHighlighter', {
type: 'Installation',
location,
});

this.setAiHighlighter(true);
if (downloadNow) {
await this.aiHighlighterUpdater.isNewVersionAvailable();
Expand All @@ -1136,6 +1145,12 @@ export class HighlighterService extends PersistentStatefulService<IHighlighterSt
this.SET_UPDATER_STATE(true);
this.SET_HIGHLIGHTER_VERSION(this.aiHighlighterUpdater.version || '');
await this.aiHighlighterUpdater.update(progress => this.updateProgress(progress));
} catch (e: unknown) {
console.error('Error updating AI Highlighter:', e);
this.usageStatisticsService.recordAnalyticsEvent('Highlighter', {
type: 'UpdateError',
newVersion: this.aiHighlighterUpdater.version,
});
} finally {
this.SET_UPDATER_STATE(false);
}
Expand Down Expand Up @@ -1248,14 +1263,25 @@ export class HighlighterService extends PersistentStatefulService<IHighlighterSt
type: 'Detection',
clips: highlighterResponse.length,
game: 'Fortnite', // hardcode for now
streamId: this.streamMilestones?.streamId,
});
console.log('✅ Final HighlighterData', highlighterResponse);
} catch (error: unknown) {
if (error instanceof Error && error.message === 'Highlight generation canceled') {
setStreamInfo.state.type = EAiDetectionState.CANCELED_BY_USER;
this.usageStatisticsService.recordAnalyticsEvent('AIHighlighter', {
type: 'DetectionCanceled',
reason: EAiDetectionState.CANCELED_BY_USER,
game: 'Fortnite',
});
} else {
console.error('Error in highlight generation:', error);
setStreamInfo.state.type = EAiDetectionState.ERROR;
this.usageStatisticsService.recordAnalyticsEvent('AIHighlighter', {
type: 'DetectionFailed',
reason: EAiDetectionState.ERROR,
game: 'Fortnite',
});
}
} finally {
setStreamInfo.abortController = undefined;
Expand Down Expand Up @@ -1343,7 +1369,7 @@ export class HighlighterService extends PersistentStatefulService<IHighlighterSt
this.CLEAR_UPLOAD();
}

async uploadYoutube(options: IYoutubeVideoUploadOptions) {
async uploadYoutube(options: IYoutubeVideoUploadOptions, streamId: string | undefined) {
if (!this.userService.state.auth?.platforms.youtube) {
throw new Error('Cannot upload without YT linked');
}
Expand Down Expand Up @@ -1407,6 +1433,7 @@ export class HighlighterService extends PersistentStatefulService<IHighlighterSt
this.views.useAiHighlighter ? 'AIHighlighter' : 'Highlighter',
{
type: 'UploadYouTubeSuccess',
streamId,
privacy: options.privacyStatus,
videoLink:
options.privacyStatus === 'public'
Expand Down
3 changes: 3 additions & 0 deletions app/services/highlighter/rendering/start-rendering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface IRenderingConfig {
transitionDuration: number;
transition: ITransitionInfo;
useAiHighlighter: boolean;
streamId: string | undefined;
}
export async function startRendering(
renderingConfig: IRenderingConfig,
Expand All @@ -43,6 +44,7 @@ export async function startRendering(
const transitionDuration = renderingConfig.transitionDuration;
const transition = renderingConfig.transition;
const useAiHighlighter = renderingConfig.useAiHighlighter;
const streamId = renderingConfig.streamId;

let fader: AudioCrossfader | null = null;
let mixer: AudioMixer | null = null;
Expand Down Expand Up @@ -200,6 +202,7 @@ export async function startRendering(
preset: exportInfo.preset,
duration: totalFramesAfterTransitions / exportOptions.fps,
isPreview,
streamId,
});
break;
}
Expand Down
Loading