voice clone request page (wip)

This commit is contained in:
Brandon Thomas committed 2022-03-04 01:37:48 -05:00
1 parent a314fab0bc
commit b9eb7eccd8
4 files changed
+420

No files matched your search

@@ -0,0 +1,86 @@
import { ApiConfig } from "@storyteller/components";
export interface CreateVoiceCloneApplicationRequest {
idempotency_token: string,
// Contact
email_address: string,
discord_username: string,
// TODO: Make enum.
// Visibility
is_for_private_use: boolean,
is_for_public_use: boolean,
// Use
is_for_studio: boolean,
is_for_twitch_tts: boolean,
is_for_api_use: boolean,
is_for_music: boolean,
is_for_games: boolean,
is_for_other: boolean,
optional_notes_on_use?: string,
// Subject/Ownership
is_own_voice: boolean,
is_third_party_voice: boolean,
optional_notes_on_subject?: string,
// Equipment
has_clean_audio_recordings: boolean,
has_good_microphone: boolean,
// Comments
optional_questions?: string,
optional_extra_comments?: string,
}
export interface CreateVoiceCloneApplicationSuccessResponse {
success: boolean,
}
export interface CreateVoiceCloneApplicationErrorResponse {
success: boolean,
}
type CreateVoiceCloneApplicationResponse = CreateVoiceCloneApplicationSuccessResponse | CreateVoiceCloneApplicationErrorResponse;
export function CreateVoiceCloneApplicationIsSuccess(response: CreateVoiceCloneApplicationResponse): response is CreateVoiceCloneApplicationSuccessResponse {
return response?.success === true;
}
export function CreateVoiceCloneApplicationIsError(response: CreateVoiceCloneApplicationResponse): response is CreateVoiceCloneApplicationErrorResponse {
return response?.success === false;
}
export async function CreateVoiceCloneApplication(request: CreateVoiceCloneApplicationRequest) : Promise<CreateVoiceCloneApplicationResponse>
{
const endpoint = new ApiConfig().createVoiceCloneRequest();
return await fetch(endpoint, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify(request),
})
.then(res => res.json())
.then(res => {
if (!res) {
return { success : false };
}
if (res && 'success' in res) {
return res;
} else {
return { success : false };
}
})
.catch(e => {
return { success : false };
});
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

