-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e99137d
Showing
34 changed files
with
9,036 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Rename this file to .env.local and add your fal credentials | ||
# Visit https://fal.ai to get started | ||
FAL_KEY="FAL_KEY_ID:FAL_KEY_SECRET" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.yarn/install-state.gz | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
## Lightning Fast SDXL API demo by fal.ai | ||
|
||
This application is a sample of the SDXL Lightning API [https://fal.ai/models/stable-diffusion-xl-lightning]. It also shows the `fal.realtime` client in action. | ||
|
||
### Prerequisites | ||
|
||
1. [Fal AI](https://fal.ai/) API key (for model access) | ||
|
||
### Getting started | ||
|
||
1. Add the `FAL_KEY` to your `.env.local` file. | ||
2. Run | ||
```sh | ||
npm run dev | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { route } from "@fal-ai/serverless-proxy/nextjs"; | ||
import { type NextRequest } from "next/server"; | ||
|
||
const URL_ALLOW_LIST = ["https://rest.alpha.fal.ai/tokens/"]; | ||
|
||
export const POST = (req: NextRequest) => { | ||
const url = req.headers.get("x-fal-target-url"); | ||
if (!url) { | ||
return new Response("Not found", { status: 404 }); | ||
} | ||
|
||
if (!URL_ALLOW_LIST.includes(url)) { | ||
return new Response("Not allowed", { status: 403 }); | ||
} | ||
|
||
const appCheckCookie = req.cookies.get("fal-app"); | ||
if (!appCheckCookie || !appCheckCookie.value) { | ||
return new Response("Not allowed", { status: 403 }); | ||
} | ||
|
||
return route.POST(req); | ||
}; | ||
|
||
export const GET = (req: NextRequest) => { | ||
return route.GET(req); | ||
}; |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
@tailwind base; | ||
@tailwind components; | ||
@tailwind utilities; | ||
|
||
::-webkit-scrollbar { | ||
width: 0; | ||
background-color: transparent; | ||
} | ||
|
||
@layer base { | ||
:root { | ||
--background: 0 0% 100%; | ||
--foreground: 240 10% 3.9%; | ||
--card: 0 0% 100%; | ||
--card-foreground: 240 10% 3.9%; | ||
--popover: 0 0% 100%; | ||
--popover-foreground: 240 10% 3.9%; | ||
--primary: 240 5.9% 10%; | ||
--primary-foreground: 0 0% 98%; | ||
--secondary: 240 4.8% 95.9%; | ||
--secondary-foreground: 240 5.9% 10%; | ||
--muted: 240 4.8% 95.9%; | ||
--muted-foreground: 240 3.8% 46.1%; | ||
--accent: 240 4.8% 95.9%; | ||
--accent-foreground: 240 5.9% 10%; | ||
--destructive: 0 84.2% 60.2%; | ||
--destructive-foreground: 0 0% 98%; | ||
--border: 240 5.9% 90%; | ||
--input: 240 5.9% 90%; | ||
--ring: 240 5.9% 10%; | ||
--radius: 0.3rem; | ||
} | ||
|
||
.dark { | ||
--background: 240 10% 3.9%; | ||
--foreground: 0 0% 98%; | ||
--card: 240 10% 3.9%; | ||
--card-foreground: 0 0% 98%; | ||
--popover: 240 10% 3.9%; | ||
--popover-foreground: 0 0% 98%; | ||
--primary: 0 0% 98%; | ||
--primary-foreground: 240 5.9% 10%; | ||
--secondary: 240 3.7% 15.9%; | ||
--secondary-foreground: 0 0% 98%; | ||
--muted: 240 3.7% 15.9%; | ||
--muted-foreground: 240 5% 64.9%; | ||
--accent: 240 3.7% 15.9%; | ||
--accent-foreground: 0 0% 98%; | ||
--destructive: 0 62.8% 30.6%; | ||
--destructive-foreground: 0 0% 98%; | ||
--border: 240 3.7% 15.9%; | ||
--input: 240 3.7% 15.9%; | ||
--ring: 240 4.9% 83.9%; | ||
} | ||
} | ||
|
||
@layer base { | ||
* { | ||
@apply border-border; | ||
} | ||
body { | ||
@apply bg-background text-foreground; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import type { Metadata } from "next"; | ||
import { Inter } from "next/font/google"; | ||
import "./globals.css"; | ||
import { Nav } from "@/components/nav"; | ||
import { ThemeProvider } from "@/components/theme-provider"; | ||
import { Analytics } from "@vercel/analytics/react"; | ||
|
||
const inter = Inter({ subsets: ["latin"] }); | ||
|
||
export const metadata: Metadata = { | ||
title: "SDXL Lightning - by fal.ai", | ||
description: "Lightning fast SDXL API demo by fal.ai", | ||
authors: [{ name: "fal.ai", url: "https://fal.ai" }], | ||
metadataBase: new URL("https://fastsdxl.ai"), | ||
openGraph: { | ||
images: "/og_thumbnail.jpeg", | ||
}, | ||
}; | ||
|
||
export default function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
return ( | ||
<html lang="en" suppressHydrationWarning> | ||
<body | ||
className={inter.className} | ||
style={{ | ||
display: "flex", | ||
flex: 1, | ||
flexDirection: "column", | ||
height: "100vh", | ||
}} | ||
> | ||
<Analytics /> | ||
<ThemeProvider | ||
attribute="class" | ||
defaultTheme="system" | ||
enableSystem | ||
disableTransitionOnChange | ||
> | ||
<Nav /> | ||
{children} | ||
</ThemeProvider> | ||
</body> | ||
</html> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
"use client"; | ||
|
||
/* eslint-disable @next/next/no-img-element */ | ||
/* eslint-disable @next/next/no-html-link-for-pages */ | ||
import * as fal from "@fal-ai/serverless-client"; | ||
import { useEffect, useRef, useState } from "react"; | ||
import { Input } from "@/components/ui/input"; | ||
import { ModelIcon } from "@/components/icons/model-icon"; | ||
import Link from "next/link"; | ||
|
||
const DEFAULT_PROMPT = | ||
"A cinematic shot of a baby raccoon wearing an intricate italian priest robe"; | ||
|
||
function randomSeed() { | ||
return Math.floor(Math.random() * 10000000).toFixed(0); | ||
} | ||
|
||
fal.config({ | ||
proxyUrl: "/api/proxy", | ||
}); | ||
|
||
const INPUT_DEFAULTS = { | ||
_force_msgpack: new Uint8Array([]), | ||
enable_safety_checker: true, | ||
image_size: "square_hd", | ||
sync_mode: true, | ||
num_images: 1, | ||
num_inference_steps: "2", | ||
}; | ||
|
||
export default function Lightning() { | ||
const [image, setImage] = useState<null | string>(null); | ||
const [prompt, setPrompt] = useState<string>(DEFAULT_PROMPT); | ||
const [seed, setSeed] = useState<string>(randomSeed()); | ||
const [inferenceTime, setInferenceTime] = useState<number>(NaN); | ||
|
||
const connection = fal.realtime.connect("fal-ai/fast-lightning-sdxl", { | ||
connectionKey: "lightning-sdxl", | ||
throttleInterval: 64, | ||
onResult: (result) => { | ||
const blob = new Blob([result.images[0].content], { type: "image/jpeg" }); | ||
setImage(URL.createObjectURL(blob)); | ||
setInferenceTime(result.timings.inference); | ||
}, | ||
}); | ||
|
||
const timer = useRef<any | undefined>(undefined); | ||
|
||
const handleOnChange = async (prompt: string) => { | ||
if (timer.current) { | ||
clearTimeout(timer.current); | ||
} | ||
setPrompt(prompt); | ||
const input = { | ||
...INPUT_DEFAULTS, | ||
prompt: prompt, | ||
seed: seed ? Number(seed) : Number(randomSeed()), | ||
}; | ||
connection.send(input); | ||
timer.current = setTimeout(() => { | ||
connection.send({ ...input, num_inference_steps: "4" }); | ||
}, 500); | ||
}; | ||
|
||
useEffect(() => { | ||
if (typeof window !== "undefined") { | ||
window.document.cookie = "fal-app=true; path=/; samesite=strict; secure;"; | ||
} | ||
// initial image | ||
connection.send({ | ||
...INPUT_DEFAULTS, | ||
num_inference_steps: "4", | ||
prompt: prompt, | ||
seed: seed ? Number(seed) : Number(randomSeed()), | ||
}); | ||
}, []); | ||
|
||
return ( | ||
<main> | ||
<div className="container py-4 px-1.5 space-y-4 lg:space-y-8 mx-auto"> | ||
<div className="flex flex-col space-y-2"> | ||
<div className="flex flex-col max-md:space-y-4 md:flex-row md:space-x-4"> | ||
<div className="flex-1 space-y-1"> | ||
<label>Prompt</label> | ||
<Input | ||
onChange={(e) => { | ||
handleOnChange(e.target.value); | ||
}} | ||
className="font-light w-full" | ||
placeholder="Type something..." | ||
value={prompt} | ||
/> | ||
</div> | ||
<div className="space-y-1"> | ||
<label>Seed</label> | ||
<Input | ||
onChange={(e) => { | ||
setSeed(e.target.value); | ||
handleOnChange(prompt); | ||
}} | ||
className="font-light w-full" | ||
placeholder="random" | ||
type="number" | ||
value={seed} | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
<div className="flex flex-col space-y-6 lg:flex-row lg:space-y-0"> | ||
<div className="flex-1 flex-col flex items-center justify-center"> | ||
{image && inferenceTime && ( | ||
<div className="flex flex-row space-x-1"> | ||
<span>inference time</span> | ||
<strong> | ||
{inferenceTime | ||
? `${(inferenceTime * 1000).toFixed(0)}ms` | ||
: `n/a`} | ||
</strong> | ||
</div> | ||
)} | ||
<div className="min-h-[512px] max-w-fit"> | ||
{image && ( | ||
<img id="imageDisplay" src={image} alt="Dynamic Image" /> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div className="container flex flex-col items-center justify-center my-4"> | ||
<p className="text-sm text-base-content/70 py-4 text-center"> | ||
This playground is hosted on{" "} | ||
<strong> | ||
<a href="https://fal.ai" className="underline" target="_blank"> | ||
fal.ai | ||
</a> | ||
</strong>{" "} | ||
and is for demonstration purposes only. | ||
</p> | ||
<div className="flex flex-row items-center space-x-2"> | ||
<span className="text-xs font-mono">powered by</span> | ||
<Link href="https://fal.ai" target="_blank"> | ||
<ModelIcon /> | ||
</Link> | ||
</div> | ||
</div> | ||
</main> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"$schema": "https://ui.shadcn.com/schema.json", | ||
"style": "new-york", | ||
"rsc": true, | ||
"tsx": true, | ||
"tailwind": { | ||
"config": "tailwind.config.js", | ||
"css": "app/globals.css", | ||
"baseColor": "zinc", | ||
"cssVariables": true | ||
}, | ||
"aliases": { | ||
"components": "@/components", | ||
"utils": "@/lib/utils" | ||
} | ||
} |
Oops, something went wrong.