https://www.ai-outpainting.com
網站首頁
價格頁面
部落格列表
圖片編輯
1.基於nextjs 14 和tailwindcss3 開發的AI擴圖網站,網址:https://www.ai-outpainting.com/
2.網站需配合後端AI模型使用。後端模型需要自行搭建。
模型位址:https://huggingface.co/spaces/fffiloni/diffusers-image-outpaint
3.國際化採用lingui實現,這個對比next-intl 的好處是不需要為每個文案生成一個key,它會通過命令提取文案生成多語言文件。之後基於多語言文件做翻譯
4.專案編寫了一些自動化腳本,如自動翻譯國際化內容,自動翻譯部落格內容。這些都需要在有需要的時候手動運行
5.專案依賴資料庫、cloudfare r2 儲存、Google登入所需的參數、paypal支付參數,這些參數都配置在.env和.env.production檔案當中。
6.使用next-auth 整合google登入。本地開發時如果需要google登錄,需要修改一些原始碼才可以,不然會報錯。具體修改內容請見下方說明
7.整合了paypal、stripe支付。在本地開發使用的時沙盒環境,正式環境需要配置正式的paypal參數到.env.production檔案當中
8.目前項目呼叫AI模型使用的方式大致如下:
將處理結果上傳到cloudfare r2 存儲,並調用當前網站的訂單狀態更新回調地址
將處理結果同時傳送給MQ隊列,由MQ隊列管理器服務推送給前端,前端接收到處理結果後,將結果展示到前端頁面
前端發起請求創建訂單,攜帶訂單號碼和當前網站訂單狀態更新回調地址,調用MQ隊列管理器服務(這個是一個python開發的微服務,暫時沒空整理代碼)
發起一個SSE請求到MQ佇列管理服務後端,持續等待MQ佇列管理器服務處理完成,並傳回結果
後端MQ隊列管理器服務接收到請求後,直接將訂單資訊提交給MQ隊列
GPU伺服器監聽MQ佇列,取得到訂單資訊後,開始呼叫AI模型處理,處理完成後會做兩件事:
整個過程不涉及網站直接和GPU伺服器通信,都是透過MQ佇列管理器服務來轉發,文件都是透過R2儲存中轉,這樣解決了GPU伺服器和網站的耦合問題,如果訂單量過大可以隨時增加GPU伺服器,而網站不需要做任何調整。
9.整體架構圖如下:
10.另外一種實現方案
將處理結果上傳到cloudfare r2 存儲,並調用當前網站的訂單狀態更新回調地址去更新訂單狀態
前端建立訂單後,頁面透過輪詢方式一直不停的查詢訂單狀態,直到訂單完成。
後端有其他程式定時掃描資料庫,取得到訂單狀態為pending的訂單,取得到訂單資訊後,開始呼叫AI模型進行處理,處理完成後會做兩件事:
11.如果有預算的也可以考慮直接使用runpod 的API服務,就不用自己實現MQ隊列管理器伺服器了,集成它的SDK就可以。
參考程式碼
import runpodSdk, { EndpointCompletedOutput, EndpointIncompleteOutput } from 'runpod-sdk'async function fetchProcessByRunPod(data: any): Promise<EndpointIncompleteOutput | undefined> { // const serverUrl = `${UE_PROCESS_API}/create_docker` // https://docs.runpod.io/serverless/endpoints/job-operations const runpod = runpodSdk("N5Jxxxxxxxxxxxxx"); const endpoint = runpod.endpoint("1zgk5xi3ew77pv"); console.log("start invoke runpod endpoint,data:",data) return endpoint?.run({"input": data, })}
目前專案原始碼如果需要完整使用AI擴圖功能,則需要以上面的方式選擇一種方案,修改app/[lang]/(editor)/editor/view.tsx檔案當中建立訂單和監聽訂單狀態的邏輯! ! !
每次修改頁面有新的內容後,需要執行yarn extract
指令,將新的文案提取到國際化文件當中,並執行yarn translate
指令將文案翻譯為對應語言
如果有新增blog文章也需要執行yarn translate
指令新將會增加的部落格內容翻譯為對應語言
翻譯涉及到呼叫api,需要先申請到api key,然後修改scripts/openai-chat.js 當中的api key
如果需要新增或減少多語言內容,則需要修改framework/locale/locale.ts framework/locale/localeConfig.js framework/locale/messagesLoader.ts 這三個文件
直接使用node scripts/generator-website.js 指令產生網站內容(這個指令會產生與指定關鍵字相關的文案、TDK、部落格標題)
需要先修改關鍵字和描述,然後再執行指令
// 網站關鍵字 const keyword = 'extend image ai' // 網站該要描述 const description = '利用AI技術實現對圖片進行擴展,在保證原始圖片不變的前提下,擴展四周的內容,且能與原始圖片保持內容延續性
修改config/site.ts當中的設定訊息
將自己的logo favicon.ico 放到public/目錄下,直接取代原文件
修改public/sitemap.xml 當中的域名
修改.env和.env.production當中的配置信息,具體修改要求查看註釋
目前專案採用prisma作為ORM框架,表格結構宣告在schema.prisma檔案當中,第一次使用需要執行下列指令
// 這個指令會根據表結構宣告產生資料庫表,並初始化表格資料。如果有新的表格欄位更新都需要執行目前指令 yarn pg:migrate // 其他操作指令建議直接看prisma官方文檔
網站的配色資訊存放在tailwind.config.ts檔案當中,若需要修改配色,直接修改tailwind.config.ts檔案當中的內容
將程式碼提交到github.com然後使用vercel關聯這個程式碼倉庫部署即可,具體流程參考相關文件。
【2024-10-19】 解決啟動時提示Error: ENOENT: no such file or directory xxx/.next/fallback-build-manifest.json
問題,透過固定"@lingui/swc-plugin": "4.0.8" ,版本解決。刪除本機node_modules目錄,重新安裝依賴解決。
增加Google 登入設定參考截圖
【2024-10-20】 解決啟動時提示Error: Cannot find module 'canvas'
問題,透過加入webpack ignore plugin 解決。優化多語言檔案載入方式。
1.純tailwindcss程式碼組件網站
可以從網站上直接複製某些現成的元件程式碼完全基於tw實現
2.組件化UI 框架-nextui.org
提供基於封裝好的組件直接使用
3.icon組件-react-icons
提供多套默認icon圖示可以直接用
4.Pricing頁面生成
shipixen
5.國際化
動態產生國際化文件
6.MDX博客
基於MDX生成部落格內容
7.Google Auth 配置中心
設定Google登入所需的參數
在目前專案開發環境下使用自訂代理位址,解決本機無法呼叫google.com的問題。具體配置請參考程式碼config/auth-config.ts。生產環境不受影響
https://www.prisma.io/docs/orm/more/help-and-troubleshooting/help-articles/vercel-caching-issue
點擊google登入時,頁面提示There is a problem with the server configuration.
,後端提示[auth][error] OperationProcessingError: "response" body "issuer" property does not match the expected value
錯誤,如下修改
修改node_modules/@auth/core/node_modules/oauth4webapi/build/index.js 或node_modules/oauth4webapi/dist/index.js文件
修改後需手動刪除.next目錄,並重新編譯
1034 或1003 或1237 行(不同版本可能不一樣),註解拋出的異常有些新版本不一定是這一行,可以參考下面的點找到這個報錯訊息,然後註解掉
function validateIssuer(expected, result) { if (result.claims.iss !== expected) {// throw new OPE('unexpected JWT "iss" (issuer) claim value'); } return result;}
250或238行(不同版本可能不一樣),註解拋出的例外
if (new URL(json.issuer).href !== expectedIssuerIdentifier.href) { // throw new OPE('"response" body "issuer" does not match "expectedIssuer"');}
修改後需手動刪除.next目錄,並重新執行run dev
在scripts/add-word-locale.js中修改要調整字詞密度的語言程式碼和目標字
cd scripts/ 目錄下執行指令: bun run add-word-locale.js
或node add-word-locale.js
本專案採用MIT開源協議,請遵守協議內容
如果你願意的話,請幫我的網站留一個連結:https://www.ai-outpainting.com/ 非常感謝!
如果專案對你有幫助,請給個star,非常感謝!
有技術問題歡迎加入微信交流:fafafa-ai
小廣告:目前ai-outpainting網站,接受付費提交外鏈,有需要的朋友可以聯絡我。