@@ -0,0 +1,8 @@
.checkbox-block {
margin: 5px 0px 0px 0px;
}
.checkbox-block label {
margin: 0 0 10px;
}
@@ -0,0 +1,326 @@
import './VoiceCloneRequestPage.css';
import { faEnvelope } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useCallback, useEffect, useState } from 'react';
interface Props {
}
function VoiceCloneRequestPage(props: Props) {
//const [leaderboard, setLeaderboard] = useState<Leaderboard|undefined>(undefined);
//const [ttsLeaderboard, setTtsLeaderboard] = useState<Array<LeaderboardEntryForList>|undefined>(undefined);
//const [w2lLeaderboard, setW2lLeaderboard] = useState<Array<LeaderboardEntryForList>|undefined>(undefined);
//const [retryCount, setRetryCount] = useState(0);
//const getLeaderboard = useCallback(async () => {
// const leaderboardReponse = await GetLeaderboard();
// if (GetLeaderboardIsOk(leaderboardReponse)) {
// setLeaderboard(leaderboardReponse);
// setTtsLeaderboard(leaderboardReponse.tts_leaderboard);
// setW2lLeaderboard(leaderboardReponse.w2l_leaderboard);
// } else if (GetLeaderboardIsErr(leaderboardReponse)) {
// switch(leaderboardReponse) {
// // TODO: There's an issue with the queries not returning before the deadline.
// // I should add a Redis TTL cache to store the results and an async job to warm the cache.
// case LeaderboardLookupError.NotFound:
// if (retryCount < 3) {
// setTimeout(() => getLeaderboard(), 1000);
// setRetryCount(retryCount+1);
// }
// break;
// }
// }
//}, [retryCount]);
//useEffect(() => {
// getLeaderboard();
//}, [getLeaderboard]);
return (
<div>
<section className="hero is-small">
<div className="hero-body">
<div className="columns is-vcentered">
<div className="column is-one-third">
<div className="mascot">
<img src="/mascot/kitsune_pose4_black_2000.webp" alt="FakeYou's mascot!" />
</div>
</div>
<div className="column">
<p className="title is-1">
Professionally Clone Your Voice
</p>
<p className="subtitle is-3">
(or any voice) for just $70
</p>
</div>
</div>
</div>
</section>
<section className="section">
<div className="container">
<h1 className="title is-2">Want a Custom Voice You Can Use?</h1>
<h1 className="subtitle is-4">For Music, Videos, Twitch Rewards, API, friends, family&hellip; whatever you want!</h1>
<p>
We have an extremely talented staff that will personally handle your voice clone request.
Please help us understand more about your voice and how you want to use it, and we'll be in touch
shortly.
</p>
<br />
<h1 className="title is-3">First, how should we get in touch?</h1>
<div className="field">
<label className="label">Email Address</label>
<div className="control has-icons-left">
<input className="input is-medium is-fullwidth" type="text" placeholder="Email Address" value="" />
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faEnvelope} />
</span>
</div>
<p className="help is-success"></p>
<p className="help is-danger"></p>
</div>
<div className="field">
<label className="label">
Discord Username (Optional, but an alternate way to reach you.)
<br />
</label>
<div className="control has-icons-left">
<input className="input is-medium is-fullwidth" type="text" placeholder="Discord" value="" />
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faEnvelope} />
</span>
</div>
<p className="help">
Don't forget the <em>#0000</em> part of your username!
</p>
<p className="help is-danger"></p>
</div>
<br />
<h1 className="title is-3">How will you use it?</h1>
<p>Click as many as you plan to use!</p>
<br />
<div className="checkbox-block">
<label className="checkbox">
<input type="checkbox" />
&nbsp;For Music (for creating new songs)
</label>
<br />
<label className="checkbox">
<input type="checkbox" />
&nbsp;For Games (because NPCs won't talk by themselves)
</label>
<br />
<label className="checkbox">
<input type="checkbox" />
&nbsp;For Twitch TTS (creating rewards for my stream, helping me engage and monetize)
</label>
<br />
<label className="checkbox">
<input type="checkbox" />
&nbsp;For API use (unlimited use of the FakeYou.com API for anything you want to build)
</label>
<br />
<label className="checkbox">
<input type="checkbox" />
&nbsp;Other (Oooh, now we're curious!)
</label>
</div>
<br />
<div className="field">
<label className="label">Let us know more about your use (optional)</label>
<div className="control has-icons-left">
<input className="input is-medium is-fullwidth" type="text" placeholder="Optional details" value="" />
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faEnvelope} />
</span>
</div>
<p className="help is-success"></p>
<p className="help is-danger"></p>
</div>
<br />
<h1 className="title is-3">Who's voice is this?</h1>
<p>If it's your voice, you'll be able to do anything you want with it. If it's another person's voice, you may have
limits on how you can use it (eg. limits on commercialization.) That doesn't mean we can't help you. Even if you
just want your favorite character so you can make Twitter memes, that's fine!</p>
<br />
<div className="checkbox-block">
<div className="control">
<label className="radio">
<input type="radio" name="answer" />
&nbsp;My own voice
</label>
<br />
<label className="radio">
<input type="radio" name="answer" />
&nbsp;A family member's voice
</label>
<br />
<label className="radio">
<input type="radio" name="answer" />
&nbsp;Another person's voice
</label>
</div>
</div>
<br />
<h1 className="title is-3">How's your audio quality?</h1>
<p>It's okay if you don't have a quality source of audio, but the results are top notch only with a good recording setup.</p>
<br />
<div className="checkbox-block">
<label className="checkbox">
<input type="checkbox" />
&nbsp;I have a good microphone (and I know what a condenser microphone is)
</label>
<br />
<label className="checkbox">
<input type="checkbox" />
&nbsp;I have really good preexisting recordings.
</label>
</div>
<br />
<h1 className="title is-3">Anything else?</h1>
<div className="field">
<label className="label">Do you have any questions for us?</label>
<div className="control">
<textarea className="textarea" placeholder="Optional Questions"></textarea>
</div>
</div>
<div className="field">
<label className="label">Do you have any important notes or details?</label>
<div className="control">
<textarea className="textarea" placeholder="Optional Notes"></textarea>
</div>
</div>
{/*
<p>Once you've linked Twitch with Storyteller, you can add the following page as an <em>OBS Browser Source</em>:</p>
<br />
<div className="field">
<p className="control has-icons-left">
<input className="input is-large" type="text" value={obsUrl} readOnly={true} />
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faDiscord} />
</span>
</p>
</div>
<br />
<a
href={obsUrl}
target="_blank"
rel="noreferrer"
className="button is-large is-info is-fullwidth"
>
Open In New Tab&nbsp;<FontAwesomeIcon icon={faExternalLinkAlt} />
</a>
<br />
<br />
<br />
<h1 className="title is-2">Setup Instructions</h1>
<p>If you're not familiar with OBS or you need a refresher, here's a quick glance at the setup.</p>
<br />
<h1 className="title is-4">Step 1) Click <FontAwesomeIcon icon={faPlus} /> to add a new Browser Source</h1>
<img src="/obs-tutorial/obs-step1.webp" alt="step 1" />
<p>The bottom of OBS should have a plus icon (<FontAwesomeIcon icon={faPlus} />) to add new sources.
You'll want to add a new <strong>Browser Source</strong>.</p>
<br />
<h1 className="title is-4">Step 2) Paste the URL into the configuration window</h1>
<img src="/obs-tutorial/obs-step2.webp" alt="step 2" />
<br />
<p>Remember, the URL is <code>{obsUrl}</code></p>
<br />
<h1 className="title is-4">Step 3) Activate the Page</h1>
<img src="/obs-tutorial/obs-step3.webp" alt="step 3" />
<br />
<br />
<p>Right click the layer and select <em>&ldquo;Interact&rdquo;</em>.
This will let you click the button and activate the service.</p>
<br />
<br />
<h1 className="title is-2">Good to go! <FontAwesomeIcon icon={faTwitch} /></h1>
<p>You can now hide the layer and make it invisible. The audio levels are also independently adjustable.</p>
<br />
<p>Have fun! We'll be back soon with some even more jaw-dropping utilities.</p>
*/}
</div>
</section>
</div>
);
}
export { VoiceCloneRequestPage }