diff --git a/examples/text-to-voice/x-to-voice/app/(default)/actions/actions.ts b/examples/text-to-voice/x-to-voice/app/(default)/actions/actions.ts index bb38189..ad2ff03 100644 --- a/examples/text-to-voice/x-to-voice/app/(default)/actions/actions.ts +++ b/examples/text-to-voice/x-to-voice/app/(default)/actions/actions.ts @@ -22,9 +22,9 @@ const synthesizeRetrieveHumanSchema = z.object({ }); const uploadAudio = async (buffer: Buffer) => { - const fileBlob = new Blob([buffer], { type: 'audio/mpeg' }); + const fileBlob = new Blob([buffer], { type: "audio/mpeg" }); const formData = new FormData(); - formData.append('file', fileBlob, 'audio.mp3'); + formData.append("file", fileBlob, "audio.mp3"); const audioResponse = await fetch( "https://mercury.dev.dream-ai.com/api/v1/audio", { @@ -41,10 +41,9 @@ const uploadAudio = async (buffer: Buffer) => { const uploadImage = async (imageUrl: string) => { const imageResponse = await fetch(imageUrl); - console.log(); const imageBlob = await imageResponse.blob(); const formData = new FormData(); - formData.append('file', imageBlob, 'image.jpg'); + formData.append("file", imageBlob, "image.jpg"); const audioResponse = await fetch( "https://mercury.dev.dream-ai.com/api/v1/portrait", { @@ -89,16 +88,19 @@ export async function getJobStatus(jobId: string) { return status; } -const createCharacter = async ({ voiceBuffer, profilePicture }: { voiceBuffer: Buffer, profilePicture: string }) => { +const createCharacter = async ({ voiceBuffer, profilePicture }: { + voiceBuffer: Buffer, + profilePicture: string +}): Promise => { const [audioData, imageData] = await Promise.all([ await uploadAudio(voiceBuffer), - await uploadImage(profilePicture) + await uploadImage(profilePicture), ]); const voiceUrl = audioData["url"]; const avatarImage = imageData["url"]; - const requestBody = { "audioSource": "audio", voiceUrl, avatarImage, }; + const requestBody = { "audioSource": "audio", voiceUrl, avatarImage }; const statusData = await createVideo(requestBody); - return statusData['jobId']; + return statusData["jobId"]; }; async function getAnalysis(user: XProfile) { @@ -273,10 +275,21 @@ export const synthesizeHumanAction = actionClient ), ]); - const jobId = await createCharacter({ + let jobId = await createCharacter({ voiceBuffer: audioBuffer1, - profilePicture: user.profilePicture - }) + profilePicture: user.profilePicture, + }); + + if (!jobId) { + jobId = await createCharacter({ + voiceBuffer: audioBuffer1, + profilePicture: user.profilePicture, + }); + } + + if (!jobId) { + throw Error("Couldn't create character.") + } const humanSpecimen = humanSpecimenSchema.parse({ user, diff --git a/examples/text-to-voice/x-to-voice/app/(default)/layout.tsx b/examples/text-to-voice/x-to-voice/app/(default)/layout.tsx index 8fbe345..b8ea823 100644 --- a/examples/text-to-voice/x-to-voice/app/(default)/layout.tsx +++ b/examples/text-to-voice/x-to-voice/app/(default)/layout.tsx @@ -7,6 +7,7 @@ import { Analytics } from "@vercel/analytics/react"; import { BackgroundWave } from "@/components/background-wave"; import Link from "next/link"; import { Button } from "@/components/ui/button"; +import { SpeedInsights } from "@vercel/speed-insights/next"; export const maxDuration = 60; // Applies to the actions @@ -23,54 +24,66 @@ const geistMono = localFont({ export const metadata: Metadata = { title: "X to Voice | ElevenLabs", - description: "Analyze your X profile to generate a unique voice using ElevenLabs' new Voice Design feature", + description: + "Analyze your X profile to generate a unique voice using ElevenLabs' new Voice Design feature", }; -export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { +export default function RootLayout({ + children, +}: Readonly<{ children: React.ReactNode }>) { return ( - - - -
- {children} - -
- - - +
+ + + +
+
+ + + + + + +
+ +
+ {children} + +
+ + + + ); } diff --git a/examples/text-to-voice/x-to-voice/components/avatar-player.tsx b/examples/text-to-voice/x-to-voice/components/avatar-player.tsx index 18d49ae..3aa2604 100644 --- a/examples/text-to-voice/x-to-voice/components/avatar-player.tsx +++ b/examples/text-to-voice/x-to-voice/components/avatar-player.tsx @@ -91,7 +91,7 @@ export function AvatarPlayer({ jobId }: { setVideoUrl(data.videoUrl); setIsLoading(false); } catch { - intervalId = window.setTimeout(fetchCharacter, 2000); + intervalId = window.setTimeout(fetchCharacter, 4000); } } diff --git a/examples/text-to-voice/x-to-voice/components/share-button.tsx b/examples/text-to-voice/x-to-voice/components/share-button.tsx index f4fb4b2..eb43093 100644 --- a/examples/text-to-voice/x-to-voice/components/share-button.tsx +++ b/examples/text-to-voice/x-to-voice/components/share-button.tsx @@ -14,7 +14,8 @@ function XIcon({ className }: { className: string }) { ); } -export function ShareOnXButton({ shareText }: { shareText: string }) { +export function ShareOnXButton() { + const shareText = "This is what I would sound like based on my X posts using the @elevenlabsio Voice Designer\n\nTry it yourself on xtovoice.com\n\n#xtovoice\n\n" function share() { const url = window.location.href; window.open( diff --git a/examples/text-to-voice/x-to-voice/components/specimen-card.tsx b/examples/text-to-voice/x-to-voice/components/specimen-card.tsx index 2e7a9d7..577a1db 100644 --- a/examples/text-to-voice/x-to-voice/components/specimen-card.tsx +++ b/examples/text-to-voice/x-to-voice/components/specimen-card.tsx @@ -68,9 +68,7 @@ export async function SpecimenCard({ humanSpecimen }: { humanSpecimen: HumanSpec
- +
@@ -79,9 +77,7 @@ export async function SpecimenCard({ humanSpecimen }: { humanSpecimen: HumanSpec
- +
diff --git a/examples/text-to-voice/x-to-voice/package.json b/examples/text-to-voice/x-to-voice/package.json index cfc2a2c..31b4c49 100644 --- a/examples/text-to-voice/x-to-voice/package.json +++ b/examples/text-to-voice/x-to-voice/package.json @@ -19,6 +19,7 @@ "@upstash/redis": "^1.34.3", "@vercel/analytics": "^1.3.1", "@vercel/blob": "^0.25.1", + "@vercel/speed-insights": "^1.0.14", "apify-client": "^2.9.7", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", diff --git a/examples/text-to-voice/x-to-voice/pnpm-lock.yaml b/examples/text-to-voice/x-to-voice/pnpm-lock.yaml index 269a9e1..31b391b 100644 --- a/examples/text-to-voice/x-to-voice/pnpm-lock.yaml +++ b/examples/text-to-voice/x-to-voice/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: '@vercel/blob': specifier: ^0.25.1 version: 0.25.1 + '@vercel/speed-insights': + specifier: ^1.0.14 + version: 1.0.14(next@15.0.0(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) apify-client: specifier: ^2.9.7 version: 2.9.7 @@ -708,6 +711,29 @@ packages: resolution: {integrity: sha512-JqnDCGcoDH2gDF5Qgp5RGcDfrdR4IoOEnpS7CiDE15pw25/m1xE0CusjeZcjiBVBnLrLJCDuA9Ts77etOoCOeQ==} engines: {node: '>=16.14'} + '@vercel/speed-insights@1.0.14': + resolution: {integrity: sha512-env1BkPddz1UaEZwBL4GmfRksMi2LbiYaKuoxMQjfLk83aEh7kkWMukkUhpQVs717NE6nnD+1+KO85GZHOZ4nQ==} + peerDependencies: + '@sveltejs/kit': ^1 || ^2 + next: '>= 13' + react: ^18 || ^19 || ^19.0.0-rc + svelte: '>= 4' + vue: ^3 + vue-router: ^4 + peerDependenciesMeta: + '@sveltejs/kit': + optional: true + next: + optional: true + react: + optional: true + svelte: + optional: true + vue: + optional: true + vue-router: + optional: true + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -2741,6 +2767,11 @@ snapshots: is-buffer: 2.0.5 undici: 5.28.4 + '@vercel/speed-insights@1.0.14(next@15.0.0(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020)': + optionalDependencies: + next: 15.0.0(react-dom@19.0.0-rc-65a56d0e-20241020(react@19.0.0-rc-65a56d0e-20241020))(react@19.0.0-rc-65a56d0e-20241020) + react: 19.0.0-rc-65a56d0e-20241020 + abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -3171,8 +3202,8 @@ snapshots: '@typescript-eslint/parser': 8.11.0(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.1(eslint@8.57.1) eslint-plugin-react: 7.37.1(eslint@8.57.1) eslint-plugin-react-hooks: 5.0.0(eslint@8.57.1) @@ -3191,37 +3222,37 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1): + eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.3.7 enhanced-resolve: 5.17.1 eslint: 8.57.1 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 is-glob: 4.0.3 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.11.0(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -3232,7 +3263,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.11.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3