Skip to content

Instantly share code, notes, and snippets.

@dabit3
Created December 1, 2023 22:28
Show Gist options
  • Save dabit3/f48be98178aa5b0a7d0d6149971b77be to your computer and use it in GitHub Desktop.
Save dabit3/f48be98178aa5b0a7d0d6149971b77be to your computer and use it in GitHub Desktop.
Fal + Next.js Real Time with Websockets
'use client'
import { useState } from 'react'
import { Input } from '@/components/ui/input'
import * as fal from "@fal-ai/serverless-client";
import { Excalidraw, exportToBlob } from "@excalidraw/excalidraw";
import Image from 'next/image'
fal.config({
proxyUrl: "/api/fal/proxy",
})
function randomSeed(): number {
const multipliers = [2342534, 1235392, 875441, 102321];
const multiplier =
multipliers[Math.floor(Math.random() * multipliers.length)];
return Math.floor(Math.random() * multiplier);
}
const seed = randomSeed().toFixed(0)
export default function Home() {
const [input, setInput] = useState('A cinematic shot of a baby raccoon wearing an intricate italian priest robe')
const [image, setImage] = useState(null)
const [localImage, setLocalImage] = useState(null)
const [excalidrawAPI, setExcalidrawAPI] = useState<any>(null)
const [_appState, setAppState] = useState<any>(null)
const { send } = fal.realtime.connect('110602490-sdxl-turbo-realtime', {
connectionKey: 'realtime-demo-test-two',
clientOnly: true,
onResult(result) {
if (result.error) return
setImage(() => result.images[0].url)
}
})
async function getDataUrl() {
const elements = excalidrawAPI.getSceneElements()
if (!elements || !elements.length) {
return
}
const blob = await exportToBlob({
elements,
appState: {
..._appState,
exportWithDarkMode: false,
},
files: excalidrawAPI.getFiles(),
getDimensions: () => { return {width: 350, height: 350}}
})
let dataUrl = await new Promise(r => {let a=new FileReader(); a.onload=r; a.readAsDataURL(blob)}).then(e => e.target.result)
return dataUrl
}
return (
<main className="p-24">
<p className="text-xl mb-2">Prompt</p>
<Input
className='border rounded'
value={input}
onChange={(e) => {
setInput(e.target.value)
}}
/>
<div className='flex'>
<div style={{ width: '500px', height: "500px" }}>
<Excalidraw
excalidrawAPI={(api)=> setExcalidrawAPI(api)}
onChange={
async (_, appState) => {
let dataUrl = await getDataUrl()
setLocalImage(dataUrl)
if (dataUrl !== localImage) {
send({
prompt: input,
sync_mode: true,
image_url: dataUrl,
seed,
strength: .99,
})
}
setAppState(appState)
}
}
/>
</div>
{
image && (
<Image
className='mt-6'
src={image}
width={500}
height={500}
alt='fal image'
/>
)
}
</div>
</main>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment